From 3fe71581743ceb838b113ee728e6de7f7ee8d25d Mon Sep 17 00:00:00 2001 From: Marianne Mailhot-Sarrasin Date: Thu, 12 May 2016 20:00:53 +0000 Subject: [LLDB] Added support for PHI nodes to IR interpreter This allows expressions such as 'i == 1 || i == 2` to be executed using the IR interpreter, instead of relying on JIT code injection (which may not be available on some platforms). Patch by cameron314 Differential Revision: http://reviews.llvm.org/D19124 llvm-svn: 269340 --- lldb/source/Expression/IRInterpreter.cpp | 47 +++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) (limited to 'lldb/source/Expression/IRInterpreter.cpp') diff --git a/lldb/source/Expression/IRInterpreter.cpp b/lldb/source/Expression/IRInterpreter.cpp index 42d6dc116f9..0285248314b 100644 --- a/lldb/source/Expression/IRInterpreter.cpp +++ b/lldb/source/Expression/IRInterpreter.cpp @@ -106,6 +106,7 @@ public: DataLayout &m_target_data; lldb_private::IRExecutionUnit &m_execution_unit; const BasicBlock *m_bb; + const BasicBlock *m_prev_bb; BasicBlock::const_iterator m_ii; BasicBlock::const_iterator m_ie; @@ -121,7 +122,9 @@ public: lldb::addr_t stack_frame_bottom, lldb::addr_t stack_frame_top) : m_target_data (target_data), - m_execution_unit (execution_unit) + m_execution_unit (execution_unit), + m_bb (nullptr), + m_prev_bb (nullptr) { m_byte_order = (target_data.isLittleEndian() ? lldb::eByteOrderLittle : lldb::eByteOrderBig); m_addr_byte_size = (target_data.getPointerSize(0)); @@ -137,6 +140,7 @@ public: void Jump (const BasicBlock *bb) { + m_prev_bb = m_bb; m_bb = bb; m_ii = m_bb->begin(); m_ie = m_bb->end(); @@ -569,6 +573,7 @@ IRInterpreter::CanInterpret (llvm::Module &module, case Instruction::Alloca: case Instruction::BitCast: case Instruction::Br: + case Instruction::PHI: break; case Instruction::Call: { @@ -1063,6 +1068,46 @@ IRInterpreter::Interpret (llvm::Module &module, } } continue; + case Instruction::PHI: + { + const PHINode *phi_inst = dyn_cast(inst); + + if (!phi_inst) + { + if (log) + log->Printf("getOpcode() returns PHI, but instruction is not a PHINode"); + error.SetErrorToGenericError(); + error.SetErrorString(interpreter_internal_error); + return false; + } + if (!frame.m_prev_bb) + { + if (log) + log->Printf("Encountered PHI node without having jumped from another basic block"); + error.SetErrorToGenericError(); + error.SetErrorString(interpreter_internal_error); + return false; + } + + Value* value = phi_inst->getIncomingValueForBlock(frame.m_prev_bb); + lldb_private::Scalar result; + if (!frame.EvaluateValue(result, value, module)) + { + if (log) + log->Printf("Couldn't evaluate %s", PrintValue(value).c_str()); + error.SetErrorToGenericError(); + error.SetErrorString(bad_value_error); + return false; + } + frame.AssignValue(inst, result, module); + + if (log) + { + log->Printf("Interpreted a %s", inst->getOpcodeName()); + log->Printf(" Incoming value : %s", frame.SummarizeValue(value).c_str()); + } + } + break; case Instruction::GetElementPtr: { const GetElementPtrInst *gep_inst = dyn_cast(inst); -- cgit v1.2.3