diff options
-rw-r--r-- | lldb/include/lldb/Expression/ClangExpressionDeclMap.h | 28 | ||||
-rw-r--r-- | lldb/include/lldb/Expression/ClangExpressionParser.h | 11 | ||||
-rw-r--r-- | lldb/include/lldb/Expression/ClangExpressionVariable.h | 4 | ||||
-rw-r--r-- | lldb/include/lldb/Expression/ClangUserExpression.h | 18 | ||||
-rw-r--r-- | lldb/include/lldb/Expression/IRForTarget.h | 50 | ||||
-rw-r--r-- | lldb/source/Expression/ClangExpressionDeclMap.cpp | 100 | ||||
-rw-r--r-- | lldb/source/Expression/ClangExpressionParser.cpp | 9 | ||||
-rw-r--r-- | lldb/source/Expression/ClangFunction.cpp | 4 | ||||
-rw-r--r-- | lldb/source/Expression/ClangUserExpression.cpp | 21 | ||||
-rw-r--r-- | lldb/source/Expression/ClangUtilityFunction.cpp | 4 | ||||
-rw-r--r-- | lldb/source/Expression/IRForTarget.cpp | 287 | ||||
-rw-r--r-- | lldb/source/Target/Process.cpp | 6 | ||||
-rw-r--r-- | lldb/source/Target/Target.cpp | 1 |
13 files changed, 384 insertions, 159 deletions
diff --git a/lldb/include/lldb/Expression/ClangExpressionDeclMap.h b/lldb/include/lldb/Expression/ClangExpressionDeclMap.h index ebae71dedd7..4aa96d69f9a 100644 --- a/lldb/include/lldb/Expression/ClangExpressionDeclMap.h +++ b/lldb/include/lldb/Expression/ClangExpressionDeclMap.h @@ -127,6 +127,28 @@ public: const llvm::APInt& value); //------------------------------------------------------------------ + /// [Used by IRForTarget] Cast an existing variable given a Decl and + /// a type. + /// + /// @param[in] name + /// The name of the new variable + /// + /// @param[in] decl + /// The Clang variable declaration for the original variable, + /// which must be looked up in the map + /// + /// @param[in] type + /// The desired type of the variable after casting + /// + /// @return + /// The created variable + //------------------------------------------------------------------ + lldb::ClangExpressionVariableSP + BuildCastVariable (const ConstString &name, + clang::VarDecl *decl, + lldb_private::TypeFromParser type); + + //------------------------------------------------------------------ /// [Used by IRForTarget] Add a variable to the list of persistent /// variables for the process. /// @@ -620,7 +642,7 @@ private: /// @return /// The LLDB Variable found, or NULL if none was found. //------------------------------------------------------------------ - Variable * + lldb::VariableSP FindVariableInScope (StackFrame &frame, const ConstString &name, TypeFromUser *type = NULL); @@ -656,7 +678,7 @@ private: //------------------------------------------------------------------ Value * GetVariableValue (ExecutionContext &exe_ctx, - Variable *var, + lldb::VariableSP var, clang::ASTContext *parser_ast_context, TypeFromUser *found_type = NULL, TypeFromParser *parser_type = NULL); @@ -673,7 +695,7 @@ private: //------------------------------------------------------------------ void AddOneVariable (NameSearchContext &context, - Variable *var); + lldb::VariableSP var); //------------------------------------------------------------------ /// Use the NameSearchContext to generate a Decl for the given diff --git a/lldb/include/lldb/Expression/ClangExpressionParser.h b/lldb/include/lldb/Expression/ClangExpressionParser.h index 1625b861721..806e45cbd73 100644 --- a/lldb/include/lldb/Expression/ClangExpressionParser.h +++ b/lldb/include/lldb/Expression/ClangExpressionParser.h @@ -103,9 +103,13 @@ public: /// The execution context to write the function into. /// /// @param[out] const_result - /// If non-NULL, the result of the expression is constant, and the + /// If the result of the expression is constant, and the /// expression has no side effects, this is set to the result of the - /// expression. + /// expression. + /// + /// @param[in] jit_only_if_needed + /// True if the expression must be compiled, regardless of whether a + /// constant result could be extracted from the IR or no. /// /// @return /// An error code indicating the success or failure of the operation. @@ -116,7 +120,8 @@ public: lldb::addr_t &func_addr, lldb::addr_t &func_end, ExecutionContext &exe_ctx, - lldb::ClangExpressionVariableSP *const_result = NULL); + lldb::ClangExpressionVariableSP &const_result, + bool jit_only_if_needed = false); //------------------------------------------------------------------ /// Disassemble the machine code for a JITted function from the target diff --git a/lldb/include/lldb/Expression/ClangExpressionVariable.h b/lldb/include/lldb/Expression/ClangExpressionVariable.h index a1a9debbacd..7f8203e830b 100644 --- a/lldb/include/lldb/Expression/ClangExpressionVariable.h +++ b/lldb/include/lldb/Expression/ClangExpressionVariable.h @@ -97,7 +97,8 @@ public: m_parser_type(), m_named_decl (NULL), m_llvm_value (NULL), - m_lldb_value (NULL) + m_lldb_value (NULL), + m_lldb_var () { } @@ -105,6 +106,7 @@ public: const clang::NamedDecl *m_named_decl; ///< The Decl corresponding to this variable llvm::Value *m_llvm_value; ///< The IR value corresponding to this variable; usually a GlobalValue lldb_private::Value *m_lldb_value; ///< The value found in LLDB for this variable + lldb::VariableSP m_lldb_var; ///< The original variable for this variable private: DISALLOW_COPY_AND_ASSIGN (ParserVars); diff --git a/lldb/include/lldb/Expression/ClangUserExpression.h b/lldb/include/lldb/Expression/ClangUserExpression.h index 12e1d215aaa..e1e320e8169 100644 --- a/lldb/include/lldb/Expression/ClangUserExpression.h +++ b/lldb/include/lldb/Expression/ClangUserExpression.h @@ -85,11 +85,6 @@ public: /// True if the resulting persistent variable should reside in /// target memory, if applicable. /// - /// @param[out] const_result - /// If this is non-NULL, the expression has no side effects, and - /// the expression returns a constant result, then that result - /// is put into this variable. - /// /// @return /// True on success (no errors); false otherwise. //------------------------------------------------------------------ @@ -97,8 +92,7 @@ public: Parse (Stream &error_stream, ExecutionContext &exe_ctx, TypeFromUser desired_type, - bool keep_result_in_memory, - lldb::ClangExpressionVariableSP *const_result = NULL); + bool keep_result_in_memory); //------------------------------------------------------------------ /// Execute the parsed expression @@ -133,7 +127,6 @@ public: Execute (Stream &error_stream, ExecutionContext &exe_ctx, bool discard_on_error, - bool keep_in_memory, ClangUserExpressionSP &shared_ptr_to_me, lldb::ClangExpressionVariableSP &result); @@ -244,10 +237,6 @@ public: /// True if the thread's state should be restored in the case /// of an error. /// - /// @param[in] keep_in_memory - /// True if the resulting persistent variable should reside in - /// target memory, if applicable. - /// /// @param[in] expr_cstr /// A C string containing the expression to be evaluated. /// @@ -264,7 +253,6 @@ public: static ExecutionResults Evaluate (ExecutionContext &exe_ctx, bool discard_on_error, - bool keep_in_memory, const char *expr_cstr, const char *expr_prefix, lldb::ValueObjectSP &result_valobj_sp); @@ -289,13 +277,15 @@ private: TypeFromUser m_desired_type; ///< The type to coerce the expression's result to. If NULL, inferred from the expression. std::auto_ptr<ClangExpressionDeclMap> m_expr_decl_map; ///< The map to use when parsing and materializing the expression. - std::auto_ptr<ClangExpressionVariableList> m_local_variables; ///< The local expression variables, if the expression is DWARF. + std::auto_ptr<ClangExpressionVariableList> m_local_variables; ///< The local expression variables, if the expression is DWARF. std::auto_ptr<StreamString> m_dwarf_opcodes; ///< The DWARF opcodes for the expression. May be NULL. bool m_cplusplus; ///< True if the expression is compiled as a C++ member function (true if it was parsed when exe_ctx was in a C++ method). bool m_objectivec; ///< True if the expression is compiled as an Objective-C method (true if it was parsed when exe_ctx was in an Objective-C method). bool m_needs_object_ptr; ///< True if "this" or "self" must be looked up and passed in. False if the expression doesn't really use them and they can be NULL. bool m_const_object; ///< True if "this" is const. + + lldb::ClangExpressionVariableSP m_const_result; ///< The statically-computed result of the expression. NULL if it could not be computed statically or the expression has side effects. }; } // namespace lldb_private diff --git a/lldb/include/lldb/Expression/IRForTarget.h b/lldb/include/lldb/Expression/IRForTarget.h index 70480d78c45..f78a5896708 100644 --- a/lldb/include/lldb/Expression/IRForTarget.h +++ b/lldb/include/lldb/Expression/IRForTarget.h @@ -21,9 +21,11 @@ namespace llvm { class CallInst; class Constant; class Function; + class GlobalValue; class GlobalVariable; class Instruction; class Module; + class StoreInst; class Value; } @@ -62,10 +64,9 @@ public: /// are resolved. /// /// @param[in] const_result - /// If non-NULL, a shared pointer to a ClangExpressionVariable that - /// is populated with the statically-computed result of the function, - /// if it has no side-effects and the result can be computed - /// statically. + /// This variable is populated with the statically-computed result + /// of the function, if it has no side-effects and the result can + /// be computed statically. /// /// @param[in] error_stream /// If non-NULL, a stream on which errors can be printed. @@ -75,7 +76,7 @@ public: //------------------------------------------------------------------ IRForTarget(lldb_private::ClangExpressionDeclMap *decl_map, bool resolve_vars, - lldb::ClangExpressionVariableSP *const_result, + lldb::ClangExpressionVariableSP &const_result, lldb_private::Stream *error_stream, const char* func_name = "$__lldb_expr"); @@ -153,6 +154,24 @@ private: /// constant, assuming it can be evaluated. The result variable /// will be reset to NULL later if the expression has side effects. /// + /// @param[in] llvm_module + /// The module currently being processed. + /// + /// @param[in] global + /// The global entity to search for + /// + /// @return + /// The corresponding variable declaration + //------------------------------------------------------------------ + clang::NamedDecl * + DeclForGlobal (llvm::Module &llvm_module, + llvm::GlobalValue *global); + + //------------------------------------------------------------------ + /// Set the constant result variable m_const_result to the provided + /// constant, assuming it can be evaluated. The result variable + /// will be reset to NULL later if the expression has side effects. + /// /// @param[in] initializer /// The constant initializer for the variable. /// @@ -161,9 +180,6 @@ private: /// /// @param[in] type /// The Clang type of the result variable. - /// - /// @return - /// True on success; false otherwise //------------------------------------------------------------------ void MaybeSetConstantResult (llvm::Constant *initializer, @@ -171,6 +187,21 @@ private: lldb_private::TypeFromParser type); //------------------------------------------------------------------ + /// If the IR represents a cast of a variable, set m_const_result + /// to the result of the cast. The result variable will be reset to + /// NULL latger if the expression has side effects. + /// + /// @param[in] llvm_module + /// The module currently being processed. + /// + /// @param[in] type + /// The Clang type of the result variable. + //------------------------------------------------------------------ + void + MaybeSetCastResult (llvm::Module &llvm_module, + lldb_private::TypeFromParser type); + + //------------------------------------------------------------------ /// The top-level pass implementation /// /// @param[in] llvm_module @@ -476,10 +507,11 @@ private: lldb_private::ClangExpressionDeclMap *m_decl_map; ///< The DeclMap containing the Decls llvm::Constant *m_CFStringCreateWithBytes; ///< The address of the function CFStringCreateWithBytes, cast to the appropriate function pointer type llvm::Constant *m_sel_registerName; ///< The address of the function sel_registerName, cast to the appropriate function pointer type - lldb::ClangExpressionVariableSP *m_const_result; ///< If non-NULL, this value should be set to the return value of the expression if it is constant and the expression has no side effects + lldb::ClangExpressionVariableSP &m_const_result; ///< This value should be set to the return value of the expression if it is constant and the expression has no side effects lldb_private::Stream *m_error_stream; ///< If non-NULL, the stream on which errors should be printed bool m_has_side_effects; ///< True if the function's result cannot be simply determined statically + llvm::StoreInst *m_result_store; ///< If non-NULL, the store instruction that writes to the result variable. If m_has_side_effects is true, this is NULL. bool m_result_is_pointer; ///< True if the function's result in the AST is a pointer (see comments in ASTResultSynthesizer::SynthesizeBodyResult) private: diff --git a/lldb/source/Expression/ClangExpressionDeclMap.cpp b/lldb/source/Expression/ClangExpressionDeclMap.cpp index 678c175b22b..9e0f67c9c1d 100644 --- a/lldb/source/Expression/ClangExpressionDeclMap.cpp +++ b/lldb/source/Expression/ClangExpressionDeclMap.cpp @@ -139,7 +139,7 @@ ClangExpressionDeclMap::BuildIntegerVariable (const ConstString &name, type.GetASTContext(), type.GetOpaqueQualType()), context); - + if (!m_parser_vars->m_persistent_vars->CreatePersistentVariable (exe_ctx->GetBestExecutionContextScope (), name, user_type, @@ -194,10 +194,81 @@ ClangExpressionDeclMap::BuildIntegerVariable (const ConstString &name, } pvar_sp->m_flags |= ClangExpressionVariable::EVIsFreezeDried; + pvar_sp->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated; + pvar_sp->m_flags |= ClangExpressionVariable::EVNeedsAllocation; return pvar_sp; } +lldb::ClangExpressionVariableSP +ClangExpressionDeclMap::BuildCastVariable (const ConstString &name, + clang::VarDecl *decl, + lldb_private::TypeFromParser type) +{ + assert (m_parser_vars.get()); + + lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + ExecutionContext *exe_ctx = m_parser_vars->m_exe_ctx; + clang::ASTContext *context(exe_ctx->target->GetScratchClangASTContext()->getASTContext()); + + ClangExpressionVariableSP var_sp (m_found_entities.GetVariable(decl)); + + if (!var_sp) + var_sp = m_parser_vars->m_persistent_vars->GetVariable(decl); + + if (!var_sp) + return ClangExpressionVariableSP(); + + TypeFromUser user_type(ClangASTContext::CopyType(context, + type.GetASTContext(), + type.GetOpaqueQualType()), + context); + + TypeFromUser var_type = var_sp->GetTypeFromUser(); + + VariableSP var = FindVariableInScope (*exe_ctx->frame, var_sp->GetName(), &var_type); + + if (!var) + return lldb::ClangExpressionVariableSP(); // but we should handle this; it may be a persistent variable + + ValueObjectSP var_valobj = exe_ctx->frame->GetValueObjectForFrameVariable(var, lldb::eNoDynamicValues); + + if (!var_valobj) + return lldb::ClangExpressionVariableSP(); + + ValueObjectSP var_casted_valobj = var_valobj->CastPointerType(name.GetCString(), user_type); + + if (!var_casted_valobj) + return lldb::ClangExpressionVariableSP(); + + if (log) + { + StreamString my_stream_string; + + ClangASTType::DumpTypeDescription (var_type.GetASTContext(), + var_type.GetOpaqueQualType(), + &my_stream_string); + + + log->Printf("Building cast variable to type: %s", my_stream_string.GetString().c_str()); + } + + ClangExpressionVariableSP pvar_sp = m_parser_vars->m_persistent_vars->CreatePersistentVariable (var_casted_valobj); + + if (!pvar_sp) + return lldb::ClangExpressionVariableSP(); + + if (pvar_sp != m_parser_vars->m_persistent_vars->GetVariable(name)) + return lldb::ClangExpressionVariableSP(); + + pvar_sp->m_flags |= ClangExpressionVariable::EVIsFreezeDried; + pvar_sp->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated; + pvar_sp->m_flags |= ClangExpressionVariable::EVNeedsAllocation; + + return pvar_sp; +} + bool ClangExpressionDeclMap::AddPersistentVariable ( @@ -535,9 +606,9 @@ ClangExpressionDeclMap::GetObjectPointer return false; } - Variable *object_ptr_var = FindVariableInScope (*exe_ctx.frame, - object_name, - (suppress_type_check ? NULL : &m_struct_vars->m_object_pointer_type)); + VariableSP object_ptr_var = FindVariableInScope (*exe_ctx.frame, + object_name, + (suppress_type_check ? NULL : &m_struct_vars->m_object_pointer_type)); if (!object_ptr_var) { @@ -1122,7 +1193,7 @@ ClangExpressionDeclMap::DoMaterializeOnePersistentVariable if (log) log->Printf("Materialized %s into 0x%llx", var_sp->GetName().GetCString(), (uint64_t)mem); } - else if (!var_sp->m_flags & ClangExpressionVariable::EVIsProgramReference) + else if (!(var_sp->m_flags & ClangExpressionVariable::EVIsProgramReference)) { err.SetErrorStringWithFormat("Persistent variables without separate allocations are not currently supported."); return false; @@ -1153,7 +1224,7 @@ ClangExpressionDeclMap::DoMaterializeOneVariable const ConstString &name(expr_var->GetName()); TypeFromUser type(expr_var->GetTypeFromUser()); - Variable *var = FindVariableInScope (*exe_ctx.frame, name, &type); + VariableSP var = FindVariableInScope (*exe_ctx.frame, name, &type); if (!var) { @@ -1495,7 +1566,7 @@ ClangExpressionDeclMap::DoMaterializeOneRegister return true; } -Variable * +lldb::VariableSP ClangExpressionDeclMap::FindVariableInScope ( StackFrame &frame, @@ -1508,7 +1579,7 @@ ClangExpressionDeclMap::FindVariableInScope VariableList *var_list = frame.GetVariableList(true); if (!var_list) - return NULL; + return lldb::VariableSP(); lldb::VariableSP var_sp (var_list->FindVariable(name)); @@ -1543,17 +1614,17 @@ ClangExpressionDeclMap::FindVariableInScope if (type->GetASTContext() == var_sp->GetType()->GetClangAST()) { if (!ClangASTContext::AreTypesSame(type->GetASTContext(), type->GetOpaqueQualType(), var_sp->GetType()->GetClangFullType())) - return NULL; + return lldb::VariableSP(); } else { if (log) log->PutCString("Skipping a candidate variable because of different AST contexts"); - return NULL; + return lldb::VariableSP(); } } - return var_sp.get(); + return var_sp; } // Interface for ClangASTSource @@ -1590,7 +1661,7 @@ ClangExpressionDeclMap::GetDecls (NameSearchContext &context, const ConstString // doesn't start with our phony prefix of '$' if (name_unique_cstr[0] != '$') { - Variable *var = FindVariableInScope(*m_parser_vars->m_exe_ctx->frame, name); + VariableSP var = FindVariableInScope(*m_parser_vars->m_exe_ctx->frame, name); // If we found a variable in scope, no need to pull up function names if (var != NULL) @@ -1797,7 +1868,7 @@ Value * ClangExpressionDeclMap::GetVariableValue ( ExecutionContext &exe_ctx, - Variable *var, + VariableSP var, clang::ASTContext *parser_ast_context, TypeFromUser *user_type, TypeFromParser *parser_type @@ -1904,7 +1975,7 @@ ClangExpressionDeclMap::GetVariableValue } void -ClangExpressionDeclMap::AddOneVariable (NameSearchContext &context, Variable* var) +ClangExpressionDeclMap::AddOneVariable (NameSearchContext &context, VariableSP var) { assert (m_parser_vars.get()); @@ -1936,6 +2007,7 @@ ClangExpressionDeclMap::AddOneVariable (NameSearchContext &context, Variable* va entity->m_parser_vars->m_named_decl = var_decl; entity->m_parser_vars->m_llvm_value = NULL; entity->m_parser_vars->m_lldb_value = var_location; + entity->m_parser_vars->m_lldb_var = var; if (log) { diff --git a/lldb/source/Expression/ClangExpressionParser.cpp b/lldb/source/Expression/ClangExpressionParser.cpp index 0d693ce0aeb..51654626fcd 100644 --- a/lldb/source/Expression/ClangExpressionParser.cpp +++ b/lldb/source/Expression/ClangExpressionParser.cpp @@ -456,7 +456,8 @@ ClangExpressionParser::MakeJIT (lldb::addr_t &func_allocation_addr, lldb::addr_t &func_addr, lldb::addr_t &func_end, ExecutionContext &exe_ctx, - lldb::ClangExpressionVariableSP *const_result) + lldb::ClangExpressionVariableSP &const_result, + bool jit_only_if_needed) { func_allocation_addr = LLDB_INVALID_ADDRESS; func_addr = LLDB_INVALID_ADDRESS; @@ -512,6 +513,12 @@ ClangExpressionParser::MakeJIT (lldb::addr_t &func_allocation_addr, return err; } + if (jit_only_if_needed && const_result.get()) + { + err.Clear(); + return err; + } + if (m_expr.NeedsValidation() && exe_ctx.process->GetDynamicCheckers()) { IRDynamicChecks ir_dynamic_checks(*exe_ctx.process->GetDynamicCheckers(), function_name.c_str()); diff --git a/lldb/source/Expression/ClangFunction.cpp b/lldb/source/Expression/ClangFunction.cpp index 9d7f7540fdc..935ff95ce4f 100644 --- a/lldb/source/Expression/ClangFunction.cpp +++ b/lldb/source/Expression/ClangFunction.cpp @@ -251,7 +251,9 @@ ClangFunction::WriteFunctionWrapper (ExecutionContext &exe_ctx, Stream &errors) if (m_JITted) return true; - Error jit_error (m_parser->MakeJIT (m_jit_alloc, m_jit_start_addr, m_jit_end_addr, exe_ctx)); + lldb::ClangExpressionVariableSP const_result; + + Error jit_error (m_parser->MakeJIT (m_jit_alloc, m_jit_start_addr, m_jit_end_addr, exe_ctx, const_result)); if (!jit_error.Success()) return false; diff --git a/lldb/source/Expression/ClangUserExpression.cpp b/lldb/source/Expression/ClangUserExpression.cpp index 5a92cac7e3f..f1dd49f64dd 100644 --- a/lldb/source/Expression/ClangUserExpression.cpp +++ b/lldb/source/Expression/ClangUserExpression.cpp @@ -49,7 +49,8 @@ ClangUserExpression::ClangUserExpression (const char *expr, m_cplusplus (false), m_objectivec (false), m_needs_object_ptr (false), - m_const_object (false) + m_const_object (false), + m_const_result () { } @@ -147,8 +148,7 @@ bool ClangUserExpression::Parse (Stream &error_stream, ExecutionContext &exe_ctx, TypeFromUser desired_type, - bool keep_result_in_memory, - lldb::ClangExpressionVariableSP *const_result) + bool keep_result_in_memory) { lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); @@ -284,7 +284,7 @@ ClangUserExpression::Parse (Stream &error_stream, m_dwarf_opcodes.reset(); - Error jit_error = parser.MakeJIT (m_jit_alloc, m_jit_start_addr, m_jit_end_addr, exe_ctx, const_result); + Error jit_error = parser.MakeJIT (m_jit_alloc, m_jit_start_addr, m_jit_end_addr, exe_ctx, m_const_result, true); m_expr_decl_map->DidParse(); @@ -457,7 +457,6 @@ ExecutionResults ClangUserExpression::Execute (Stream &error_stream, ExecutionContext &exe_ctx, bool discard_on_error, - bool keep_in_memory, ClangUserExpression::ClangUserExpressionSP &shared_ptr_to_me, lldb::ClangExpressionVariableSP &result) { @@ -556,7 +555,6 @@ ClangUserExpression::DwarfOpcodeStream () ExecutionResults ClangUserExpression::Evaluate (ExecutionContext &exe_ctx, bool discard_on_error, - bool keep_in_memory, const char *expr_cstr, const char *expr_prefix, lldb::ValueObjectSP &result_valobj_sp) @@ -603,13 +601,11 @@ ClangUserExpression::Evaluate (ExecutionContext &exe_ctx, ClangUserExpressionSP user_expression_sp (new ClangUserExpression (expr_cstr, expr_prefix)); StreamString error_stream; - - lldb::ClangExpressionVariableSP const_result; - + if (log) log->Printf("== [ClangUserExpression::Evaluate] Parsing expression %s ==", expr_cstr); - if (!user_expression_sp->Parse (error_stream, exe_ctx, TypeFromUser(NULL, NULL), &const_result)) + if (!user_expression_sp->Parse (error_stream, exe_ctx, TypeFromUser(NULL, NULL), true)) { if (error_stream.GetString().empty()) error.SetErrorString ("expression failed to parse, unknown error"); @@ -620,12 +616,12 @@ ClangUserExpression::Evaluate (ExecutionContext &exe_ctx, { lldb::ClangExpressionVariableSP expr_result; - if (const_result.get() && !keep_in_memory) + if (user_expression_sp->m_const_result.get()) { if (log) log->Printf("== [ClangUserExpression::Evaluate] Expression evaluated as a constant =="); - result_valobj_sp = const_result->GetValueObject(); + result_valobj_sp = user_expression_sp->m_const_result->GetValueObject(); } else { @@ -637,7 +633,6 @@ ClangUserExpression::Evaluate (ExecutionContext &exe_ctx, execution_results = user_expression_sp->Execute (error_stream, exe_ctx, discard_on_error, - keep_in_memory, user_expression_sp, expr_result); diff --git a/lldb/source/Expression/ClangUtilityFunction.cpp b/lldb/source/Expression/ClangUtilityFunction.cpp index 9d9b3d1d849..7882371ef3a 100644 --- a/lldb/source/Expression/ClangUtilityFunction.cpp +++ b/lldb/source/Expression/ClangUtilityFunction.cpp @@ -108,8 +108,10 @@ ClangUtilityFunction::Install (Stream &error_stream, ////////////////////////////////// // JIT the output of the parser // + + lldb::ClangExpressionVariableSP const_result; - Error jit_error = parser.MakeJIT (m_jit_alloc, m_jit_start_addr, m_jit_end_addr, exe_ctx); + Error jit_error = parser.MakeJIT (m_jit_alloc, m_jit_start_addr, m_jit_end_addr, exe_ctx, const_result); if (exe_ctx.process && m_jit_start_addr != LLDB_INVALID_ADDRESS) m_jit_process_sp = exe_ctx.process->GetSP(); diff --git a/lldb/source/Expression/IRForTarget.cpp b/lldb/source/Expression/IRForTarget.cpp index 4581712ceaa..8be2a429fb4 100644 --- a/lldb/source/Expression/IRForTarget.cpp +++ b/lldb/source/Expression/IRForTarget.cpp @@ -26,6 +26,7 @@ #include "lldb/Core/Scalar.h" #include "lldb/Core/StreamString.h" #include "lldb/Expression/ClangExpressionDeclMap.h" +#include "lldb/Symbol/ClangASTContext.h" #include <map> @@ -35,7 +36,7 @@ static char ID; IRForTarget::IRForTarget (lldb_private::ClangExpressionDeclMap *decl_map, bool resolve_vars, - lldb::ClangExpressionVariableSP *const_result, + lldb::ClangExpressionVariableSP &const_result, lldb_private::Stream *error_stream, const char *func_name) : ModulePass(ID), @@ -44,10 +45,11 @@ IRForTarget::IRForTarget (lldb_private::ClangExpressionDeclMap *decl_map, m_decl_map(decl_map), m_CFStringCreateWithBytes(NULL), m_sel_registerName(NULL), - m_const_result(const_result), m_error_stream(error_stream), m_has_side_effects(false), - m_result_is_pointer(false) + m_result_store(NULL), + m_result_is_pointer(false), + m_const_result(const_result) { } @@ -87,7 +89,7 @@ IRForTarget::HasSideEffects (llvm::Module &llvm_module, { llvm::Function::iterator bbi; BasicBlock::iterator ii; - + for (bbi = llvm_function.begin(); bbi != llvm_function.end(); ++bbi) @@ -108,15 +110,33 @@ IRForTarget::HasSideEffects (llvm::Module &llvm_module, Value *store_ptr = store_inst->getPointerOperand(); - if (!isa <AllocaInst> (store_ptr)) - return true; - else + std::string ptr_name; + + if (store_ptr->hasName()) + ptr_name = store_ptr->getNameStr(); + + if (isa <AllocaInst> (store_ptr)) break; + + if (ptr_name.find("$__lldb_expr_result") != std::string::npos) + { + if (ptr_name.find("GV") == std::string::npos) + m_result_store = store_inst; + } + else + { + return true; + } + + break; } case Instruction::Load: case Instruction::Alloca: case Instruction::GetElementPtr: + case Instruction::BitCast: case Instruction::Ret: + case Instruction::ICmp: + case Instruction::Br: break; } } @@ -125,18 +145,133 @@ IRForTarget::HasSideEffects (llvm::Module &llvm_module, return false; } +clang::NamedDecl * +IRForTarget::DeclForGlobal (llvm::Module &module, GlobalValue *global_val) +{ + lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + NamedMDNode *named_metadata = module.getNamedMetadata("clang.global.decl.ptrs"); + + if (!named_metadata) + return NULL; + + unsigned num_nodes = named_metadata->getNumOperands(); + unsigned node_index; + + for (node_index = 0; + node_index < num_nodes; + ++node_index) + { + MDNode *metadata_node = named_metadata->getOperand(node_index); + + if (!metadata_node) + return NULL; + + if (metadata_node->getNumOperands() != 2) + continue; + + if (metadata_node->getOperand(0) != global_val) + continue; + + ConstantInt *constant_int = dyn_cast<ConstantInt>(metadata_node->getOperand(1)); + + if (!constant_int) + return NULL; + + uintptr_t ptr = constant_int->getZExtValue(); + + return reinterpret_cast<clang::NamedDecl *>(ptr); + } + + return NULL; +} + void IRForTarget::MaybeSetConstantResult (llvm::Constant *initializer, const lldb_private::ConstString &name, lldb_private::TypeFromParser type) { - if (!m_const_result) + if (llvm::ConstantExpr *init_expr = dyn_cast<llvm::ConstantExpr>(initializer)) + { + switch (init_expr->getOpcode()) + { + default: + return; + case Instruction::IntToPtr: + MaybeSetConstantResult (init_expr->getOperand(0), name, type); + return; + } + } + else if (llvm::ConstantInt *init_int = dyn_cast<llvm::ConstantInt>(initializer)) + { + m_const_result = m_decl_map->BuildIntegerVariable(name, type, init_int->getValue()); + } +} + +void +IRForTarget::MaybeSetCastResult (llvm::Module &llvm_module, lldb_private::TypeFromParser type) +{ + lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (!m_result_store) return; - if (llvm::ConstantInt *init_int = dyn_cast<llvm::ConstantInt>(initializer)) + LoadInst *original_load = NULL; + + for (llvm::Value *current_value = m_result_store->getValueOperand(), *next_value; + current_value != NULL; + current_value = next_value) { - *m_const_result = m_decl_map->BuildIntegerVariable(name, type, init_int->getValue()); + CastInst *cast_inst = dyn_cast<CastInst>(current_value); + LoadInst *load_inst = dyn_cast<LoadInst>(current_value); + + if (cast_inst) + { + next_value = cast_inst->getOperand(0); + } + else if(load_inst) + { + if (isa<LoadInst>(load_inst->getPointerOperand())) + { + next_value = load_inst->getPointerOperand(); + } + else + { + original_load = load_inst; + break; + } + } + else + { + return; + } } + + Value *loaded_value = original_load->getPointerOperand(); + GlobalVariable *loaded_global = dyn_cast<GlobalVariable>(loaded_value); + + if (!loaded_global) + return; + + clang::NamedDecl *loaded_decl = DeclForGlobal(llvm_module, loaded_global); + + if (!loaded_decl) + return; + + clang::VarDecl *loaded_var = dyn_cast<clang::VarDecl>(loaded_decl); + + if (!loaded_var) + return; + + if (log) + { + lldb_private::StreamString type_desc_stream; + type.DumpTypeDescription(&type_desc_stream); + + log->Printf("Type to cast variable to: \"%s\"", type_desc_stream.GetString().c_str()); + } + + m_const_result = m_decl_map->BuildCastVariable(m_result_name, loaded_var, type); } bool @@ -214,64 +349,50 @@ IRForTarget::CreateResultVariable (llvm::Module &llvm_module, llvm::Function &ll return false; } - // Find the metadata and follow it to the VarDecl - - NamedMDNode *named_metadata = llvm_module.getNamedMetadata("clang.global.decl.ptrs"); - - if (!named_metadata) + clang::NamedDecl *result_decl = DeclForGlobal (llvm_module, result_global); + if (!result_decl) { if (log) - log->PutCString("No global metadata"); + log->PutCString("Result variable doesn't have a corresponding Decl"); if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: No metadata\n"); + m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s) does not have a corresponding Clang entity\n", result_name); return false; } - - unsigned num_nodes = named_metadata->getNumOperands(); - unsigned node_index; - MDNode *metadata_node = NULL; - - for (node_index = 0; - node_index < num_nodes; - ++node_index) + if (log) { - metadata_node = named_metadata->getOperand(node_index); - - if (metadata_node->getNumOperands() != 2) - continue; + std::string decl_desc_str; + raw_string_ostream decl_desc_stream(decl_desc_str); + result_decl->print(decl_desc_stream); + decl_desc_stream.flush(); - if (metadata_node->getOperand(0) == result_global) - break; + log->Printf("Found result decl: \"%s\"", decl_desc_str.c_str()); } - if (!metadata_node) + clang::VarDecl *result_var = dyn_cast<clang::VarDecl>(result_decl); + if (!result_var) { if (log) - log->PutCString("Couldn't find result metadata"); + log->PutCString("Result variable Decl isn't a VarDecl"); if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s) is a global variable, but has no metadata\n", result_name); + m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s)'s corresponding Clang entity isn't a variable\n", result_name); return false; } - - ConstantInt *constant_int = dyn_cast<ConstantInt>(metadata_node->getOperand(1)); - - lldb::addr_t result_decl_intptr = constant_int->getZExtValue(); - clang::VarDecl *result_decl = reinterpret_cast<clang::VarDecl *>(result_decl_intptr); - // Get the next available result name from m_decl_map and create the persistent // variable for it lldb_private::TypeFromParser result_decl_type; + // If the result is an Lvalue, it is emitted as a pointer; see + // ASTResultSynthesizer::SynthesizeBodyResult. if (m_result_is_pointer) { - clang::QualType pointer_qual_type = result_decl->getType(); + clang::QualType pointer_qual_type = result_var->getType(); const clang::Type *pointer_type = pointer_qual_type.getTypePtr(); const clang::PointerType *pointer_pointertype = dyn_cast<clang::PointerType>(pointer_type); @@ -293,18 +414,19 @@ IRForTarget::CreateResultVariable (llvm::Module &llvm_module, llvm::Function &ll } else { - result_decl_type = lldb_private::TypeFromParser(result_decl->getType().getAsOpaquePtr(), + result_decl_type = lldb_private::TypeFromParser(result_var->getType().getAsOpaquePtr(), &result_decl->getASTContext()); } + if (log) + { + lldb_private::StreamString type_desc_stream; + result_decl_type.DumpTypeDescription(&type_desc_stream); + + log->Printf("Result decl type: \"%s\"", type_desc_stream.GetString().c_str()); + } + m_result_name = m_decl_map->GetPersistentResultName(); - // If the result is an Lvalue, it is emitted as a pointer; see - // ASTResultSynthesizer::SynthesizeBodyResult. - m_decl_map->AddPersistentVariable(result_decl, - m_result_name, - result_decl_type, - true, - m_result_is_pointer); if (log) log->Printf("Creating a new result global: \"%s\"", m_result_name.GetCString()); @@ -325,8 +447,8 @@ IRForTarget::CreateResultVariable (llvm::Module &llvm_module, llvm::Function &ll // ClangExpressionDeclMap::DoMaterialize, and the name of the variable is // fixed up. - ConstantInt *new_constant_int = ConstantInt::get(constant_int->getType(), - result_decl_intptr, + ConstantInt *new_constant_int = ConstantInt::get(llvm::Type::getInt64Ty(llvm_module.getContext()), + reinterpret_cast<uint64_t>(result_decl), false); llvm::Value* values[2]; @@ -334,6 +456,7 @@ IRForTarget::CreateResultVariable (llvm::Module &llvm_module, llvm::Function &ll values[1] = new_constant_int; MDNode *persistent_global_md = MDNode::get(llvm_module.getContext(), values, 2); + NamedMDNode *named_metadata = llvm_module.getNamedMetadata("clang.global.decl.ptrs"); named_metadata->addOperand(persistent_global_md); if (log) @@ -384,8 +507,20 @@ IRForTarget::CreateResultVariable (llvm::Module &llvm_module, llvm::Function &ll } else { + if (!m_has_side_effects && lldb_private::ClangASTContext::IsPointerType (result_decl_type.GetOpaqueQualType())) + { + MaybeSetCastResult (llvm_module, result_decl_type); + } + result_global->replaceAllUsesWith(new_result_global); } + + if (!m_const_result) + m_decl_map->AddPersistentVariable(result_decl, + m_result_name, + result_decl_type, + true, + m_result_is_pointer); result_global->eraseFromParent(); @@ -1047,45 +1182,6 @@ IRForTarget::RewritePersistentAllocs(llvm::Module &llvm_module, llvm::BasicBlock return true; } -static clang::NamedDecl * -DeclForGlobalValue(Module &module, GlobalValue *global_value) -{ - NamedMDNode *named_metadata = module.getNamedMetadata("clang.global.decl.ptrs"); - - if (!named_metadata) - return NULL; - - unsigned num_nodes = named_metadata->getNumOperands(); - unsigned node_index; - - for (node_index = 0; - node_index < num_nodes; - ++node_index) - { - MDNode *metadata_node = named_metadata->getOperand(node_index); - - if (!metadata_node) - return NULL; - - if (metadata_node->getNumOperands() != 2) - continue; - - if (metadata_node->getOperand(0) != global_value) - continue; - - ConstantInt *constant_int = dyn_cast<ConstantInt>(metadata_node->getOperand(1)); - - if (!constant_int) - return NULL; - - uintptr_t ptr = constant_int->getZExtValue(); - - return reinterpret_cast<clang::NamedDecl *>(ptr); - } - - return NULL; -} - // This function does not report errors; its callers are responsible. bool IRForTarget::MaybeHandleVariable (Module &llvm_module, Value *llvm_value_ptr) @@ -1110,7 +1206,7 @@ IRForTarget::MaybeHandleVariable (Module &llvm_module, Value *llvm_value_ptr) } else if (GlobalVariable *global_variable = dyn_cast<GlobalVariable>(llvm_value_ptr)) { - clang::NamedDecl *named_decl = DeclForGlobalValue(llvm_module, global_variable); + clang::NamedDecl *named_decl = DeclForGlobal(llvm_module, global_variable); if (!named_decl) { @@ -1331,7 +1427,7 @@ IRForTarget::MaybeHandleCall (Module &llvm_module, CallInst *llvm_call_inst) str.SetCStringWithLength (fun->getName().data(), fun->getName().size()); } - clang::NamedDecl *fun_decl = DeclForGlobalValue (llvm_module, fun); + clang::NamedDecl *fun_decl = DeclForGlobal (llvm_module, fun); lldb::addr_t fun_addr = LLDB_INVALID_ADDRESS; Value **fun_value_ptr = NULL; @@ -1445,7 +1541,7 @@ IRForTarget::ResolveExternals (Module &llvm_module, Function &llvm_function) if (log) log->Printf("Examining %s, DeclForGlobalValue returns %p", (*global).getName().str().c_str(), - DeclForGlobalValue(llvm_module, global)); + DeclForGlobal(llvm_module, global)); if ((*global).getName().str().find("OBJC_IVAR") == 0) { @@ -1457,7 +1553,7 @@ IRForTarget::ResolveExternals (Module &llvm_module, Function &llvm_function) return false; } } - else if (DeclForGlobalValue(llvm_module, global)) + else if (DeclForGlobal(llvm_module, global)) { if (!MaybeHandleVariable (llvm_module, global)) { @@ -1882,6 +1978,9 @@ IRForTarget::runOnModule (Module &llvm_module) return false; } + if (m_const_result) + return true; + /////////////////////////////////////////////////////////////////////////////// // Fix all Objective-C constant strings to use NSStringWithCString:encoding: // diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index 7bdccdaf4d0..80d1d758cf5 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -1246,14 +1246,13 @@ Process::LoadImage (const FileSpec &image_spec, Error &error) ExecutionContext exe_ctx; frame_sp->CalculateExecutionContext (exe_ctx); bool unwind_on_error = true; - bool keep_in_memory = false; StreamString expr; char path[PATH_MAX]; image_spec.GetPath(path, sizeof(path)); expr.Printf("dlopen (\"%s\", 2)", path); const char *prefix = "extern \"C\" void* dlopen (const char *path, int mode);\n"; lldb::ValueObjectSP result_valobj_sp; - ClangUserExpression::Evaluate (exe_ctx, keep_in_memory, unwind_on_error, expr.GetData(), prefix, result_valobj_sp); + ClangUserExpression::Evaluate (exe_ctx, unwind_on_error, expr.GetData(), prefix, result_valobj_sp); if (result_valobj_sp->GetError().Success()) { Scalar scalar; @@ -1314,12 +1313,11 @@ Process::UnloadImage (uint32_t image_token) ExecutionContext exe_ctx; frame_sp->CalculateExecutionContext (exe_ctx); bool unwind_on_error = true; - bool keep_in_memory = false; StreamString expr; expr.Printf("dlclose ((void *)0x%llx)", image_addr); const char *prefix = "extern \"C\" int dlclose(void* handle);\n"; lldb::ValueObjectSP result_valobj_sp; - ClangUserExpression::Evaluate (exe_ctx, unwind_on_error, keep_in_memory, expr.GetData(), prefix, result_valobj_sp); + ClangUserExpression::Evaluate (exe_ctx, unwind_on_error, expr.GetData(), prefix, result_valobj_sp); if (result_valobj_sp->GetError().Success()) { Scalar scalar; diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index 9f3a45e31c7..080a54e4d14 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -994,7 +994,6 @@ Target::EvaluateExpression execution_results = ClangUserExpression::Evaluate (exe_ctx, unwind_on_error, - keep_in_memory, expr_cstr, prefix, result_valobj_sp); |