diff --git a/lldb/include/lldb/Expression/ClangExpressionParser.h b/lldb/include/lldb/Expression/ClangExpressionParser.h index 982e67a92840..c3323b88e132 100644 --- a/lldb/include/lldb/Expression/ClangExpressionParser.h +++ b/lldb/include/lldb/Expression/ClangExpressionParser.h @@ -189,7 +189,6 @@ private: std::auto_ptr m_selector_table; ///< Selector table for Objective-C methods std::auto_ptr m_ast_context; ///< The AST context used to hold types and names for the parser std::auto_ptr m_code_generator; ///< [owned by the Execution Engine] The Clang object that generates IR - std::auto_ptr m_execution_engine; ///< The LLVM JIT std::vector m_jitted_functions; ///< A vector of all functions that have been JITted into machine code (just one, if ParseExpression() was called) }; diff --git a/lldb/include/lldb/Expression/IRForTarget.h b/lldb/include/lldb/Expression/IRForTarget.h index 46fd3a6a9854..d263e7de3b1d 100644 --- a/lldb/include/lldb/Expression/IRForTarget.h +++ b/lldb/include/lldb/Expression/IRForTarget.h @@ -12,6 +12,7 @@ #include "lldb/lldb-public.h" #include "lldb/Core/ConstString.h" +#include "lldb/Core/Error.h" #include "lldb/Core/Stream.h" #include "lldb/Symbol/TaggedASTType.h" #include "llvm/Pass.h" @@ -115,6 +116,10 @@ public: /// $__lldb_expr, and that function is passed to the passes one by /// one. /// + /// @param[in] interpreter_error + /// An error. If the expression fails to be interpreted, this error + /// is set to a reason why. + /// /// @return /// True on success; false otherwise //------------------------------------------------------------------ @@ -146,10 +151,10 @@ public: /// /// Returns true if it did; false otherwise. //------------------------------------------------------------------ - bool - interpretSuccess () + lldb_private::Error & + getInterpreterError () { - return m_interpret_success; + return m_interpreter_error; } private: @@ -632,6 +637,7 @@ private: llvm::Constant *m_sel_registerName; ///< The address of the function sel_registerName, cast to the appropriate function pointer type 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 + lldb_private::Error m_interpreter_error; ///< The error result from the IR interpreter 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. diff --git a/lldb/include/lldb/Expression/IRInterpreter.h b/lldb/include/lldb/Expression/IRInterpreter.h index dd4d38410df0..c8d341f045f7 100644 --- a/lldb/include/lldb/Expression/IRInterpreter.h +++ b/lldb/include/lldb/Expression/IRInterpreter.h @@ -79,6 +79,9 @@ public: /// @param[in] llvm_module /// The module containing the function. /// + /// @param[in] error + /// If the expression fails to interpret, a reason why. + /// /// @return /// True on success; false otherwise //------------------------------------------------------------------ @@ -87,21 +90,24 @@ public: const lldb_private::ConstString &result_name, lldb_private::TypeFromParser result_type, llvm::Function &llvm_function, - llvm::Module &llvm_module); + llvm::Module &llvm_module, + lldb_private::Error &err); private: /// Flags lldb_private::ClangExpressionDeclMap &m_decl_map; ///< The DeclMap containing the Decls lldb_private::Stream *m_error_stream; bool - supportsFunction (llvm::Function &llvm_function); + supportsFunction (llvm::Function &llvm_function, + lldb_private::Error &err); bool runOnFunction (lldb::ClangExpressionVariableSP &result, const lldb_private::ConstString &result_name, lldb_private::TypeFromParser result_type, llvm::Function &llvm_function, - llvm::Module &llvm_module); + llvm::Module &llvm_module, + lldb_private::Error &err); }; #endif diff --git a/lldb/source/Expression/ClangExpressionParser.cpp b/lldb/source/Expression/ClangExpressionParser.cpp index 7c3e6589621a..625b03e28a22 100644 --- a/lldb/source/Expression/ClangExpressionParser.cpp +++ b/lldb/source/Expression/ClangExpressionParser.cpp @@ -187,7 +187,6 @@ ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope, m_expr (expr), m_compiler (), m_code_generator (NULL), - m_execution_engine (), m_jitted_functions () { // Initialize targets first, so that --version shows registered targets. @@ -447,6 +446,8 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_allocation_addr, func_end = LLDB_INVALID_ADDRESS; lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + std::auto_ptr execution_engine; + Error err; llvm::Module *module = m_code_generator->ReleaseModule(); @@ -498,7 +499,9 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_allocation_addr, return err; } - if (execution_policy != eExecutionPolicyAlways && ir_for_target.interpretSuccess()) + Error &interpreter_error(ir_for_target.getInterpreterError()); + + if (execution_policy != eExecutionPolicyAlways && interpreter_error.Success()) { if (const_result) const_result->TransferAddress(); @@ -512,7 +515,10 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_allocation_addr, if (!process || execution_policy == eExecutionPolicyNever) { err.SetErrorToGenericError(); - err.SetErrorString("Execution needed to run in the target, but the target can't be run"); + if (execution_policy == eExecutionPolicyAlways) + err.SetErrorString("Execution needed to run in the target, but the target can't be run"); + else + err.SetErrorStringWithFormat("Interpreting the expression locally failed: %s", interpreter_error.AsCString()); return err; } @@ -571,15 +577,6 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_allocation_addr, log->Printf ("Module being sent to JIT: \n%s", s.c_str()); } -#if defined (USE_STANDARD_JIT) - m_execution_engine.reset(llvm::ExecutionEngine::createJIT (module, - &error_string, - jit_memory_manager, - CodeGenOpt::Less, - true, - Reloc::Default, - CodeModel::Small)); -#else EngineBuilder builder(module); builder.setEngineKind(EngineKind::JIT) .setErrorStr(&error_string) @@ -589,24 +586,23 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_allocation_addr, .setAllocateGVsWithCode(true) .setCodeModel(CodeModel::Small) .setUseMCJIT(true); - m_execution_engine.reset(builder.create()); -#endif + execution_engine.reset(builder.create()); - if (!m_execution_engine.get()) + if (!execution_engine.get()) { err.SetErrorToGenericError(); err.SetErrorStringWithFormat("Couldn't JIT the function: %s", error_string.c_str()); return err; } - m_execution_engine->DisableLazyCompilation(); + execution_engine->DisableLazyCompilation(); llvm::Function *function = module->getFunction (function_name.c_str()); // We don't actually need the function pointer here, this just forces it to get resolved. - void *fun_ptr = m_execution_engine->getPointerToFunction(function); - + void *fun_ptr = execution_engine->getPointerToFunction(function); + // Errors usually cause failures in the JIT, but if we're lucky we get here. if (!function) @@ -717,6 +713,8 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_allocation_addr, } } + execution_engine.reset(); + err.Clear(); return err; } diff --git a/lldb/source/Expression/IRForTarget.cpp b/lldb/source/Expression/IRForTarget.cpp index c16e1266b91d..15ba25038afa 100644 --- a/lldb/source/Expression/IRForTarget.cpp +++ b/lldb/source/Expression/IRForTarget.cpp @@ -2663,11 +2663,10 @@ IRForTarget::runOnModule (Module &llvm_module) IRInterpreter interpreter (*m_decl_map, m_error_stream); - if (interpreter.maybeRunOnFunction(m_const_result, m_result_name, m_result_type, *function, llvm_module)) - { - m_interpret_success = true; + interpreter.maybeRunOnFunction(m_const_result, m_result_name, m_result_type, *function, llvm_module, m_interpreter_error); + + if (m_interpreter_error.Success()) return true; - } } if (log && log->GetVerbose()) diff --git a/lldb/source/Expression/IRInterpreter.cpp b/lldb/source/Expression/IRInterpreter.cpp index dba09799d5bd..3cbe9f3bd8f2 100644 --- a/lldb/source/Expression/IRInterpreter.cpp +++ b/lldb/source/Expression/IRInterpreter.cpp @@ -851,20 +851,32 @@ IRInterpreter::maybeRunOnFunction (lldb::ClangExpressionVariableSP &result, const lldb_private::ConstString &result_name, lldb_private::TypeFromParser result_type, Function &llvm_function, - Module &llvm_module) + Module &llvm_module, + lldb_private::Error &err) { - if (supportsFunction (llvm_function)) + if (supportsFunction (llvm_function, err)) return runOnFunction(result, result_name, result_type, llvm_function, - llvm_module); + llvm_module, + err); else return false; } +static const char *unsupported_opcode_error = "Interpreter doesn't handle one of the expression's opcodes"; +static const char *interpreter_initialization_error = "Interpreter couldn't be initialized"; +static const char *interpreter_internal_error = "Interpreter encountered an internal error"; +static const char *bad_value_error = "Interpreter couldn't resolve a value during execution"; +static const char *memory_allocation_error = "Interpreter couldn't allocate memory"; +static const char *memory_write_error = "Interpreter couldn't write to memory"; +static const char *memory_read_error = "Interpreter couldn't read from memory"; +static const char *infinite_loop_error = "Interpreter ran for too many cycles"; + bool -IRInterpreter::supportsFunction (Function &llvm_function) +IRInterpreter::supportsFunction (Function &llvm_function, + lldb_private::Error &err) { lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); @@ -882,6 +894,8 @@ IRInterpreter::supportsFunction (Function &llvm_function) { if (log) log->Printf("Unsupported instruction: %s", PrintValue(ii).c_str()); + err.SetErrorToGenericError(); + err.SetErrorString(unsupported_opcode_error); return false; } case Instruction::Add: @@ -895,7 +909,11 @@ IRInterpreter::supportsFunction (Function &llvm_function) ICmpInst *icmp_inst = dyn_cast(ii); if (!icmp_inst) + { + err.SetErrorToGenericError(); + err.SetErrorString(interpreter_internal_error); return false; + } switch (icmp_inst->getPredicate()) { @@ -903,6 +921,9 @@ IRInterpreter::supportsFunction (Function &llvm_function) { if (log) log->Printf("Unsupported ICmp predicate: %s", PrintValue(ii).c_str()); + + err.SetErrorToGenericError(); + err.SetErrorString(unsupported_opcode_error); return false; } case CmpInst::ICMP_EQ: @@ -940,14 +961,19 @@ IRInterpreter::runOnFunction (lldb::ClangExpressionVariableSP &result, const lldb_private::ConstString &result_name, lldb_private::TypeFromParser result_type, Function &llvm_function, - Module &llvm_module) + Module &llvm_module, + lldb_private::Error &err) { lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); lldb_private::ClangExpressionDeclMap::TargetInfo target_info = m_decl_map.GetTargetInfo(); if (!target_info.IsValid()) + { + err.SetErrorToGenericError(); + err.SetErrorString(interpreter_initialization_error); return false; + } lldb::addr_t alloc_min; lldb::addr_t alloc_max; @@ -955,7 +981,9 @@ IRInterpreter::runOnFunction (lldb::ClangExpressionVariableSP &result, switch (target_info.address_byte_size) { default: - return false; + err.SetErrorToGenericError(); + err.SetErrorString(interpreter_initialization_error); + return false; case 4: alloc_min = 0x00001000llu; alloc_max = 0x0000ffffllu; @@ -968,9 +996,17 @@ IRInterpreter::runOnFunction (lldb::ClangExpressionVariableSP &result, TargetData target_data(&llvm_module); if (target_data.getPointerSize() != target_info.address_byte_size) + { + err.SetErrorToGenericError(); + err.SetErrorString(interpreter_initialization_error); return false; + } if (target_data.isLittleEndian() != (target_info.byte_order == lldb::eByteOrderLittle)) + { + err.SetErrorToGenericError(); + err.SetErrorString(interpreter_initialization_error); return false; + } Memory memory(target_data, m_decl_map, alloc_min, alloc_max); InterpreterStackFrame frame(target_data, memory, m_decl_map); @@ -1002,8 +1038,9 @@ IRInterpreter::runOnFunction (lldb::ClangExpressionVariableSP &result, { if (log) log->Printf("getOpcode() returns %s, but instruction is not a BinaryOperator", inst->getOpcodeName()); - - return false; + err.SetErrorToGenericError(); + err.SetErrorString(interpreter_internal_error); + return false; } Value *lhs = inst->getOperand(0); @@ -1016,7 +1053,8 @@ IRInterpreter::runOnFunction (lldb::ClangExpressionVariableSP &result, { if (log) log->Printf("Couldn't evaluate %s", PrintValue(lhs).c_str()); - + err.SetErrorToGenericError(); + err.SetErrorString(bad_value_error); return false; } @@ -1024,7 +1062,8 @@ IRInterpreter::runOnFunction (lldb::ClangExpressionVariableSP &result, { if (log) log->Printf("Couldn't evaluate %s", PrintValue(rhs).c_str()); - + err.SetErrorToGenericError(); + err.SetErrorString(bad_value_error); return false; } @@ -1070,7 +1109,8 @@ IRInterpreter::runOnFunction (lldb::ClangExpressionVariableSP &result, { if (log) log->Printf("getOpcode() returns Alloca, but instruction is not an AllocaInst"); - + err.SetErrorToGenericError(); + err.SetErrorString(interpreter_internal_error); return false; } @@ -1078,7 +1118,8 @@ IRInterpreter::runOnFunction (lldb::ClangExpressionVariableSP &result, { if (log) log->Printf("AllocaInsts are not handled if isArrayAllocation() is true"); - + err.SetErrorToGenericError(); + err.SetErrorString(unsupported_opcode_error); return false; } @@ -1096,7 +1137,8 @@ IRInterpreter::runOnFunction (lldb::ClangExpressionVariableSP &result, { if (log) log->Printf("Couldn't allocate memory for an AllocaInst"); - + err.SetErrorToGenericError(); + err.SetErrorString(memory_allocation_error); return false; } @@ -1106,7 +1148,8 @@ IRInterpreter::runOnFunction (lldb::ClangExpressionVariableSP &result, { if (log) log->Printf("Couldn't allocate the result pointer for an AllocaInst"); - + err.SetErrorToGenericError(); + err.SetErrorString(memory_allocation_error); return false; } @@ -1115,8 +1158,9 @@ IRInterpreter::runOnFunction (lldb::ClangExpressionVariableSP &result, if (P_encoder->PutAddress(0, R.m_base) == UINT32_MAX) { if (log) - log->Printf("Couldn't write the reseult pointer for an AllocaInst"); - + log->Printf("Couldn't write the result pointer for an AllocaInst"); + err.SetErrorToGenericError(); + err.SetErrorString(memory_write_error); return false; } @@ -1138,7 +1182,8 @@ IRInterpreter::runOnFunction (lldb::ClangExpressionVariableSP &result, { if (log) log->Printf("getOpcode() returns BitCast, but instruction is not a BitCastInst"); - + err.SetErrorToGenericError(); + err.SetErrorString(interpreter_internal_error); return false; } @@ -1150,7 +1195,8 @@ IRInterpreter::runOnFunction (lldb::ClangExpressionVariableSP &result, { if (log) log->Printf("Couldn't evaluate %s", PrintValue(source).c_str()); - + err.SetErrorToGenericError(); + err.SetErrorString(bad_value_error); return false; } @@ -1165,7 +1211,8 @@ IRInterpreter::runOnFunction (lldb::ClangExpressionVariableSP &result, { if (log) log->Printf("getOpcode() returns Br, but instruction is not a BranchInst"); - + err.SetErrorToGenericError(); + err.SetErrorString(interpreter_internal_error); return false; } @@ -1179,7 +1226,8 @@ IRInterpreter::runOnFunction (lldb::ClangExpressionVariableSP &result, { if (log) log->Printf("Couldn't evaluate %s", PrintValue(condition).c_str()); - + err.SetErrorToGenericError(); + err.SetErrorString(bad_value_error); return false; } @@ -1213,7 +1261,8 @@ IRInterpreter::runOnFunction (lldb::ClangExpressionVariableSP &result, { if (log) log->Printf("getOpcode() returns GetElementPtr, but instruction is not a GetElementPtrInst"); - + err.SetErrorToGenericError(); + err.SetErrorString(interpreter_internal_error); return false; } @@ -1223,8 +1272,14 @@ IRInterpreter::runOnFunction (lldb::ClangExpressionVariableSP &result, lldb_private::Scalar P; if (!frame.EvaluateValue(P, pointer_operand, llvm_module)) + { + if (log) + log->Printf("Couldn't evaluate %s", PrintValue(pointer_operand).c_str()); + err.SetErrorToGenericError(); + err.SetErrorString(bad_value_error); return false; - + } + SmallVector indices (gep_inst->idx_begin(), gep_inst->idx_end()); @@ -1250,7 +1305,8 @@ IRInterpreter::runOnFunction (lldb::ClangExpressionVariableSP &result, { if (log) log->Printf("getOpcode() returns ICmp, but instruction is not an ICmpInst"); - + err.SetErrorToGenericError(); + err.SetErrorString(interpreter_internal_error); return false; } @@ -1266,7 +1322,8 @@ IRInterpreter::runOnFunction (lldb::ClangExpressionVariableSP &result, { if (log) log->Printf("Couldn't evaluate %s", PrintValue(lhs).c_str()); - + err.SetErrorToGenericError(); + err.SetErrorString(bad_value_error); return false; } @@ -1274,7 +1331,8 @@ IRInterpreter::runOnFunction (lldb::ClangExpressionVariableSP &result, { if (log) log->Printf("Couldn't evaluate %s", PrintValue(rhs).c_str()); - + err.SetErrorToGenericError(); + err.SetErrorString(bad_value_error); return false; } @@ -1335,7 +1393,8 @@ IRInterpreter::runOnFunction (lldb::ClangExpressionVariableSP &result, { if (log) log->Printf("getOpcode() returns IntToPtr, but instruction is not an IntToPtrInst"); - + err.SetErrorToGenericError(); + err.SetErrorString(interpreter_internal_error); return false; } @@ -1344,7 +1403,13 @@ IRInterpreter::runOnFunction (lldb::ClangExpressionVariableSP &result, lldb_private::Scalar I; if (!frame.EvaluateValue(I, src_operand, llvm_module)) + { + if (log) + log->Printf("Couldn't evaluate %s", PrintValue(src_operand).c_str()); + err.SetErrorToGenericError(); + err.SetErrorString(bad_value_error); return false; + } frame.AssignValue(inst, I, llvm_module); @@ -1364,7 +1429,8 @@ IRInterpreter::runOnFunction (lldb::ClangExpressionVariableSP &result, { if (log) log->Printf("getOpcode() returns Load, but instruction is not a LoadInst"); - + err.SetErrorToGenericError(); + err.SetErrorString(interpreter_internal_error); return false; } @@ -1379,7 +1445,13 @@ IRInterpreter::runOnFunction (lldb::ClangExpressionVariableSP &result, Type *pointer_ty = pointer_operand->getType(); PointerType *pointer_ptr_ty = dyn_cast(pointer_ty); if (!pointer_ptr_ty) + { + if (log) + log->Printf("getPointerOperand()->getType() is not a PointerType"); + err.SetErrorToGenericError(); + err.SetErrorString(interpreter_internal_error); return false; + } Type *target_ty = pointer_ptr_ty->getElementType(); Memory::Region D = frame.ResolveValue(load_inst, llvm_module); @@ -1389,7 +1461,8 @@ IRInterpreter::runOnFunction (lldb::ClangExpressionVariableSP &result, { if (log) log->Printf("LoadInst's value doesn't resolve to anything"); - + err.SetErrorToGenericError(); + err.SetErrorString(bad_value_error); return false; } @@ -1397,7 +1470,8 @@ IRInterpreter::runOnFunction (lldb::ClangExpressionVariableSP &result, { if (log) log->Printf("LoadInst's pointer doesn't resolve to anything"); - + err.SetErrorToGenericError(); + err.SetErrorString(bad_value_error); return false; } @@ -1415,7 +1489,8 @@ IRInterpreter::runOnFunction (lldb::ClangExpressionVariableSP &result, { if (log) log->Printf("Couldn't read from a region on behalf of a LoadInst"); - + err.SetErrorToGenericError(); + err.SetErrorString(memory_read_error); return false; } } @@ -1425,7 +1500,8 @@ IRInterpreter::runOnFunction (lldb::ClangExpressionVariableSP &result, { if (log) log->Printf("Couldn't read from a raw pointer on behalf of a LoadInst"); - + err.SetErrorToGenericError(); + err.SetErrorString(memory_read_error); return false; } } @@ -1458,7 +1534,8 @@ IRInterpreter::runOnFunction (lldb::ClangExpressionVariableSP &result, { if (log) log->Printf("getOpcode() returns Store, but instruction is not a StoreInst"); - + err.SetErrorToGenericError(); + err.SetErrorString(interpreter_internal_error); return false; } @@ -1484,7 +1561,8 @@ IRInterpreter::runOnFunction (lldb::ClangExpressionVariableSP &result, { if (log) log->Printf("StoreInst's value doesn't resolve to anything"); - + err.SetErrorToGenericError(); + err.SetErrorString(bad_value_error); return false; } @@ -1492,7 +1570,8 @@ IRInterpreter::runOnFunction (lldb::ClangExpressionVariableSP &result, { if (log) log->Printf("StoreInst's pointer doesn't resolve to anything"); - + err.SetErrorToGenericError(); + err.SetErrorString(bad_value_error); return false; } @@ -1513,7 +1592,8 @@ IRInterpreter::runOnFunction (lldb::ClangExpressionVariableSP &result, { if (log) log->Printf("Couldn't write to a region on behalf of a LoadInst"); - + err.SetErrorToGenericError(); + err.SetErrorString(memory_write_error); return false; } } @@ -1523,7 +1603,8 @@ IRInterpreter::runOnFunction (lldb::ClangExpressionVariableSP &result, { if (log) log->Printf("Couldn't write to a raw pointer on behalf of a LoadInst"); - + err.SetErrorToGenericError(); + err.SetErrorString(memory_write_error); return false; } } @@ -1544,7 +1625,11 @@ IRInterpreter::runOnFunction (lldb::ClangExpressionVariableSP &result, } if (num_insts >= 4096) + { + err.SetErrorToGenericError(); + err.SetErrorString(infinite_loop_error); return false; - + } + return false; }