| //===-- IRForTarget.h ---------------------------------------------*- C++ | |
| //-*-===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #ifndef LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_IRFORTARGET_H | |
| #define LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_IRFORTARGET_H | |
| #include "lldb/Symbol/TaggedASTType.h" | |
| #include "lldb/Utility/ConstString.h" | |
| #include "lldb/Utility/Status.h" | |
| #include "lldb/Utility/Stream.h" | |
| #include "lldb/Utility/StreamString.h" | |
| #include "lldb/lldb-public.h" | |
| #include "llvm/IR/DerivedTypes.h" | |
| #include "llvm/Pass.h" | |
| #include <functional> | |
| #include <map> | |
| namespace llvm { | |
| class BasicBlock; | |
| class CallInst; | |
| class Constant; | |
| class ConstantInt; | |
| class Function; | |
| class GlobalValue; | |
| class GlobalVariable; | |
| class Instruction; | |
| class Module; | |
| class StoreInst; | |
| class DataLayout; | |
| class Value; | |
| } | |
| namespace clang { | |
| class NamedDecl; | |
| } | |
| namespace lldb_private { | |
| class ClangExpressionDeclMap; | |
| class IRExecutionUnit; | |
| class IRMemoryMap; | |
| } | |
| /// \class IRForTarget IRForTarget.h "lldb/Expression/IRForTarget.h" | |
| /// Transforms the IR for a function to run in the target | |
| /// | |
| /// Once an expression has been parsed and converted to IR, it can run in two | |
| /// contexts: interpreted by LLDB as a DWARF location expression, or compiled | |
| /// by the JIT and inserted into the target process for execution. | |
| /// | |
| /// IRForTarget makes the second possible, by applying a series of | |
| /// transformations to the IR which make it relocatable. These | |
| /// transformations are discussed in more detail next to their relevant | |
| /// functions. | |
| class IRForTarget { | |
| public: | |
| enum class LookupResult { Success, Fail, Ignore }; | |
| /// Constructor | |
| /// | |
| /// \param[in] decl_map | |
| /// The list of externally-referenced variables for the expression, | |
| /// for use in looking up globals and allocating the argument | |
| /// struct. See the documentation for ClangExpressionDeclMap. | |
| /// | |
| /// \param[in] resolve_vars | |
| /// True if the external variable references (including persistent | |
| /// variables) should be resolved. If not, only external functions | |
| /// are resolved. | |
| /// | |
| /// \param[in] execution_unit | |
| /// The holder for raw data associated with the expression. | |
| /// | |
| /// \param[in] error_stream | |
| /// If non-NULL, a stream on which errors can be printed. | |
| /// | |
| /// \param[in] func_name | |
| /// The name of the function to prepare for execution in the target. | |
| IRForTarget(lldb_private::ClangExpressionDeclMap *decl_map, bool resolve_vars, | |
| lldb_private::IRExecutionUnit &execution_unit, | |
| lldb_private::Stream &error_stream, | |
| lldb_private::ExecutionPolicy execution_policy, | |
| const char *func_name = "$__lldb_expr"); | |
| /// Run this IR transformer on a single module | |
| /// | |
| /// Implementation of the llvm::ModulePass::runOnModule() function. | |
| /// | |
| /// \param[in] llvm_module | |
| /// The module to run on. This module is searched for the function | |
| /// $__lldb_expr, and that function is passed to the passes one by | |
| /// one. | |
| /// | |
| /// \return | |
| /// True on success; false otherwise | |
| bool runOnModule(llvm::Module &llvm_module); | |
| private: | |
| /// Ensures that the current function's linkage is set to external. | |
| /// Otherwise the JIT may not return an address for it. | |
| /// | |
| /// \param[in] llvm_function | |
| /// The function whose linkage is to be fixed. | |
| /// | |
| /// \return | |
| /// True on success; false otherwise. | |
| bool FixFunctionLinkage(llvm::Function &llvm_function); | |
| /// A function-level pass to take the generated global value | |
| /// $__lldb_expr_result and make it into a persistent variable. Also see | |
| /// ASTResultSynthesizer. | |
| /// Find the NamedDecl corresponding to a Value. This interface is exposed | |
| /// for the IR interpreter. | |
| /// | |
| /// \param[in] global_val | |
| /// The global entity to search for | |
| /// | |
| /// \param[in] module | |
| /// The module containing metadata to search | |
| /// | |
| /// \return | |
| /// The corresponding variable declaration | |
| public: | |
| static clang::NamedDecl *DeclForGlobal(const llvm::GlobalValue *global_val, | |
| llvm::Module *module); | |
| private: | |
| clang::NamedDecl *DeclForGlobal(llvm::GlobalValue *global); | |
| /// The top-level pass implementation | |
| /// | |
| /// \param[in] llvm_function | |
| /// The function currently being processed. | |
| /// | |
| /// \return | |
| /// True on success; false otherwise | |
| bool CreateResultVariable(llvm::Function &llvm_function); | |
| /// A module-level pass to find Objective-C constant strings and | |
| /// transform them to calls to CFStringCreateWithBytes. | |
| /// Rewrite a single Objective-C constant string. | |
| /// | |
| /// \param[in] NSStr | |
| /// The constant NSString to be transformed | |
| /// | |
| /// \param[in] CStr | |
| /// The constant C string inside the NSString. This will be | |
| /// passed as the bytes argument to CFStringCreateWithBytes. | |
| /// | |
| /// \return | |
| /// True on success; false otherwise | |
| bool RewriteObjCConstString(llvm::GlobalVariable *NSStr, | |
| llvm::GlobalVariable *CStr); | |
| /// The top-level pass implementation | |
| /// | |
| /// \return | |
| /// True on success; false otherwise | |
| bool RewriteObjCConstStrings(); | |
| /// A basic block-level pass to find all Objective-C method calls and | |
| /// rewrite them to use sel_registerName instead of statically allocated | |
| /// selectors. The reason is that the selectors are created on the | |
| /// assumption that the Objective-C runtime will scan the appropriate | |
| /// section and prepare them. This doesn't happen when code is copied into | |
| /// the target, though, and there's no easy way to induce the runtime to | |
| /// scan them. So instead we get our selectors from sel_registerName. | |
| /// Replace a single selector reference | |
| /// | |
| /// \param[in] selector_load | |
| /// The load of the statically-allocated selector. | |
| /// | |
| /// \return | |
| /// True on success; false otherwise | |
| bool RewriteObjCSelector(llvm::Instruction *selector_load); | |
| /// The top-level pass implementation | |
| /// | |
| /// \param[in] basic_block | |
| /// The basic block currently being processed. | |
| /// | |
| /// \return | |
| /// True on success; false otherwise | |
| bool RewriteObjCSelectors(llvm::BasicBlock &basic_block); | |
| /// A basic block-level pass to find all newly-declared persistent | |
| /// variables and register them with the ClangExprDeclMap. This allows them | |
| /// to be materialized and dematerialized like normal external variables. | |
| /// Before transformation, these persistent variables look like normal | |
| /// locals, so they have an allocation. This pass excises these allocations | |
| /// and makes references look like external references where they will be | |
| /// resolved -- like all other external references -- by ResolveExternals(). | |
| /// Handle a single allocation of a persistent variable | |
| /// | |
| /// \param[in] persistent_alloc | |
| /// The allocation of the persistent variable. | |
| /// | |
| /// \return | |
| /// True on success; false otherwise | |
| bool RewritePersistentAlloc(llvm::Instruction *persistent_alloc); | |
| /// The top-level pass implementation | |
| /// | |
| /// \param[in] basic_block | |
| /// The basic block currently being processed. | |
| bool RewritePersistentAllocs(llvm::BasicBlock &basic_block); | |
| /// A function-level pass to find all external variables and functions | |
| /// used in the IR. Each found external variable is added to the struct, | |
| /// and each external function is resolved in place, its call replaced with | |
| /// a call to a function pointer whose value is the address of the function | |
| /// in the target process. | |
| /// Handle a single externally-defined variable | |
| /// | |
| /// \param[in] value | |
| /// The variable. | |
| /// | |
| /// \return | |
| /// True on success; false otherwise | |
| bool MaybeHandleVariable(llvm::Value *value); | |
| /// Handle a single externally-defined symbol | |
| /// | |
| /// \param[in] symbol | |
| /// The symbol. | |
| /// | |
| /// \return | |
| /// True on success; false otherwise | |
| bool HandleSymbol(llvm::Value *symbol); | |
| /// Handle a single externally-defined Objective-C class | |
| /// | |
| /// \param[in] classlist_reference | |
| /// The reference, usually "01L_OBJC_CLASSLIST_REFERENCES_$_n" | |
| /// where n (if present) is an index. | |
| /// | |
| /// \return | |
| /// True on success; false otherwise | |
| bool HandleObjCClass(llvm::Value *classlist_reference); | |
| /// Handle all the arguments to a function call | |
| /// | |
| /// \param[in] call_inst | |
| /// The call instruction. | |
| /// | |
| /// \return | |
| /// True on success; false otherwise | |
| bool MaybeHandleCallArguments(llvm::CallInst *call_inst); | |
| /// Resolve variable references in calls to external functions | |
| /// | |
| /// \param[in] basic_block | |
| /// The basic block currently being processed. | |
| /// | |
| /// \return | |
| /// True on success; false otherwise | |
| bool ResolveCalls(llvm::BasicBlock &basic_block); | |
| /// Remove calls to __cxa_atexit, which should never be generated by | |
| /// expressions. | |
| /// | |
| /// \param[in] basic_block | |
| /// The basic block currently being processed. | |
| /// | |
| /// \return | |
| /// True if the scan was successful; false if some operation | |
| /// failed | |
| bool RemoveCXAAtExit(llvm::BasicBlock &basic_block); | |
| /// The top-level pass implementation | |
| /// | |
| /// \param[in] llvm_function | |
| /// The function currently being processed. | |
| /// | |
| /// \return | |
| /// True on success; false otherwise | |
| bool ResolveExternals(llvm::Function &llvm_function); | |
| /// A basic block-level pass to excise guard variables from the code. | |
| /// The result for the function is passed through Clang as a static | |
| /// variable. Static variables normally have guard variables to ensure that | |
| /// they are only initialized once. | |
| /// Rewrite a load to a guard variable to return constant 0. | |
| /// | |
| /// \param[in] guard_load | |
| /// The load instruction to zero out. | |
| void TurnGuardLoadIntoZero(llvm::Instruction *guard_load); | |
| /// The top-level pass implementation | |
| /// | |
| /// \param[in] basic_block | |
| /// The basic block currently being processed. | |
| /// | |
| /// \return | |
| /// True on success; false otherwise | |
| bool RemoveGuards(llvm::BasicBlock &basic_block); | |
| /// A function-level pass to make all external variable references | |
| /// point at the correct offsets from the void* passed into the function. | |
| /// ClangExpressionDeclMap::DoStructLayout() must be called beforehand, so | |
| /// that the offsets are valid. | |
| /// The top-level pass implementation | |
| /// | |
| /// \param[in] llvm_function | |
| /// The function currently being processed. | |
| /// | |
| /// \return | |
| /// True on success; false otherwise | |
| bool ReplaceVariables(llvm::Function &llvm_function); | |
| /// True if external variable references and persistent variable references | |
| /// should be resolved | |
| bool m_resolve_vars; | |
| /// The name of the function to translate | |
| lldb_private::ConstString m_func_name; | |
| /// The name of the result variable ($0, $1, ...) | |
| lldb_private::ConstString m_result_name; | |
| /// The type of the result variable. | |
| lldb_private::TypeFromParser m_result_type; | |
| /// The module being processed, or NULL if that has not been determined yet. | |
| llvm::Module *m_module = nullptr; | |
| /// The target data for the module being processed, or nullptr if there is no | |
| /// module. | |
| const llvm::DataLayout *m_target_data = nullptr; | |
| /// The DeclMap containing the Decls | |
| lldb_private::ClangExpressionDeclMap *m_decl_map; | |
| /// The address of the function CFStringCreateWithBytes, cast to the | |
| /// appropriate function pointer type | |
| llvm::FunctionCallee m_CFStringCreateWithBytes; | |
| /// The address of the function sel_registerName, cast to the appropriate | |
| /// function pointer type. | |
| llvm::FunctionCallee m_sel_registerName; | |
| /// The type of an integer large enough to hold a pointer. | |
| llvm::IntegerType *m_intptr_ty = nullptr; | |
| /// The stream on which errors should be printed. | |
| lldb_private::Stream &m_error_stream; | |
| /// The execution unit containing the IR being created. | |
| lldb_private::IRExecutionUnit &m_execution_unit; | |
| /// True if the function's result in the AST is a pointer (see comments in | |
| /// ASTResultSynthesizer::SynthesizeBodyResult) | |
| bool m_result_is_pointer = false; | |
| lldb_private::ExecutionPolicy m_policy; | |
| class FunctionValueCache { | |
| public: | |
| typedef std::function<llvm::Value *(llvm::Function *)> Maker; | |
| FunctionValueCache(Maker const &maker); | |
| ~FunctionValueCache(); | |
| llvm::Value *GetValue(llvm::Function *function); | |
| private: | |
| Maker const m_maker; | |
| typedef std::map<llvm::Function *, llvm::Value *> FunctionValueMap; | |
| FunctionValueMap m_values; | |
| }; | |
| FunctionValueCache m_entry_instruction_finder; | |
| /// UnfoldConstant operates on a constant [Old] which has just been replaced | |
| /// with a value [New]. We assume that new_value has been properly placed | |
| /// early in the function, in front of the first instruction in the entry | |
| /// basic block [FirstEntryInstruction]. | |
| /// | |
| /// UnfoldConstant reads through the uses of Old and replaces Old in those | |
| /// uses with New. Where those uses are constants, the function generates | |
| /// new instructions to compute the result of the new, non-constant | |
| /// expression and places them before FirstEntryInstruction. These | |
| /// instructions replace the constant uses, so UnfoldConstant calls itself | |
| /// recursively for those. | |
| /// | |
| /// \return | |
| /// True on success; false otherwise | |
| static bool UnfoldConstant(llvm::Constant *old_constant, | |
| llvm::Function *llvm_function, | |
| FunctionValueCache &value_maker, | |
| FunctionValueCache &entry_instruction_finder, | |
| lldb_private::Stream &error_stream); | |
| }; | |
| #endif // LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_IRFORTARGET_H |