180814287SRaphael Isemann //===-- IRInterpreter.cpp -------------------------------------------------===//
23bfdaa2aSSean Callanan //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63bfdaa2aSSean Callanan //
73bfdaa2aSSean Callanan //===----------------------------------------------------------------------===//
83bfdaa2aSSean Callanan
9579e70c9SSean Callanan #include "lldb/Expression/IRInterpreter.h"
1090ff7911SEwan Crawford #include "lldb/Core/Module.h"
11579e70c9SSean Callanan #include "lldb/Core/ModuleSpec.h"
1290ff7911SEwan Crawford #include "lldb/Core/ValueObject.h"
13579e70c9SSean Callanan #include "lldb/Expression/DiagnosticManager.h"
147071c5fdSTed Woodward #include "lldb/Expression/IRExecutionUnit.h"
15fefe43cdSSean Callanan #include "lldb/Expression/IRMemoryMap.h"
16bf9a7730SZachary Turner #include "lldb/Utility/ConstString.h"
17666cc0b2SZachary Turner #include "lldb/Utility/DataExtractor.h"
1801c3243fSZachary Turner #include "lldb/Utility/Endian.h"
19c34698a8SPavel Labath #include "lldb/Utility/LLDBLog.h"
206f9e6901SZachary Turner #include "lldb/Utility/Log.h"
21d821c997SPavel Labath #include "lldb/Utility/Scalar.h"
2297206d57SZachary Turner #include "lldb/Utility/Status.h"
23bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h"
243bfdaa2aSSean Callanan
2590ff7911SEwan Crawford #include "lldb/Target/ABI.h"
2690ff7911SEwan Crawford #include "lldb/Target/ExecutionContext.h"
2790ff7911SEwan Crawford #include "lldb/Target/Target.h"
2890ff7911SEwan Crawford #include "lldb/Target/Thread.h"
2990ff7911SEwan Crawford #include "lldb/Target/ThreadPlan.h"
3090ff7911SEwan Crawford #include "lldb/Target/ThreadPlanCallFunctionUsingABI.h"
3190ff7911SEwan Crawford
321e157587SChandler Carruth #include "llvm/IR/Constants.h"
33fefe43cdSSean Callanan #include "llvm/IR/DataLayout.h"
341e157587SChandler Carruth #include "llvm/IR/Function.h"
351e157587SChandler Carruth #include "llvm/IR/Instructions.h"
36576a4374SSean Callanan #include "llvm/IR/Intrinsics.h"
3790ff7911SEwan Crawford #include "llvm/IR/LLVMContext.h"
381e157587SChandler Carruth #include "llvm/IR/Module.h"
39d05b8992SEduard Burtescu #include "llvm/IR/Operator.h"
403bfdaa2aSSean Callanan #include "llvm/Support/raw_ostream.h"
413bfdaa2aSSean Callanan
423bfdaa2aSSean Callanan #include <map>
433bfdaa2aSSean Callanan
443bfdaa2aSSean Callanan using namespace llvm;
45a007a6d8SPavel Labath using lldb_private::LLDBLog;
463bfdaa2aSSean Callanan
PrintValue(const Value * value,bool truncate=false)47b9c1b51eSKate Stone static std::string PrintValue(const Value *value, bool truncate = false) {
483bfdaa2aSSean Callanan std::string s;
493bfdaa2aSSean Callanan raw_string_ostream rso(s);
503bfdaa2aSSean Callanan value->print(rso);
513bfdaa2aSSean Callanan rso.flush();
523bfdaa2aSSean Callanan if (truncate)
533bfdaa2aSSean Callanan s.resize(s.length() - 1);
543bfdaa2aSSean Callanan
553bfdaa2aSSean Callanan size_t offset;
563bfdaa2aSSean Callanan while ((offset = s.find('\n')) != s.npos)
573bfdaa2aSSean Callanan s.erase(offset, 1);
583bfdaa2aSSean Callanan while (s[0] == ' ' || s[0] == '\t')
593bfdaa2aSSean Callanan s.erase(0, 1);
603bfdaa2aSSean Callanan
613bfdaa2aSSean Callanan return s;
623bfdaa2aSSean Callanan }
633bfdaa2aSSean Callanan
PrintType(const Type * type,bool truncate=false)64b9c1b51eSKate Stone static std::string PrintType(const Type *type, bool truncate = false) {
653bfdaa2aSSean Callanan std::string s;
663bfdaa2aSSean Callanan raw_string_ostream rso(s);
673bfdaa2aSSean Callanan type->print(rso);
683bfdaa2aSSean Callanan rso.flush();
693bfdaa2aSSean Callanan if (truncate)
703bfdaa2aSSean Callanan s.resize(s.length() - 1);
713bfdaa2aSSean Callanan return s;
723bfdaa2aSSean Callanan }
733bfdaa2aSSean Callanan
CanIgnoreCall(const CallInst * call)74b9c1b51eSKate Stone static bool CanIgnoreCall(const CallInst *call) {
75576a4374SSean Callanan const llvm::Function *called_function = call->getCalledFunction();
76576a4374SSean Callanan
77576a4374SSean Callanan if (!called_function)
78576a4374SSean Callanan return false;
79576a4374SSean Callanan
80b9c1b51eSKate Stone if (called_function->isIntrinsic()) {
81b9c1b51eSKate Stone switch (called_function->getIntrinsicID()) {
82576a4374SSean Callanan default:
83576a4374SSean Callanan break;
84576a4374SSean Callanan case llvm::Intrinsic::dbg_declare:
85576a4374SSean Callanan case llvm::Intrinsic::dbg_value:
86576a4374SSean Callanan return true;
87576a4374SSean Callanan }
88576a4374SSean Callanan }
89576a4374SSean Callanan
90576a4374SSean Callanan return false;
91576a4374SSean Callanan }
92576a4374SSean Callanan
93b9c1b51eSKate Stone class InterpreterStackFrame {
943bfdaa2aSSean Callanan public:
9508052afaSSean Callanan typedef std::map<const Value *, lldb::addr_t> ValueMap;
9608052afaSSean Callanan
973bfdaa2aSSean Callanan ValueMap m_values;
988468dbecSMicah Villmow DataLayout &m_target_data;
997071c5fdSTed Woodward lldb_private::IRExecutionUnit &m_execution_unit;
100*28c878aeSShafik Yaghmour const BasicBlock *m_bb = nullptr;
101*28c878aeSShafik Yaghmour const BasicBlock *m_prev_bb = nullptr;
1023bfdaa2aSSean Callanan BasicBlock::const_iterator m_ii;
1033bfdaa2aSSean Callanan BasicBlock::const_iterator m_ie;
1043bfdaa2aSSean Callanan
1051582ee68SSean Callanan lldb::addr_t m_frame_process_address;
1061582ee68SSean Callanan size_t m_frame_size;
1071582ee68SSean Callanan lldb::addr_t m_stack_pointer;
1081582ee68SSean Callanan
1093bfdaa2aSSean Callanan lldb::ByteOrder m_byte_order;
1103bfdaa2aSSean Callanan size_t m_addr_byte_size;
1113bfdaa2aSSean Callanan
InterpreterStackFrame(DataLayout & target_data,lldb_private::IRExecutionUnit & execution_unit,lldb::addr_t stack_frame_bottom,lldb::addr_t stack_frame_top)1128468dbecSMicah Villmow InterpreterStackFrame(DataLayout &target_data,
1137071c5fdSTed Woodward lldb_private::IRExecutionUnit &execution_unit,
114df56540aSSean Callanan lldb::addr_t stack_frame_bottom,
115b9c1b51eSKate Stone lldb::addr_t stack_frame_top)
116*28c878aeSShafik Yaghmour : m_target_data(target_data), m_execution_unit(execution_unit) {
117b9c1b51eSKate Stone m_byte_order = (target_data.isLittleEndian() ? lldb::eByteOrderLittle
118b9c1b51eSKate Stone : lldb::eByteOrderBig);
11995769bf4SSean Callanan m_addr_byte_size = (target_data.getPointerSize(0));
1201582ee68SSean Callanan
121df56540aSSean Callanan m_frame_process_address = stack_frame_bottom;
122df56540aSSean Callanan m_frame_size = stack_frame_top - stack_frame_bottom;
123df56540aSSean Callanan m_stack_pointer = stack_frame_top;
1241582ee68SSean Callanan }
1251582ee68SSean Callanan
126fd2433e1SJonas Devlieghere ~InterpreterStackFrame() = default;
1273bfdaa2aSSean Callanan
Jump(const BasicBlock * bb)128b9c1b51eSKate Stone void Jump(const BasicBlock *bb) {
1293fe71581SMarianne Mailhot-Sarrasin m_prev_bb = m_bb;
1303bfdaa2aSSean Callanan m_bb = bb;
1313bfdaa2aSSean Callanan m_ii = m_bb->begin();
1323bfdaa2aSSean Callanan m_ie = m_bb->end();
1333bfdaa2aSSean Callanan }
1343bfdaa2aSSean Callanan
SummarizeValue(const Value * value)135b9c1b51eSKate Stone std::string SummarizeValue(const Value *value) {
1363bfdaa2aSSean Callanan lldb_private::StreamString ss;
1373bfdaa2aSSean Callanan
1383bfdaa2aSSean Callanan ss.Printf("%s", PrintValue(value).c_str());
1393bfdaa2aSSean Callanan
1403bfdaa2aSSean Callanan ValueMap::iterator i = m_values.find(value);
1413bfdaa2aSSean Callanan
142b9c1b51eSKate Stone if (i != m_values.end()) {
14308052afaSSean Callanan lldb::addr_t addr = i->second;
1443bfdaa2aSSean Callanan
14508052afaSSean Callanan ss.Printf(" 0x%llx", (unsigned long long)addr);
1463bfdaa2aSSean Callanan }
1473bfdaa2aSSean Callanan
148adcd0268SBenjamin Kramer return std::string(ss.GetString());
1493bfdaa2aSSean Callanan }
1503bfdaa2aSSean Callanan
AssignToMatchType(lldb_private::Scalar & scalar,llvm::APInt value,Type * type)151b725142cSPavel Labath bool AssignToMatchType(lldb_private::Scalar &scalar, llvm::APInt value,
152b9c1b51eSKate Stone Type *type) {
1533bfdaa2aSSean Callanan size_t type_size = m_target_data.getTypeStoreSize(type);
1543bfdaa2aSSean Callanan
155ae6ca2fcSFrederic Riss if (type_size > 8)
1563bfdaa2aSSean Callanan return false;
1573bfdaa2aSSean Callanan
158ae6ca2fcSFrederic Riss if (type_size != 1)
159ae6ca2fcSFrederic Riss type_size = PowerOf2Ceil(type_size);
160ae6ca2fcSFrederic Riss
161b725142cSPavel Labath scalar = value.zextOrTrunc(type_size * 8);
1623bfdaa2aSSean Callanan return true;
1633bfdaa2aSSean Callanan }
1643bfdaa2aSSean Callanan
EvaluateValue(lldb_private::Scalar & scalar,const Value * value,Module & module)165b9c1b51eSKate Stone bool EvaluateValue(lldb_private::Scalar &scalar, const Value *value,
166b9c1b51eSKate Stone Module &module) {
1673bfdaa2aSSean Callanan const Constant *constant = dyn_cast<Constant>(value);
1683bfdaa2aSSean Callanan
169b9c1b51eSKate Stone if (constant) {
170415422ceSSean Callanan APInt value_apint;
171415422ceSSean Callanan
172415422ceSSean Callanan if (!ResolveConstantValue(value_apint, constant))
173415422ceSSean Callanan return false;
174415422ceSSean Callanan
175b725142cSPavel Labath return AssignToMatchType(scalar, value_apint, value->getType());
176c3f0d9f3SDavide Italiano }
177c3f0d9f3SDavide Italiano
17808052afaSSean Callanan lldb::addr_t process_address = ResolveValue(value, module);
1793bfdaa2aSSean Callanan size_t value_size = m_target_data.getTypeStoreSize(value->getType());
1803bfdaa2aSSean Callanan
18108052afaSSean Callanan lldb_private::DataExtractor value_extractor;
18297206d57SZachary Turner lldb_private::Status extract_error;
18308052afaSSean Callanan
184b9c1b51eSKate Stone m_execution_unit.GetMemoryData(value_extractor, process_address,
185b9c1b51eSKate Stone value_size, extract_error);
18608052afaSSean Callanan
18708052afaSSean Callanan if (!extract_error.Success())
18808052afaSSean Callanan return false;
18908052afaSSean Callanan
190c7bece56SGreg Clayton lldb::offset_t offset = 0;
191ae6ca2fcSFrederic Riss if (value_size <= 8) {
19208052afaSSean Callanan uint64_t u64value = value_extractor.GetMaxU64(&offset, value_size);
193b725142cSPavel Labath return AssignToMatchType(scalar, llvm::APInt(64, u64value),
194b725142cSPavel Labath value->getType());
1953bfdaa2aSSean Callanan }
1963bfdaa2aSSean Callanan
1973bfdaa2aSSean Callanan return false;
1983bfdaa2aSSean Callanan }
1993bfdaa2aSSean Callanan
AssignValue(const Value * value,lldb_private::Scalar scalar,Module & module)200b725142cSPavel Labath bool AssignValue(const Value *value, lldb_private::Scalar scalar,
201b9c1b51eSKate Stone Module &module) {
20208052afaSSean Callanan lldb::addr_t process_address = ResolveValue(value, module);
20308052afaSSean Callanan
20408052afaSSean Callanan if (process_address == LLDB_INVALID_ADDRESS)
20508052afaSSean Callanan return false;
2063bfdaa2aSSean Callanan
2073bfdaa2aSSean Callanan lldb_private::Scalar cast_scalar;
2083bfdaa2aSSean Callanan
209b725142cSPavel Labath scalar.MakeUnsigned();
210b725142cSPavel Labath if (!AssignToMatchType(cast_scalar, scalar.UInt128(llvm::APInt()),
211b725142cSPavel Labath value->getType()))
2123bfdaa2aSSean Callanan return false;
2133bfdaa2aSSean Callanan
21408052afaSSean Callanan size_t value_byte_size = m_target_data.getTypeStoreSize(value->getType());
2153bfdaa2aSSean Callanan
21608052afaSSean Callanan lldb_private::DataBufferHeap buf(value_byte_size, 0);
2173bfdaa2aSSean Callanan
21897206d57SZachary Turner lldb_private::Status get_data_error;
21908052afaSSean Callanan
220b9c1b51eSKate Stone if (!cast_scalar.GetAsMemoryData(buf.GetBytes(), buf.GetByteSize(),
221b9c1b51eSKate Stone m_byte_order, get_data_error))
2223bfdaa2aSSean Callanan return false;
2233bfdaa2aSSean Callanan
22497206d57SZachary Turner lldb_private::Status write_error;
2253bfdaa2aSSean Callanan
226b9c1b51eSKate Stone m_execution_unit.WriteMemory(process_address, buf.GetBytes(),
227b9c1b51eSKate Stone buf.GetByteSize(), write_error);
2285c9737a5SGreg Clayton
22908052afaSSean Callanan return write_error.Success();
2303bfdaa2aSSean Callanan }
2313bfdaa2aSSean Callanan
ResolveConstantValue(APInt & value,const Constant * constant)232b9c1b51eSKate Stone bool ResolveConstantValue(APInt &value, const Constant *constant) {
233b9c1b51eSKate Stone switch (constant->getValueID()) {
2341582ee68SSean Callanan default:
2351582ee68SSean Callanan break;
2367071c5fdSTed Woodward case Value::FunctionVal:
237b9c1b51eSKate Stone if (const Function *constant_func = dyn_cast<Function>(constant)) {
2387071c5fdSTed Woodward lldb_private::ConstString name(constant_func->getName());
239f2128b28SJim Ingham bool missing_weak = false;
240f2128b28SJim Ingham lldb::addr_t addr = m_execution_unit.FindSymbol(name, missing_weak);
241f2128b28SJim Ingham if (addr == LLDB_INVALID_ADDRESS || missing_weak)
2427071c5fdSTed Woodward return false;
2437071c5fdSTed Woodward value = APInt(m_target_data.getPointerSizeInBits(), addr);
2447071c5fdSTed Woodward return true;
2457071c5fdSTed Woodward }
2467071c5fdSTed Woodward break;
2471582ee68SSean Callanan case Value::ConstantIntVal:
248b9c1b51eSKate Stone if (const ConstantInt *constant_int = dyn_cast<ConstantInt>(constant)) {
24994a9a39eSSean Callanan value = constant_int->getValue();
25094a9a39eSSean Callanan return true;
2513bfdaa2aSSean Callanan }
2521582ee68SSean Callanan break;
2531582ee68SSean Callanan case Value::ConstantFPVal:
254b9c1b51eSKate Stone if (const ConstantFP *constant_fp = dyn_cast<ConstantFP>(constant)) {
25594a9a39eSSean Callanan value = constant_fp->getValueAPF().bitcastToAPInt();
25694a9a39eSSean Callanan return true;
2573bfdaa2aSSean Callanan }
2581582ee68SSean Callanan break;
2591582ee68SSean Callanan case Value::ConstantExprVal:
260b9c1b51eSKate Stone if (const ConstantExpr *constant_expr =
261b9c1b51eSKate Stone dyn_cast<ConstantExpr>(constant)) {
262b9c1b51eSKate Stone switch (constant_expr->getOpcode()) {
26380c48c10SSean Callanan default:
26480c48c10SSean Callanan return false;
26580c48c10SSean Callanan case Instruction::IntToPtr:
2662abffe05SSean Callanan case Instruction::PtrToInt:
26780c48c10SSean Callanan case Instruction::BitCast:
26894a9a39eSSean Callanan return ResolveConstantValue(value, constant_expr->getOperand(0));
269b9c1b51eSKate Stone case Instruction::GetElementPtr: {
27094a9a39eSSean Callanan ConstantExpr::const_op_iterator op_cursor = constant_expr->op_begin();
27194a9a39eSSean Callanan ConstantExpr::const_op_iterator op_end = constant_expr->op_end();
27294a9a39eSSean Callanan
27394a9a39eSSean Callanan Constant *base = dyn_cast<Constant>(*op_cursor);
27494a9a39eSSean Callanan
27594a9a39eSSean Callanan if (!base)
27694a9a39eSSean Callanan return false;
27794a9a39eSSean Callanan
27894a9a39eSSean Callanan if (!ResolveConstantValue(value, base))
27994a9a39eSSean Callanan return false;
28094a9a39eSSean Callanan
28194a9a39eSSean Callanan op_cursor++;
28294a9a39eSSean Callanan
28394a9a39eSSean Callanan if (op_cursor == op_end)
28494a9a39eSSean Callanan return true; // no offset to apply!
28594a9a39eSSean Callanan
28694a9a39eSSean Callanan SmallVector<Value *, 8> indices(op_cursor, op_end);
287b9c1b51eSKate Stone Type *src_elem_ty =
288b9c1b51eSKate Stone cast<GEPOperator>(constant_expr)->getSourceElementType();
289afb446e8SAndy Yankovsky
290afb446e8SAndy Yankovsky // DataLayout::getIndexedOffsetInType assumes the indices are
291afb446e8SAndy Yankovsky // instances of ConstantInt.
292b9c1b51eSKate Stone uint64_t offset =
293b9c1b51eSKate Stone m_target_data.getIndexedOffsetInType(src_elem_ty, indices);
29494a9a39eSSean Callanan
29594a9a39eSSean Callanan const bool is_signed = true;
29694a9a39eSSean Callanan value += APInt(value.getBitWidth(), offset, is_signed);
29794a9a39eSSean Callanan
29894a9a39eSSean Callanan return true;
29994a9a39eSSean Callanan }
30080c48c10SSean Callanan }
30180c48c10SSean Callanan }
3021582ee68SSean Callanan break;
3031582ee68SSean Callanan case Value::ConstantPointerNullVal:
304b9c1b51eSKate Stone if (isa<ConstantPointerNull>(constant)) {
3051582ee68SSean Callanan value = APInt(m_target_data.getPointerSizeInBits(), 0);
3061582ee68SSean Callanan return true;
3071582ee68SSean Callanan }
3081582ee68SSean Callanan break;
3091582ee68SSean Callanan }
3103bfdaa2aSSean Callanan return false;
3113bfdaa2aSSean Callanan }
3123bfdaa2aSSean Callanan
MakeArgument(const Argument * value,uint64_t address)313b9c1b51eSKate Stone bool MakeArgument(const Argument *value, uint64_t address) {
3141582ee68SSean Callanan lldb::addr_t data_address = Malloc(value->getType());
3151582ee68SSean Callanan
3161582ee68SSean Callanan if (data_address == LLDB_INVALID_ADDRESS)
3171582ee68SSean Callanan return false;
3181582ee68SSean Callanan
31997206d57SZachary Turner lldb_private::Status write_error;
3201582ee68SSean Callanan
3217071c5fdSTed Woodward m_execution_unit.WritePointerToMemory(data_address, address, write_error);
3221582ee68SSean Callanan
323b9c1b51eSKate Stone if (!write_error.Success()) {
32497206d57SZachary Turner lldb_private::Status free_error;
3257071c5fdSTed Woodward m_execution_unit.Free(data_address, free_error);
3261582ee68SSean Callanan return false;
3271582ee68SSean Callanan }
3281582ee68SSean Callanan
3291582ee68SSean Callanan m_values[value] = data_address;
3301582ee68SSean Callanan
331a007a6d8SPavel Labath lldb_private::Log *log(GetLog(LLDBLog::Expressions));
3321582ee68SSean Callanan
333b9c1b51eSKate Stone if (log) {
33463e5fb76SJonas Devlieghere LLDB_LOGF(log, "Made an allocation for argument %s",
335b9c1b51eSKate Stone PrintValue(value).c_str());
33663e5fb76SJonas Devlieghere LLDB_LOGF(log, " Data region : %llx", (unsigned long long)address);
33763e5fb76SJonas Devlieghere LLDB_LOGF(log, " Ref region : %llx",
33863e5fb76SJonas Devlieghere (unsigned long long)data_address);
3391582ee68SSean Callanan }
3401582ee68SSean Callanan
3411582ee68SSean Callanan return true;
3421582ee68SSean Callanan }
3431582ee68SSean Callanan
ResolveConstant(lldb::addr_t process_address,const Constant * constant)344b9c1b51eSKate Stone bool ResolveConstant(lldb::addr_t process_address, const Constant *constant) {
34594a9a39eSSean Callanan APInt resolved_value;
34694a9a39eSSean Callanan
34794a9a39eSSean Callanan if (!ResolveConstantValue(resolved_value, constant))
34894a9a39eSSean Callanan return false;
34994a9a39eSSean Callanan
35094a9a39eSSean Callanan size_t constant_size = m_target_data.getTypeStoreSize(constant->getType());
3519521ad2aSUlrich Weigand lldb_private::DataBufferHeap buf(constant_size, 0);
35208052afaSSean Callanan
35397206d57SZachary Turner lldb_private::Status get_data_error;
35446fc0066SSean Callanan
355b9c1b51eSKate Stone lldb_private::Scalar resolved_scalar(
356b9c1b51eSKate Stone resolved_value.zextOrTrunc(llvm::NextPowerOf2(constant_size) * 8));
357b9c1b51eSKate Stone if (!resolved_scalar.GetAsMemoryData(buf.GetBytes(), buf.GetByteSize(),
358b9c1b51eSKate Stone m_byte_order, get_data_error))
3599521ad2aSUlrich Weigand return false;
36046fc0066SSean Callanan
36197206d57SZachary Turner lldb_private::Status write_error;
36208052afaSSean Callanan
363b9c1b51eSKate Stone m_execution_unit.WriteMemory(process_address, buf.GetBytes(),
364b9c1b51eSKate Stone buf.GetByteSize(), write_error);
36508052afaSSean Callanan
36608052afaSSean Callanan return write_error.Success();
36794a9a39eSSean Callanan }
36894a9a39eSSean Callanan
Malloc(size_t size,uint8_t byte_alignment)369b9c1b51eSKate Stone lldb::addr_t Malloc(size_t size, uint8_t byte_alignment) {
3701582ee68SSean Callanan lldb::addr_t ret = m_stack_pointer;
37108052afaSSean Callanan
3721582ee68SSean Callanan ret -= size;
3731582ee68SSean Callanan ret -= (ret % byte_alignment);
37408052afaSSean Callanan
3751582ee68SSean Callanan if (ret < m_frame_process_address)
37608052afaSSean Callanan return LLDB_INVALID_ADDRESS;
3771582ee68SSean Callanan
3781582ee68SSean Callanan m_stack_pointer = ret;
3791582ee68SSean Callanan return ret;
38008052afaSSean Callanan }
38108052afaSSean Callanan
Malloc(llvm::Type * type)382b9c1b51eSKate Stone lldb::addr_t Malloc(llvm::Type *type) {
38397206d57SZachary Turner lldb_private::Status alloc_error;
38408052afaSSean Callanan
385b9c1b51eSKate Stone return Malloc(m_target_data.getTypeAllocSize(type),
386b9c1b51eSKate Stone m_target_data.getPrefTypeAlignment(type));
38708052afaSSean Callanan }
38808052afaSSean Callanan
PrintData(lldb::addr_t addr,llvm::Type * type)389b9c1b51eSKate Stone std::string PrintData(lldb::addr_t addr, llvm::Type *type) {
39008052afaSSean Callanan size_t length = m_target_data.getTypeStoreSize(type);
39108052afaSSean Callanan
39208052afaSSean Callanan lldb_private::DataBufferHeap buf(length, 0);
39308052afaSSean Callanan
39497206d57SZachary Turner lldb_private::Status read_error;
39508052afaSSean Callanan
3967071c5fdSTed Woodward m_execution_unit.ReadMemory(buf.GetBytes(), addr, length, read_error);
39708052afaSSean Callanan
39808052afaSSean Callanan if (!read_error.Success())
39908052afaSSean Callanan return std::string("<couldn't read data>");
40008052afaSSean Callanan
40108052afaSSean Callanan lldb_private::StreamString ss;
40208052afaSSean Callanan
403b9c1b51eSKate Stone for (size_t i = 0; i < length; i++) {
40408052afaSSean Callanan if ((!(i & 0xf)) && i)
40508052afaSSean Callanan ss.Printf("%02hhx - ", buf.GetBytes()[i]);
40608052afaSSean Callanan else
40708052afaSSean Callanan ss.Printf("%02hhx ", buf.GetBytes()[i]);
40808052afaSSean Callanan }
40908052afaSSean Callanan
410adcd0268SBenjamin Kramer return std::string(ss.GetString());
41108052afaSSean Callanan }
41208052afaSSean Callanan
ResolveValue(const Value * value,Module & module)413b9c1b51eSKate Stone lldb::addr_t ResolveValue(const Value *value, Module &module) {
4143bfdaa2aSSean Callanan ValueMap::iterator i = m_values.find(value);
4153bfdaa2aSSean Callanan
4163bfdaa2aSSean Callanan if (i != m_values.end())
4173bfdaa2aSSean Callanan return i->second;
4183bfdaa2aSSean Callanan
4191582ee68SSean Callanan // Fall back and allocate space [allocation type Alloca]
4201582ee68SSean Callanan
4211582ee68SSean Callanan lldb::addr_t data_address = Malloc(value->getType());
4221582ee68SSean Callanan
423b9c1b51eSKate Stone if (const Constant *constant = dyn_cast<Constant>(value)) {
424b9c1b51eSKate Stone if (!ResolveConstant(data_address, constant)) {
42597206d57SZachary Turner lldb_private::Status free_error;
4267071c5fdSTed Woodward m_execution_unit.Free(data_address, free_error);
4271582ee68SSean Callanan return LLDB_INVALID_ADDRESS;
4281582ee68SSean Callanan }
4291582ee68SSean Callanan }
4301582ee68SSean Callanan
4311582ee68SSean Callanan m_values[value] = data_address;
4321582ee68SSean Callanan return data_address;
4333bfdaa2aSSean Callanan }
4343bfdaa2aSSean Callanan };
4353bfdaa2aSSean Callanan
436b9c1b51eSKate Stone static const char *unsupported_opcode_error =
437b9c1b51eSKate Stone "Interpreter doesn't handle one of the expression's opcodes";
438b9c1b51eSKate Stone static const char *unsupported_operand_error =
439b9c1b51eSKate Stone "Interpreter doesn't handle one of the expression's operands";
440b9c1b51eSKate Stone static const char *interpreter_internal_error =
441b9c1b51eSKate Stone "Interpreter encountered an internal error";
442b9c1b51eSKate Stone static const char *bad_value_error =
443b9c1b51eSKate Stone "Interpreter couldn't resolve a value during execution";
444b9c1b51eSKate Stone static const char *memory_allocation_error =
445b9c1b51eSKate Stone "Interpreter couldn't allocate memory";
446175a0d04SSean Callanan static const char *memory_write_error = "Interpreter couldn't write to memory";
447175a0d04SSean Callanan static const char *memory_read_error = "Interpreter couldn't read from memory";
448175a0d04SSean Callanan static const char *infinite_loop_error = "Interpreter ran for too many cycles";
449b9c1b51eSKate Stone static const char *too_many_functions_error =
450b9c1b51eSKate Stone "Interpreter doesn't handle modules with multiple function bodies.";
451175a0d04SSean Callanan
CanResolveConstant(llvm::Constant * constant)452b9c1b51eSKate Stone static bool CanResolveConstant(llvm::Constant *constant) {
453b9c1b51eSKate Stone switch (constant->getValueID()) {
4548c62daf2SSean Callanan default:
4558c62daf2SSean Callanan return false;
4568c62daf2SSean Callanan case Value::ConstantIntVal:
4578c62daf2SSean Callanan case Value::ConstantFPVal:
4587071c5fdSTed Woodward case Value::FunctionVal:
4598c62daf2SSean Callanan return true;
4608c62daf2SSean Callanan case Value::ConstantExprVal:
461b9c1b51eSKate Stone if (const ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(constant)) {
462b9c1b51eSKate Stone switch (constant_expr->getOpcode()) {
4638c62daf2SSean Callanan default:
4648c62daf2SSean Callanan return false;
4658c62daf2SSean Callanan case Instruction::IntToPtr:
4668c62daf2SSean Callanan case Instruction::PtrToInt:
4678c62daf2SSean Callanan case Instruction::BitCast:
4688c62daf2SSean Callanan return CanResolveConstant(constant_expr->getOperand(0));
469b9c1b51eSKate Stone case Instruction::GetElementPtr: {
470afb446e8SAndy Yankovsky // Check that the base can be constant-resolved.
4718c62daf2SSean Callanan ConstantExpr::const_op_iterator op_cursor = constant_expr->op_begin();
4728c62daf2SSean Callanan Constant *base = dyn_cast<Constant>(*op_cursor);
473afb446e8SAndy Yankovsky if (!base || !CanResolveConstant(base))
4748c62daf2SSean Callanan return false;
4758c62daf2SSean Callanan
476afb446e8SAndy Yankovsky // Check that all other operands are just ConstantInt.
477afb446e8SAndy Yankovsky for (Value *op : make_range(constant_expr->op_begin() + 1,
478afb446e8SAndy Yankovsky constant_expr->op_end())) {
479afb446e8SAndy Yankovsky ConstantInt *constant_int = dyn_cast<ConstantInt>(op);
480afb446e8SAndy Yankovsky if (!constant_int)
481afb446e8SAndy Yankovsky return false;
482afb446e8SAndy Yankovsky }
483afb446e8SAndy Yankovsky return true;
4848c62daf2SSean Callanan }
4858c62daf2SSean Callanan }
4868c62daf2SSean Callanan } else {
4878c62daf2SSean Callanan return false;
4888c62daf2SSean Callanan }
4898c62daf2SSean Callanan case Value::ConstantPointerNullVal:
4908c62daf2SSean Callanan return true;
4918c62daf2SSean Callanan }
4928c62daf2SSean Callanan }
4938c62daf2SSean Callanan
CanInterpret(llvm::Module & module,llvm::Function & function,lldb_private::Status & error,const bool support_function_calls)494b9c1b51eSKate Stone bool IRInterpreter::CanInterpret(llvm::Module &module, llvm::Function &function,
49597206d57SZachary Turner lldb_private::Status &error,
496b9c1b51eSKate Stone const bool support_function_calls) {
497a007a6d8SPavel Labath lldb_private::Log *log(GetLog(LLDBLog::Expressions));
4983bfdaa2aSSean Callanan
49985fc8761SSean Callanan bool saw_function_with_body = false;
500af4adb07SRaphael Isemann for (Function &f : module) {
501af4adb07SRaphael Isemann if (f.begin() != f.end()) {
502b9c1b51eSKate Stone if (saw_function_with_body) {
50363e5fb76SJonas Devlieghere LLDB_LOGF(log, "More than one function in the module has a body");
5043f998107SAdrian McCarthy error.SetErrorToGenericError();
5053f998107SAdrian McCarthy error.SetErrorString(too_many_functions_error);
50685fc8761SSean Callanan return false;
5073f998107SAdrian McCarthy }
50885fc8761SSean Callanan saw_function_with_body = true;
50985fc8761SSean Callanan }
51085fc8761SSean Callanan }
51185fc8761SSean Callanan
512af4adb07SRaphael Isemann for (BasicBlock &bb : function) {
513af4adb07SRaphael Isemann for (Instruction &ii : bb) {
514af4adb07SRaphael Isemann switch (ii.getOpcode()) {
515b9c1b51eSKate Stone default: {
516af4adb07SRaphael Isemann LLDB_LOGF(log, "Unsupported instruction: %s", PrintValue(&ii).c_str());
51744342735SSean Callanan error.SetErrorToGenericError();
51844342735SSean Callanan error.SetErrorString(unsupported_opcode_error);
5193bfdaa2aSSean Callanan return false;
5203bfdaa2aSSean Callanan }
5213bfdaa2aSSean Callanan case Instruction::Add:
5223bfdaa2aSSean Callanan case Instruction::Alloca:
5233bfdaa2aSSean Callanan case Instruction::BitCast:
5243bfdaa2aSSean Callanan case Instruction::Br:
5253fe71581SMarianne Mailhot-Sarrasin case Instruction::PHI:
526576a4374SSean Callanan break;
527b9c1b51eSKate Stone case Instruction::Call: {
528af4adb07SRaphael Isemann CallInst *call_inst = dyn_cast<CallInst>(&ii);
529576a4374SSean Callanan
530b9c1b51eSKate Stone if (!call_inst) {
531576a4374SSean Callanan error.SetErrorToGenericError();
532576a4374SSean Callanan error.SetErrorString(interpreter_internal_error);
533576a4374SSean Callanan return false;
534576a4374SSean Callanan }
535576a4374SSean Callanan
536b9c1b51eSKate Stone if (!CanIgnoreCall(call_inst) && !support_function_calls) {
53763e5fb76SJonas Devlieghere LLDB_LOGF(log, "Unsupported instruction: %s",
538af4adb07SRaphael Isemann PrintValue(&ii).c_str());
539576a4374SSean Callanan error.SetErrorToGenericError();
540576a4374SSean Callanan error.SetErrorString(unsupported_opcode_error);
541576a4374SSean Callanan return false;
542576a4374SSean Callanan }
543b9c1b51eSKate Stone } break;
5443bfdaa2aSSean Callanan case Instruction::GetElementPtr:
5453bfdaa2aSSean Callanan break;
546b9c1b51eSKate Stone case Instruction::ICmp: {
547af4adb07SRaphael Isemann ICmpInst *icmp_inst = dyn_cast<ICmpInst>(&ii);
5483bfdaa2aSSean Callanan
549b9c1b51eSKate Stone if (!icmp_inst) {
55044342735SSean Callanan error.SetErrorToGenericError();
55144342735SSean Callanan error.SetErrorString(interpreter_internal_error);
5523bfdaa2aSSean Callanan return false;
553175a0d04SSean Callanan }
5543bfdaa2aSSean Callanan
555b9c1b51eSKate Stone switch (icmp_inst->getPredicate()) {
556b9c1b51eSKate Stone default: {
55763e5fb76SJonas Devlieghere LLDB_LOGF(log, "Unsupported ICmp predicate: %s",
558af4adb07SRaphael Isemann PrintValue(&ii).c_str());
559175a0d04SSean Callanan
56044342735SSean Callanan error.SetErrorToGenericError();
56144342735SSean Callanan error.SetErrorString(unsupported_opcode_error);
5623bfdaa2aSSean Callanan return false;
5633bfdaa2aSSean Callanan }
5643bfdaa2aSSean Callanan case CmpInst::ICMP_EQ:
5653bfdaa2aSSean Callanan case CmpInst::ICMP_NE:
5663bfdaa2aSSean Callanan case CmpInst::ICMP_UGT:
5673bfdaa2aSSean Callanan case CmpInst::ICMP_UGE:
5683bfdaa2aSSean Callanan case CmpInst::ICMP_ULT:
5693bfdaa2aSSean Callanan case CmpInst::ICMP_ULE:
5703bfdaa2aSSean Callanan case CmpInst::ICMP_SGT:
5713bfdaa2aSSean Callanan case CmpInst::ICMP_SGE:
5723bfdaa2aSSean Callanan case CmpInst::ICMP_SLT:
5733bfdaa2aSSean Callanan case CmpInst::ICMP_SLE:
5743bfdaa2aSSean Callanan break;
5753bfdaa2aSSean Callanan }
576b9c1b51eSKate Stone } break;
577087f437bSSean Callanan case Instruction::And:
578087f437bSSean Callanan case Instruction::AShr:
57980c48c10SSean Callanan case Instruction::IntToPtr:
5802abffe05SSean Callanan case Instruction::PtrToInt:
5813bfdaa2aSSean Callanan case Instruction::Load:
582087f437bSSean Callanan case Instruction::LShr:
5833bfdaa2aSSean Callanan case Instruction::Mul:
584087f437bSSean Callanan case Instruction::Or:
5853bfdaa2aSSean Callanan case Instruction::Ret:
5863bfdaa2aSSean Callanan case Instruction::SDiv:
587415422ceSSean Callanan case Instruction::SExt:
588087f437bSSean Callanan case Instruction::Shl:
589f466a6edSSean Callanan case Instruction::SRem:
5903bfdaa2aSSean Callanan case Instruction::Store:
5913bfdaa2aSSean Callanan case Instruction::Sub:
5928c46bacaSSean Callanan case Instruction::Trunc:
5933bfdaa2aSSean Callanan case Instruction::UDiv:
594f466a6edSSean Callanan case Instruction::URem:
595087f437bSSean Callanan case Instruction::Xor:
5961ef77434SSean Callanan case Instruction::ZExt:
5973bfdaa2aSSean Callanan break;
5983bfdaa2aSSean Callanan }
5993fa3e65dSSean Callanan
600af4adb07SRaphael Isemann for (unsigned oi = 0, oe = ii.getNumOperands(); oi != oe; ++oi) {
601af4adb07SRaphael Isemann Value *operand = ii.getOperand(oi);
6023fa3e65dSSean Callanan Type *operand_type = operand->getType();
6033fa3e65dSSean Callanan
604d405d279SDavide Italiano switch (operand_type->getTypeID()) {
605d405d279SDavide Italiano default:
606d405d279SDavide Italiano break;
6072dea3f12SChristopher Tetreault case Type::FixedVectorTyID:
6082dea3f12SChristopher Tetreault case Type::ScalableVectorTyID: {
60963e5fb76SJonas Devlieghere LLDB_LOGF(log, "Unsupported operand type: %s",
610b9c1b51eSKate Stone PrintType(operand_type).c_str());
6113fa3e65dSSean Callanan error.SetErrorString(unsupported_operand_error);
6123fa3e65dSSean Callanan return false;
613d405d279SDavide Italiano }
614d405d279SDavide Italiano }
6158c62daf2SSean Callanan
6165f6789efSDavide Italiano // The IR interpreter currently doesn't know about
6175f6789efSDavide Italiano // 128-bit integers. As they're not that frequent,
6185f6789efSDavide Italiano // we can just fall back to the JIT rather than
6195f6789efSDavide Italiano // choking.
6205f6789efSDavide Italiano if (operand_type->getPrimitiveSizeInBits() > 64) {
62163e5fb76SJonas Devlieghere LLDB_LOGF(log, "Unsupported operand type: %s",
6225f6789efSDavide Italiano PrintType(operand_type).c_str());
6235f6789efSDavide Italiano error.SetErrorString(unsupported_operand_error);
6245f6789efSDavide Italiano return false;
6255f6789efSDavide Italiano }
6265f6789efSDavide Italiano
627d405d279SDavide Italiano if (Constant *constant = llvm::dyn_cast<Constant>(operand)) {
628b9c1b51eSKate Stone if (!CanResolveConstant(constant)) {
62963e5fb76SJonas Devlieghere LLDB_LOGF(log, "Unsupported constant: %s",
630b9c1b51eSKate Stone PrintValue(constant).c_str());
6318c62daf2SSean Callanan error.SetErrorString(unsupported_operand_error);
6328c62daf2SSean Callanan return false;
6338c62daf2SSean Callanan }
6348c62daf2SSean Callanan }
6353fa3e65dSSean Callanan }
6363fa3e65dSSean Callanan }
6373fa3e65dSSean Callanan }
6383bfdaa2aSSean Callanan
6393f998107SAdrian McCarthy return true;
6403f998107SAdrian McCarthy }
64114cb2aaaSSean Callanan
Interpret(llvm::Module & module,llvm::Function & function,llvm::ArrayRef<lldb::addr_t> args,lldb_private::IRExecutionUnit & execution_unit,lldb_private::Status & error,lldb::addr_t stack_frame_bottom,lldb::addr_t stack_frame_top,lldb_private::ExecutionContext & exe_ctx)642b9c1b51eSKate Stone bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function,
6431582ee68SSean Callanan llvm::ArrayRef<lldb::addr_t> args,
6447071c5fdSTed Woodward lldb_private::IRExecutionUnit &execution_unit,
64597206d57SZachary Turner lldb_private::Status &error,
646df56540aSSean Callanan lldb::addr_t stack_frame_bottom,
64790ff7911SEwan Crawford lldb::addr_t stack_frame_top,
648b9c1b51eSKate Stone lldb_private::ExecutionContext &exe_ctx) {
649a007a6d8SPavel Labath lldb_private::Log *log(GetLog(LLDBLog::Expressions));
65014cb2aaaSSean Callanan
651b9c1b51eSKate Stone if (log) {
6521582ee68SSean Callanan std::string s;
6531582ee68SSean Callanan raw_string_ostream oss(s);
6541582ee68SSean Callanan
655248a1305SKonrad Kleine module.print(oss, nullptr);
6561582ee68SSean Callanan
6571582ee68SSean Callanan oss.flush();
6581582ee68SSean Callanan
65963e5fb76SJonas Devlieghere LLDB_LOGF(log, "Module as passed in to IRInterpreter::Interpret: \n\"%s\"",
660b9c1b51eSKate Stone s.c_str());
6611582ee68SSean Callanan }
6621582ee68SSean Callanan
66314cb2aaaSSean Callanan DataLayout data_layout(&module);
66414cb2aaaSSean Callanan
665b9c1b51eSKate Stone InterpreterStackFrame frame(data_layout, execution_unit, stack_frame_bottom,
666b9c1b51eSKate Stone stack_frame_top);
66714cb2aaaSSean Callanan
668b9c1b51eSKate Stone if (frame.m_frame_process_address == LLDB_INVALID_ADDRESS) {
6691582ee68SSean Callanan error.SetErrorString("Couldn't allocate stack frame");
6701582ee68SSean Callanan }
6711582ee68SSean Callanan
6721582ee68SSean Callanan int arg_index = 0;
6731582ee68SSean Callanan
674b9c1b51eSKate Stone for (llvm::Function::arg_iterator ai = function.arg_begin(),
675b9c1b51eSKate Stone ae = function.arg_end();
676b9c1b51eSKate Stone ai != ae; ++ai, ++arg_index) {
677b9c1b51eSKate Stone if (args.size() <= static_cast<size_t>(arg_index)) {
6781582ee68SSean Callanan error.SetErrorString("Not enough arguments passed in to function");
6791582ee68SSean Callanan return false;
6801582ee68SSean Callanan }
6811582ee68SSean Callanan
6821582ee68SSean Callanan lldb::addr_t ptr = args[arg_index];
6831582ee68SSean Callanan
68433e43ca6SDuncan P. N. Exon Smith frame.MakeArgument(&*ai, ptr);
6851582ee68SSean Callanan }
6861582ee68SSean Callanan
68714cb2aaaSSean Callanan uint32_t num_insts = 0;
68814cb2aaaSSean Callanan
68933e43ca6SDuncan P. N. Exon Smith frame.Jump(&function.front());
69014cb2aaaSSean Callanan
691b9c1b51eSKate Stone while (frame.m_ii != frame.m_ie && (++num_insts < 4096)) {
69233e43ca6SDuncan P. N. Exon Smith const Instruction *inst = &*frame.m_ii;
69314cb2aaaSSean Callanan
69463e5fb76SJonas Devlieghere LLDB_LOGF(log, "Interpreting %s", PrintValue(inst).c_str());
69514cb2aaaSSean Callanan
696b9c1b51eSKate Stone switch (inst->getOpcode()) {
69714cb2aaaSSean Callanan default:
69814cb2aaaSSean Callanan break;
699576a4374SSean Callanan
70014cb2aaaSSean Callanan case Instruction::Add:
70114cb2aaaSSean Callanan case Instruction::Sub:
70214cb2aaaSSean Callanan case Instruction::Mul:
70314cb2aaaSSean Callanan case Instruction::SDiv:
70414cb2aaaSSean Callanan case Instruction::UDiv:
70514cb2aaaSSean Callanan case Instruction::SRem:
70614cb2aaaSSean Callanan case Instruction::URem:
70714cb2aaaSSean Callanan case Instruction::Shl:
70814cb2aaaSSean Callanan case Instruction::LShr:
70914cb2aaaSSean Callanan case Instruction::AShr:
71014cb2aaaSSean Callanan case Instruction::And:
71114cb2aaaSSean Callanan case Instruction::Or:
712b9c1b51eSKate Stone case Instruction::Xor: {
71314cb2aaaSSean Callanan const BinaryOperator *bin_op = dyn_cast<BinaryOperator>(inst);
71414cb2aaaSSean Callanan
715b9c1b51eSKate Stone if (!bin_op) {
71663e5fb76SJonas Devlieghere LLDB_LOGF(
71763e5fb76SJonas Devlieghere log,
718b9c1b51eSKate Stone "getOpcode() returns %s, but instruction is not a BinaryOperator",
719b9c1b51eSKate Stone inst->getOpcodeName());
72014cb2aaaSSean Callanan error.SetErrorToGenericError();
72114cb2aaaSSean Callanan error.SetErrorString(interpreter_internal_error);
72214cb2aaaSSean Callanan return false;
72314cb2aaaSSean Callanan }
72414cb2aaaSSean Callanan
72514cb2aaaSSean Callanan Value *lhs = inst->getOperand(0);
72614cb2aaaSSean Callanan Value *rhs = inst->getOperand(1);
72714cb2aaaSSean Callanan
72814cb2aaaSSean Callanan lldb_private::Scalar L;
72914cb2aaaSSean Callanan lldb_private::Scalar R;
73014cb2aaaSSean Callanan
731b9c1b51eSKate Stone if (!frame.EvaluateValue(L, lhs, module)) {
73263e5fb76SJonas Devlieghere LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(lhs).c_str());
73314cb2aaaSSean Callanan error.SetErrorToGenericError();
73414cb2aaaSSean Callanan error.SetErrorString(bad_value_error);
73514cb2aaaSSean Callanan return false;
73614cb2aaaSSean Callanan }
73714cb2aaaSSean Callanan
738b9c1b51eSKate Stone if (!frame.EvaluateValue(R, rhs, module)) {
73963e5fb76SJonas Devlieghere LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(rhs).c_str());
74014cb2aaaSSean Callanan error.SetErrorToGenericError();
74114cb2aaaSSean Callanan error.SetErrorString(bad_value_error);
74214cb2aaaSSean Callanan return false;
74314cb2aaaSSean Callanan }
74414cb2aaaSSean Callanan
74514cb2aaaSSean Callanan lldb_private::Scalar result;
74614cb2aaaSSean Callanan
747b9c1b51eSKate Stone switch (inst->getOpcode()) {
74814cb2aaaSSean Callanan default:
74914cb2aaaSSean Callanan break;
75014cb2aaaSSean Callanan case Instruction::Add:
75114cb2aaaSSean Callanan result = L + R;
75214cb2aaaSSean Callanan break;
75314cb2aaaSSean Callanan case Instruction::Mul:
75414cb2aaaSSean Callanan result = L * R;
75514cb2aaaSSean Callanan break;
75614cb2aaaSSean Callanan case Instruction::Sub:
75714cb2aaaSSean Callanan result = L - R;
75814cb2aaaSSean Callanan break;
75914cb2aaaSSean Callanan case Instruction::SDiv:
7600b342b6dSSean Callanan L.MakeSigned();
7610b342b6dSSean Callanan R.MakeSigned();
76214cb2aaaSSean Callanan result = L / R;
76314cb2aaaSSean Callanan break;
76414cb2aaaSSean Callanan case Instruction::UDiv:
7659521ad2aSUlrich Weigand L.MakeUnsigned();
7669521ad2aSUlrich Weigand R.MakeUnsigned();
7679521ad2aSUlrich Weigand result = L / R;
76814cb2aaaSSean Callanan break;
76914cb2aaaSSean Callanan case Instruction::SRem:
7700b342b6dSSean Callanan L.MakeSigned();
7710b342b6dSSean Callanan R.MakeSigned();
77214cb2aaaSSean Callanan result = L % R;
77314cb2aaaSSean Callanan break;
77414cb2aaaSSean Callanan case Instruction::URem:
7759521ad2aSUlrich Weigand L.MakeUnsigned();
7769521ad2aSUlrich Weigand R.MakeUnsigned();
7779521ad2aSUlrich Weigand result = L % R;
77814cb2aaaSSean Callanan break;
77914cb2aaaSSean Callanan case Instruction::Shl:
78014cb2aaaSSean Callanan result = L << R;
78114cb2aaaSSean Callanan break;
78214cb2aaaSSean Callanan case Instruction::AShr:
78314cb2aaaSSean Callanan result = L >> R;
78414cb2aaaSSean Callanan break;
78514cb2aaaSSean Callanan case Instruction::LShr:
78614cb2aaaSSean Callanan result = L;
78714cb2aaaSSean Callanan result.ShiftRightLogical(R);
78814cb2aaaSSean Callanan break;
78914cb2aaaSSean Callanan case Instruction::And:
79014cb2aaaSSean Callanan result = L & R;
79114cb2aaaSSean Callanan break;
79214cb2aaaSSean Callanan case Instruction::Or:
79314cb2aaaSSean Callanan result = L | R;
79414cb2aaaSSean Callanan break;
79514cb2aaaSSean Callanan case Instruction::Xor:
79614cb2aaaSSean Callanan result = L ^ R;
79714cb2aaaSSean Callanan break;
79814cb2aaaSSean Callanan }
79914cb2aaaSSean Callanan
80014cb2aaaSSean Callanan frame.AssignValue(inst, result, module);
80114cb2aaaSSean Callanan
802b9c1b51eSKate Stone if (log) {
80363e5fb76SJonas Devlieghere LLDB_LOGF(log, "Interpreted a %s", inst->getOpcodeName());
80463e5fb76SJonas Devlieghere LLDB_LOGF(log, " L : %s", frame.SummarizeValue(lhs).c_str());
80563e5fb76SJonas Devlieghere LLDB_LOGF(log, " R : %s", frame.SummarizeValue(rhs).c_str());
80663e5fb76SJonas Devlieghere LLDB_LOGF(log, " = : %s", frame.SummarizeValue(inst).c_str());
80714cb2aaaSSean Callanan }
808b9c1b51eSKate Stone } break;
809b9c1b51eSKate Stone case Instruction::Alloca: {
810f18370feSRaphael Isemann const AllocaInst *alloca_inst = cast<AllocaInst>(inst);
81114cb2aaaSSean Callanan
812b9c1b51eSKate Stone if (alloca_inst->isArrayAllocation()) {
81363e5fb76SJonas Devlieghere LLDB_LOGF(log,
814b9c1b51eSKate Stone "AllocaInsts are not handled if isArrayAllocation() is true");
81514cb2aaaSSean Callanan error.SetErrorToGenericError();
81614cb2aaaSSean Callanan error.SetErrorString(unsupported_opcode_error);
81714cb2aaaSSean Callanan return false;
81814cb2aaaSSean Callanan }
81914cb2aaaSSean Callanan
82014cb2aaaSSean Callanan // The semantics of Alloca are:
821b9c1b51eSKate Stone // Create a region R of virtual memory of type T, backed by a data
822b9c1b51eSKate Stone // buffer
823b9c1b51eSKate Stone // Create a region P of virtual memory of type T*, backed by a data
824b9c1b51eSKate Stone // buffer
82514cb2aaaSSean Callanan // Write the virtual address of R into P
82614cb2aaaSSean Callanan
82714cb2aaaSSean Callanan Type *T = alloca_inst->getAllocatedType();
82814cb2aaaSSean Callanan Type *Tptr = alloca_inst->getType();
82914cb2aaaSSean Callanan
83014cb2aaaSSean Callanan lldb::addr_t R = frame.Malloc(T);
83114cb2aaaSSean Callanan
832b9c1b51eSKate Stone if (R == LLDB_INVALID_ADDRESS) {
83363e5fb76SJonas Devlieghere LLDB_LOGF(log, "Couldn't allocate memory for an AllocaInst");
83414cb2aaaSSean Callanan error.SetErrorToGenericError();
83514cb2aaaSSean Callanan error.SetErrorString(memory_allocation_error);
83614cb2aaaSSean Callanan return false;
83714cb2aaaSSean Callanan }
83814cb2aaaSSean Callanan
83914cb2aaaSSean Callanan lldb::addr_t P = frame.Malloc(Tptr);
84014cb2aaaSSean Callanan
841b9c1b51eSKate Stone if (P == LLDB_INVALID_ADDRESS) {
84263e5fb76SJonas Devlieghere LLDB_LOGF(log,
84363e5fb76SJonas Devlieghere "Couldn't allocate the result pointer for an AllocaInst");
84414cb2aaaSSean Callanan error.SetErrorToGenericError();
84514cb2aaaSSean Callanan error.SetErrorString(memory_allocation_error);
84614cb2aaaSSean Callanan return false;
84714cb2aaaSSean Callanan }
84814cb2aaaSSean Callanan
84997206d57SZachary Turner lldb_private::Status write_error;
85014cb2aaaSSean Callanan
8517071c5fdSTed Woodward execution_unit.WritePointerToMemory(P, R, write_error);
85214cb2aaaSSean Callanan
853b9c1b51eSKate Stone if (!write_error.Success()) {
85463e5fb76SJonas Devlieghere LLDB_LOGF(log, "Couldn't write the result pointer for an AllocaInst");
85514cb2aaaSSean Callanan error.SetErrorToGenericError();
85614cb2aaaSSean Callanan error.SetErrorString(memory_write_error);
85797206d57SZachary Turner lldb_private::Status free_error;
8587071c5fdSTed Woodward execution_unit.Free(P, free_error);
8597071c5fdSTed Woodward execution_unit.Free(R, free_error);
86014cb2aaaSSean Callanan return false;
86114cb2aaaSSean Callanan }
86214cb2aaaSSean Callanan
86314cb2aaaSSean Callanan frame.m_values[alloca_inst] = P;
86414cb2aaaSSean Callanan
865b9c1b51eSKate Stone if (log) {
86663e5fb76SJonas Devlieghere LLDB_LOGF(log, "Interpreted an AllocaInst");
86763e5fb76SJonas Devlieghere LLDB_LOGF(log, " R : 0x%" PRIx64, R);
86863e5fb76SJonas Devlieghere LLDB_LOGF(log, " P : 0x%" PRIx64, P);
86914cb2aaaSSean Callanan }
870b9c1b51eSKate Stone } break;
87114cb2aaaSSean Callanan case Instruction::BitCast:
872b9c1b51eSKate Stone case Instruction::ZExt: {
873f18370feSRaphael Isemann const CastInst *cast_inst = cast<CastInst>(inst);
87414cb2aaaSSean Callanan
87514cb2aaaSSean Callanan Value *source = cast_inst->getOperand(0);
87614cb2aaaSSean Callanan
87714cb2aaaSSean Callanan lldb_private::Scalar S;
87814cb2aaaSSean Callanan
879b9c1b51eSKate Stone if (!frame.EvaluateValue(S, source, module)) {
88063e5fb76SJonas Devlieghere LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(source).c_str());
88114cb2aaaSSean Callanan error.SetErrorToGenericError();
88214cb2aaaSSean Callanan error.SetErrorString(bad_value_error);
88314cb2aaaSSean Callanan return false;
88414cb2aaaSSean Callanan }
88514cb2aaaSSean Callanan
88614cb2aaaSSean Callanan frame.AssignValue(inst, S, module);
887b9c1b51eSKate Stone } break;
888b9c1b51eSKate Stone case Instruction::SExt: {
889f18370feSRaphael Isemann const CastInst *cast_inst = cast<CastInst>(inst);
890415422ceSSean Callanan
891415422ceSSean Callanan Value *source = cast_inst->getOperand(0);
892415422ceSSean Callanan
893415422ceSSean Callanan lldb_private::Scalar S;
894415422ceSSean Callanan
895b9c1b51eSKate Stone if (!frame.EvaluateValue(S, source, module)) {
89663e5fb76SJonas Devlieghere LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(source).c_str());
897415422ceSSean Callanan error.SetErrorToGenericError();
898415422ceSSean Callanan error.SetErrorString(bad_value_error);
899415422ceSSean Callanan return false;
900415422ceSSean Callanan }
901415422ceSSean Callanan
902415422ceSSean Callanan S.MakeSigned();
903415422ceSSean Callanan
904415422ceSSean Callanan lldb_private::Scalar S_signextend(S.SLongLong());
905415422ceSSean Callanan
906415422ceSSean Callanan frame.AssignValue(inst, S_signextend, module);
907b9c1b51eSKate Stone } break;
908b9c1b51eSKate Stone case Instruction::Br: {
909f18370feSRaphael Isemann const BranchInst *br_inst = cast<BranchInst>(inst);
91014cb2aaaSSean Callanan
911b9c1b51eSKate Stone if (br_inst->isConditional()) {
91214cb2aaaSSean Callanan Value *condition = br_inst->getCondition();
91314cb2aaaSSean Callanan
91414cb2aaaSSean Callanan lldb_private::Scalar C;
91514cb2aaaSSean Callanan
916b9c1b51eSKate Stone if (!frame.EvaluateValue(C, condition, module)) {
91763e5fb76SJonas Devlieghere LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(condition).c_str());
91814cb2aaaSSean Callanan error.SetErrorToGenericError();
91914cb2aaaSSean Callanan error.SetErrorString(bad_value_error);
92014cb2aaaSSean Callanan return false;
92114cb2aaaSSean Callanan }
92214cb2aaaSSean Callanan
9239521ad2aSUlrich Weigand if (!C.IsZero())
92414cb2aaaSSean Callanan frame.Jump(br_inst->getSuccessor(0));
92514cb2aaaSSean Callanan else
92614cb2aaaSSean Callanan frame.Jump(br_inst->getSuccessor(1));
92714cb2aaaSSean Callanan
928b9c1b51eSKate Stone if (log) {
92963e5fb76SJonas Devlieghere LLDB_LOGF(log, "Interpreted a BrInst with a condition");
93063e5fb76SJonas Devlieghere LLDB_LOGF(log, " cond : %s",
93163e5fb76SJonas Devlieghere frame.SummarizeValue(condition).c_str());
93214cb2aaaSSean Callanan }
933b9c1b51eSKate Stone } else {
93414cb2aaaSSean Callanan frame.Jump(br_inst->getSuccessor(0));
93514cb2aaaSSean Callanan
936b9c1b51eSKate Stone if (log) {
93763e5fb76SJonas Devlieghere LLDB_LOGF(log, "Interpreted a BrInst with no condition");
93814cb2aaaSSean Callanan }
93914cb2aaaSSean Callanan }
94014cb2aaaSSean Callanan }
94114cb2aaaSSean Callanan continue;
942b9c1b51eSKate Stone case Instruction::PHI: {
943f18370feSRaphael Isemann const PHINode *phi_inst = cast<PHINode>(inst);
944b9c1b51eSKate Stone if (!frame.m_prev_bb) {
94563e5fb76SJonas Devlieghere LLDB_LOGF(log,
94663e5fb76SJonas Devlieghere "Encountered PHI node without having jumped from another "
947b9c1b51eSKate Stone "basic block");
9483fe71581SMarianne Mailhot-Sarrasin error.SetErrorToGenericError();
9493fe71581SMarianne Mailhot-Sarrasin error.SetErrorString(interpreter_internal_error);
9503fe71581SMarianne Mailhot-Sarrasin return false;
9513fe71581SMarianne Mailhot-Sarrasin }
9523fe71581SMarianne Mailhot-Sarrasin
9533fe71581SMarianne Mailhot-Sarrasin Value *value = phi_inst->getIncomingValueForBlock(frame.m_prev_bb);
9543fe71581SMarianne Mailhot-Sarrasin lldb_private::Scalar result;
955b9c1b51eSKate Stone if (!frame.EvaluateValue(result, value, module)) {
95663e5fb76SJonas Devlieghere LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(value).c_str());
9573fe71581SMarianne Mailhot-Sarrasin error.SetErrorToGenericError();
9583fe71581SMarianne Mailhot-Sarrasin error.SetErrorString(bad_value_error);
9593fe71581SMarianne Mailhot-Sarrasin return false;
9603fe71581SMarianne Mailhot-Sarrasin }
9613fe71581SMarianne Mailhot-Sarrasin frame.AssignValue(inst, result, module);
9623fe71581SMarianne Mailhot-Sarrasin
963b9c1b51eSKate Stone if (log) {
96463e5fb76SJonas Devlieghere LLDB_LOGF(log, "Interpreted a %s", inst->getOpcodeName());
96563e5fb76SJonas Devlieghere LLDB_LOGF(log, " Incoming value : %s",
966b9c1b51eSKate Stone frame.SummarizeValue(value).c_str());
9673fe71581SMarianne Mailhot-Sarrasin }
968b9c1b51eSKate Stone } break;
969b9c1b51eSKate Stone case Instruction::GetElementPtr: {
970f18370feSRaphael Isemann const GetElementPtrInst *gep_inst = cast<GetElementPtrInst>(inst);
97114cb2aaaSSean Callanan
97214cb2aaaSSean Callanan const Value *pointer_operand = gep_inst->getPointerOperand();
973d05b8992SEduard Burtescu Type *src_elem_ty = gep_inst->getSourceElementType();
97414cb2aaaSSean Callanan
97514cb2aaaSSean Callanan lldb_private::Scalar P;
97614cb2aaaSSean Callanan
977b9c1b51eSKate Stone if (!frame.EvaluateValue(P, pointer_operand, module)) {
97863e5fb76SJonas Devlieghere LLDB_LOGF(log, "Couldn't evaluate %s",
979b9c1b51eSKate Stone PrintValue(pointer_operand).c_str());
98014cb2aaaSSean Callanan error.SetErrorToGenericError();
98114cb2aaaSSean Callanan error.SetErrorString(bad_value_error);
98214cb2aaaSSean Callanan return false;
98314cb2aaaSSean Callanan }
98414cb2aaaSSean Callanan
98514cb2aaaSSean Callanan typedef SmallVector<Value *, 8> IndexVector;
98614cb2aaaSSean Callanan typedef IndexVector::iterator IndexIterator;
98714cb2aaaSSean Callanan
98814cb2aaaSSean Callanan SmallVector<Value *, 8> indices(gep_inst->idx_begin(),
98914cb2aaaSSean Callanan gep_inst->idx_end());
99014cb2aaaSSean Callanan
99114cb2aaaSSean Callanan SmallVector<Value *, 8> const_indices;
99214cb2aaaSSean Callanan
993b9c1b51eSKate Stone for (IndexIterator ii = indices.begin(), ie = indices.end(); ii != ie;
994b9c1b51eSKate Stone ++ii) {
99514cb2aaaSSean Callanan ConstantInt *constant_index = dyn_cast<ConstantInt>(*ii);
99614cb2aaaSSean Callanan
997b9c1b51eSKate Stone if (!constant_index) {
99814cb2aaaSSean Callanan lldb_private::Scalar I;
99914cb2aaaSSean Callanan
1000b9c1b51eSKate Stone if (!frame.EvaluateValue(I, *ii, module)) {
100163e5fb76SJonas Devlieghere LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(*ii).c_str());
100214cb2aaaSSean Callanan error.SetErrorToGenericError();
100314cb2aaaSSean Callanan error.SetErrorString(bad_value_error);
100414cb2aaaSSean Callanan return false;
100514cb2aaaSSean Callanan }
100614cb2aaaSSean Callanan
100763e5fb76SJonas Devlieghere LLDB_LOGF(log, "Evaluated constant index %s as %llu",
100863e5fb76SJonas Devlieghere PrintValue(*ii).c_str(), I.ULongLong(LLDB_INVALID_ADDRESS));
100914cb2aaaSSean Callanan
1010b9c1b51eSKate Stone constant_index = cast<ConstantInt>(ConstantInt::get(
1011b9c1b51eSKate Stone (*ii)->getType(), I.ULongLong(LLDB_INVALID_ADDRESS)));
101214cb2aaaSSean Callanan }
101314cb2aaaSSean Callanan
101414cb2aaaSSean Callanan const_indices.push_back(constant_index);
101514cb2aaaSSean Callanan }
101614cb2aaaSSean Callanan
1017b9c1b51eSKate Stone uint64_t offset =
1018b9c1b51eSKate Stone data_layout.getIndexedOffsetInType(src_elem_ty, const_indices);
101914cb2aaaSSean Callanan
102014cb2aaaSSean Callanan lldb_private::Scalar Poffset = P + offset;
102114cb2aaaSSean Callanan
102214cb2aaaSSean Callanan frame.AssignValue(inst, Poffset, module);
102314cb2aaaSSean Callanan
1024b9c1b51eSKate Stone if (log) {
102563e5fb76SJonas Devlieghere LLDB_LOGF(log, "Interpreted a GetElementPtrInst");
102663e5fb76SJonas Devlieghere LLDB_LOGF(log, " P : %s",
1027b9c1b51eSKate Stone frame.SummarizeValue(pointer_operand).c_str());
102863e5fb76SJonas Devlieghere LLDB_LOGF(log, " Poffset : %s", frame.SummarizeValue(inst).c_str());
102914cb2aaaSSean Callanan }
1030b9c1b51eSKate Stone } break;
1031b9c1b51eSKate Stone case Instruction::ICmp: {
1032f18370feSRaphael Isemann const ICmpInst *icmp_inst = cast<ICmpInst>(inst);
103314cb2aaaSSean Callanan
103414cb2aaaSSean Callanan CmpInst::Predicate predicate = icmp_inst->getPredicate();
103514cb2aaaSSean Callanan
103614cb2aaaSSean Callanan Value *lhs = inst->getOperand(0);
103714cb2aaaSSean Callanan Value *rhs = inst->getOperand(1);
103814cb2aaaSSean Callanan
103914cb2aaaSSean Callanan lldb_private::Scalar L;
104014cb2aaaSSean Callanan lldb_private::Scalar R;
104114cb2aaaSSean Callanan
1042b9c1b51eSKate Stone if (!frame.EvaluateValue(L, lhs, module)) {
104363e5fb76SJonas Devlieghere LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(lhs).c_str());
104414cb2aaaSSean Callanan error.SetErrorToGenericError();
104514cb2aaaSSean Callanan error.SetErrorString(bad_value_error);
104614cb2aaaSSean Callanan return false;
104714cb2aaaSSean Callanan }
104814cb2aaaSSean Callanan
1049b9c1b51eSKate Stone if (!frame.EvaluateValue(R, rhs, module)) {
105063e5fb76SJonas Devlieghere LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(rhs).c_str());
105114cb2aaaSSean Callanan error.SetErrorToGenericError();
105214cb2aaaSSean Callanan error.SetErrorString(bad_value_error);
105314cb2aaaSSean Callanan return false;
105414cb2aaaSSean Callanan }
105514cb2aaaSSean Callanan
105614cb2aaaSSean Callanan lldb_private::Scalar result;
105714cb2aaaSSean Callanan
1058b9c1b51eSKate Stone switch (predicate) {
105914cb2aaaSSean Callanan default:
106014cb2aaaSSean Callanan return false;
106114cb2aaaSSean Callanan case CmpInst::ICMP_EQ:
106214cb2aaaSSean Callanan result = (L == R);
106314cb2aaaSSean Callanan break;
106414cb2aaaSSean Callanan case CmpInst::ICMP_NE:
106514cb2aaaSSean Callanan result = (L != R);
106614cb2aaaSSean Callanan break;
106714cb2aaaSSean Callanan case CmpInst::ICMP_UGT:
10689521ad2aSUlrich Weigand L.MakeUnsigned();
10699521ad2aSUlrich Weigand R.MakeUnsigned();
10709521ad2aSUlrich Weigand result = (L > R);
107114cb2aaaSSean Callanan break;
107214cb2aaaSSean Callanan case CmpInst::ICMP_UGE:
10739521ad2aSUlrich Weigand L.MakeUnsigned();
10749521ad2aSUlrich Weigand R.MakeUnsigned();
10759521ad2aSUlrich Weigand result = (L >= R);
107614cb2aaaSSean Callanan break;
107714cb2aaaSSean Callanan case CmpInst::ICMP_ULT:
10789521ad2aSUlrich Weigand L.MakeUnsigned();
10799521ad2aSUlrich Weigand R.MakeUnsigned();
10809521ad2aSUlrich Weigand result = (L < R);
108114cb2aaaSSean Callanan break;
108214cb2aaaSSean Callanan case CmpInst::ICMP_ULE:
10839521ad2aSUlrich Weigand L.MakeUnsigned();
10849521ad2aSUlrich Weigand R.MakeUnsigned();
10859521ad2aSUlrich Weigand result = (L <= R);
108614cb2aaaSSean Callanan break;
108714cb2aaaSSean Callanan case CmpInst::ICMP_SGT:
10880b342b6dSSean Callanan L.MakeSigned();
10890b342b6dSSean Callanan R.MakeSigned();
109014cb2aaaSSean Callanan result = (L > R);
109114cb2aaaSSean Callanan break;
109214cb2aaaSSean Callanan case CmpInst::ICMP_SGE:
10930b342b6dSSean Callanan L.MakeSigned();
10940b342b6dSSean Callanan R.MakeSigned();
109514cb2aaaSSean Callanan result = (L >= R);
109614cb2aaaSSean Callanan break;
109714cb2aaaSSean Callanan case CmpInst::ICMP_SLT:
10980b342b6dSSean Callanan L.MakeSigned();
10990b342b6dSSean Callanan R.MakeSigned();
110014cb2aaaSSean Callanan result = (L < R);
110114cb2aaaSSean Callanan break;
110214cb2aaaSSean Callanan case CmpInst::ICMP_SLE:
11030b342b6dSSean Callanan L.MakeSigned();
11040b342b6dSSean Callanan R.MakeSigned();
110514cb2aaaSSean Callanan result = (L <= R);
110614cb2aaaSSean Callanan break;
110714cb2aaaSSean Callanan }
110814cb2aaaSSean Callanan
110914cb2aaaSSean Callanan frame.AssignValue(inst, result, module);
111014cb2aaaSSean Callanan
1111b9c1b51eSKate Stone if (log) {
111263e5fb76SJonas Devlieghere LLDB_LOGF(log, "Interpreted an ICmpInst");
111363e5fb76SJonas Devlieghere LLDB_LOGF(log, " L : %s", frame.SummarizeValue(lhs).c_str());
111463e5fb76SJonas Devlieghere LLDB_LOGF(log, " R : %s", frame.SummarizeValue(rhs).c_str());
111563e5fb76SJonas Devlieghere LLDB_LOGF(log, " = : %s", frame.SummarizeValue(inst).c_str());
111614cb2aaaSSean Callanan }
1117b9c1b51eSKate Stone } break;
1118b9c1b51eSKate Stone case Instruction::IntToPtr: {
1119f18370feSRaphael Isemann const IntToPtrInst *int_to_ptr_inst = cast<IntToPtrInst>(inst);
112014cb2aaaSSean Callanan
112114cb2aaaSSean Callanan Value *src_operand = int_to_ptr_inst->getOperand(0);
112214cb2aaaSSean Callanan
112314cb2aaaSSean Callanan lldb_private::Scalar I;
112414cb2aaaSSean Callanan
1125b9c1b51eSKate Stone if (!frame.EvaluateValue(I, src_operand, module)) {
112663e5fb76SJonas Devlieghere LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(src_operand).c_str());
112714cb2aaaSSean Callanan error.SetErrorToGenericError();
112814cb2aaaSSean Callanan error.SetErrorString(bad_value_error);
112914cb2aaaSSean Callanan return false;
113014cb2aaaSSean Callanan }
113114cb2aaaSSean Callanan
113214cb2aaaSSean Callanan frame.AssignValue(inst, I, module);
113314cb2aaaSSean Callanan
1134b9c1b51eSKate Stone if (log) {
113563e5fb76SJonas Devlieghere LLDB_LOGF(log, "Interpreted an IntToPtr");
113663e5fb76SJonas Devlieghere LLDB_LOGF(log, " Src : %s", frame.SummarizeValue(src_operand).c_str());
113763e5fb76SJonas Devlieghere LLDB_LOGF(log, " = : %s", frame.SummarizeValue(inst).c_str());
113814cb2aaaSSean Callanan }
1139b9c1b51eSKate Stone } break;
1140b9c1b51eSKate Stone case Instruction::PtrToInt: {
1141f18370feSRaphael Isemann const PtrToIntInst *ptr_to_int_inst = cast<PtrToIntInst>(inst);
114214cb2aaaSSean Callanan
114314cb2aaaSSean Callanan Value *src_operand = ptr_to_int_inst->getOperand(0);
114414cb2aaaSSean Callanan
114514cb2aaaSSean Callanan lldb_private::Scalar I;
114614cb2aaaSSean Callanan
1147b9c1b51eSKate Stone if (!frame.EvaluateValue(I, src_operand, module)) {
114863e5fb76SJonas Devlieghere LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(src_operand).c_str());
114914cb2aaaSSean Callanan error.SetErrorToGenericError();
115014cb2aaaSSean Callanan error.SetErrorString(bad_value_error);
115114cb2aaaSSean Callanan return false;
115214cb2aaaSSean Callanan }
115314cb2aaaSSean Callanan
115414cb2aaaSSean Callanan frame.AssignValue(inst, I, module);
115514cb2aaaSSean Callanan
1156b9c1b51eSKate Stone if (log) {
115763e5fb76SJonas Devlieghere LLDB_LOGF(log, "Interpreted a PtrToInt");
115863e5fb76SJonas Devlieghere LLDB_LOGF(log, " Src : %s", frame.SummarizeValue(src_operand).c_str());
115963e5fb76SJonas Devlieghere LLDB_LOGF(log, " = : %s", frame.SummarizeValue(inst).c_str());
116014cb2aaaSSean Callanan }
1161b9c1b51eSKate Stone } break;
1162b9c1b51eSKate Stone case Instruction::Trunc: {
1163f18370feSRaphael Isemann const TruncInst *trunc_inst = cast<TruncInst>(inst);
11648c46bacaSSean Callanan
11658c46bacaSSean Callanan Value *src_operand = trunc_inst->getOperand(0);
11668c46bacaSSean Callanan
11678c46bacaSSean Callanan lldb_private::Scalar I;
11688c46bacaSSean Callanan
1169b9c1b51eSKate Stone if (!frame.EvaluateValue(I, src_operand, module)) {
117063e5fb76SJonas Devlieghere LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(src_operand).c_str());
11718c46bacaSSean Callanan error.SetErrorToGenericError();
11728c46bacaSSean Callanan error.SetErrorString(bad_value_error);
11738c46bacaSSean Callanan return false;
11748c46bacaSSean Callanan }
11758c46bacaSSean Callanan
11768c46bacaSSean Callanan frame.AssignValue(inst, I, module);
11778c46bacaSSean Callanan
1178b9c1b51eSKate Stone if (log) {
117963e5fb76SJonas Devlieghere LLDB_LOGF(log, "Interpreted a Trunc");
118063e5fb76SJonas Devlieghere LLDB_LOGF(log, " Src : %s", frame.SummarizeValue(src_operand).c_str());
118163e5fb76SJonas Devlieghere LLDB_LOGF(log, " = : %s", frame.SummarizeValue(inst).c_str());
11828c46bacaSSean Callanan }
1183b9c1b51eSKate Stone } break;
1184b9c1b51eSKate Stone case Instruction::Load: {
1185f18370feSRaphael Isemann const LoadInst *load_inst = cast<LoadInst>(inst);
118614cb2aaaSSean Callanan
118714cb2aaaSSean Callanan // The semantics of Load are:
118814cb2aaaSSean Callanan // Create a region D that will contain the loaded data
118914cb2aaaSSean Callanan // Resolve the region P containing a pointer
119014cb2aaaSSean Callanan // Dereference P to get the region R that the data should be loaded from
119114cb2aaaSSean Callanan // Transfer a unit of type type(D) from R to D
119214cb2aaaSSean Callanan
119314cb2aaaSSean Callanan const Value *pointer_operand = load_inst->getPointerOperand();
119414cb2aaaSSean Callanan
119514cb2aaaSSean Callanan lldb::addr_t D = frame.ResolveValue(load_inst, module);
119614cb2aaaSSean Callanan lldb::addr_t P = frame.ResolveValue(pointer_operand, module);
119714cb2aaaSSean Callanan
1198b9c1b51eSKate Stone if (D == LLDB_INVALID_ADDRESS) {
119963e5fb76SJonas Devlieghere LLDB_LOGF(log, "LoadInst's value doesn't resolve to anything");
120014cb2aaaSSean Callanan error.SetErrorToGenericError();
120114cb2aaaSSean Callanan error.SetErrorString(bad_value_error);
120214cb2aaaSSean Callanan return false;
120314cb2aaaSSean Callanan }
120414cb2aaaSSean Callanan
1205b9c1b51eSKate Stone if (P == LLDB_INVALID_ADDRESS) {
120663e5fb76SJonas Devlieghere LLDB_LOGF(log, "LoadInst's pointer doesn't resolve to anything");
120714cb2aaaSSean Callanan error.SetErrorToGenericError();
120814cb2aaaSSean Callanan error.SetErrorString(bad_value_error);
120914cb2aaaSSean Callanan return false;
121014cb2aaaSSean Callanan }
121114cb2aaaSSean Callanan
121214cb2aaaSSean Callanan lldb::addr_t R;
121397206d57SZachary Turner lldb_private::Status read_error;
12147071c5fdSTed Woodward execution_unit.ReadPointerFromMemory(&R, P, read_error);
121514cb2aaaSSean Callanan
1216b9c1b51eSKate Stone if (!read_error.Success()) {
121763e5fb76SJonas Devlieghere LLDB_LOGF(log, "Couldn't read the address to be loaded for a LoadInst");
121814cb2aaaSSean Callanan error.SetErrorToGenericError();
121914cb2aaaSSean Callanan error.SetErrorString(memory_read_error);
122014cb2aaaSSean Callanan return false;
122114cb2aaaSSean Callanan }
122214cb2aaaSSean Callanan
12232df9430fSNikita Popov Type *target_ty = load_inst->getType();
122414cb2aaaSSean Callanan size_t target_size = data_layout.getTypeStoreSize(target_ty);
122514cb2aaaSSean Callanan lldb_private::DataBufferHeap buffer(target_size, 0);
122614cb2aaaSSean Callanan
122714cb2aaaSSean Callanan read_error.Clear();
1228b9c1b51eSKate Stone execution_unit.ReadMemory(buffer.GetBytes(), R, buffer.GetByteSize(),
1229b9c1b51eSKate Stone read_error);
1230b9c1b51eSKate Stone if (!read_error.Success()) {
123163e5fb76SJonas Devlieghere LLDB_LOGF(log, "Couldn't read from a region on behalf of a LoadInst");
123214cb2aaaSSean Callanan error.SetErrorToGenericError();
123314cb2aaaSSean Callanan error.SetErrorString(memory_read_error);
123414cb2aaaSSean Callanan return false;
123514cb2aaaSSean Callanan }
123614cb2aaaSSean Callanan
123797206d57SZachary Turner lldb_private::Status write_error;
1238b9c1b51eSKate Stone execution_unit.WriteMemory(D, buffer.GetBytes(), buffer.GetByteSize(),
1239b9c1b51eSKate Stone write_error);
1240b9c1b51eSKate Stone if (!write_error.Success()) {
124163e5fb76SJonas Devlieghere LLDB_LOGF(log, "Couldn't write to a region on behalf of a LoadInst");
124214cb2aaaSSean Callanan error.SetErrorToGenericError();
12431b7e5d46SAndy Yankovsky error.SetErrorString(memory_write_error);
124414cb2aaaSSean Callanan return false;
124514cb2aaaSSean Callanan }
124614cb2aaaSSean Callanan
1247b9c1b51eSKate Stone if (log) {
124863e5fb76SJonas Devlieghere LLDB_LOGF(log, "Interpreted a LoadInst");
124963e5fb76SJonas Devlieghere LLDB_LOGF(log, " P : 0x%" PRIx64, P);
125063e5fb76SJonas Devlieghere LLDB_LOGF(log, " R : 0x%" PRIx64, R);
125163e5fb76SJonas Devlieghere LLDB_LOGF(log, " D : 0x%" PRIx64, D);
125214cb2aaaSSean Callanan }
1253b9c1b51eSKate Stone } break;
1254b9c1b51eSKate Stone case Instruction::Ret: {
125514cb2aaaSSean Callanan return true;
125614cb2aaaSSean Callanan }
1257b9c1b51eSKate Stone case Instruction::Store: {
1258f18370feSRaphael Isemann const StoreInst *store_inst = cast<StoreInst>(inst);
125914cb2aaaSSean Callanan
126014cb2aaaSSean Callanan // The semantics of Store are:
126114cb2aaaSSean Callanan // Resolve the region D containing the data to be stored
126214cb2aaaSSean Callanan // Resolve the region P containing a pointer
126314cb2aaaSSean Callanan // Dereference P to get the region R that the data should be stored in
126414cb2aaaSSean Callanan // Transfer a unit of type type(D) from D to R
126514cb2aaaSSean Callanan
126614cb2aaaSSean Callanan const Value *value_operand = store_inst->getValueOperand();
126714cb2aaaSSean Callanan const Value *pointer_operand = store_inst->getPointerOperand();
126814cb2aaaSSean Callanan
126914cb2aaaSSean Callanan lldb::addr_t D = frame.ResolveValue(value_operand, module);
127014cb2aaaSSean Callanan lldb::addr_t P = frame.ResolveValue(pointer_operand, module);
127114cb2aaaSSean Callanan
1272b9c1b51eSKate Stone if (D == LLDB_INVALID_ADDRESS) {
127363e5fb76SJonas Devlieghere LLDB_LOGF(log, "StoreInst's value doesn't resolve to anything");
127414cb2aaaSSean Callanan error.SetErrorToGenericError();
127514cb2aaaSSean Callanan error.SetErrorString(bad_value_error);
127614cb2aaaSSean Callanan return false;
127714cb2aaaSSean Callanan }
127814cb2aaaSSean Callanan
1279b9c1b51eSKate Stone if (P == LLDB_INVALID_ADDRESS) {
128063e5fb76SJonas Devlieghere LLDB_LOGF(log, "StoreInst's pointer doesn't resolve to anything");
128114cb2aaaSSean Callanan error.SetErrorToGenericError();
128214cb2aaaSSean Callanan error.SetErrorString(bad_value_error);
128314cb2aaaSSean Callanan return false;
128414cb2aaaSSean Callanan }
128514cb2aaaSSean Callanan
128614cb2aaaSSean Callanan lldb::addr_t R;
128797206d57SZachary Turner lldb_private::Status read_error;
12887071c5fdSTed Woodward execution_unit.ReadPointerFromMemory(&R, P, read_error);
128914cb2aaaSSean Callanan
1290b9c1b51eSKate Stone if (!read_error.Success()) {
129163e5fb76SJonas Devlieghere LLDB_LOGF(log, "Couldn't read the address to be loaded for a LoadInst");
129214cb2aaaSSean Callanan error.SetErrorToGenericError();
129314cb2aaaSSean Callanan error.SetErrorString(memory_read_error);
129414cb2aaaSSean Callanan return false;
129514cb2aaaSSean Callanan }
129614cb2aaaSSean Callanan
12972df9430fSNikita Popov Type *target_ty = value_operand->getType();
129814cb2aaaSSean Callanan size_t target_size = data_layout.getTypeStoreSize(target_ty);
129914cb2aaaSSean Callanan lldb_private::DataBufferHeap buffer(target_size, 0);
130014cb2aaaSSean Callanan
130114cb2aaaSSean Callanan read_error.Clear();
1302b9c1b51eSKate Stone execution_unit.ReadMemory(buffer.GetBytes(), D, buffer.GetByteSize(),
1303b9c1b51eSKate Stone read_error);
1304b9c1b51eSKate Stone if (!read_error.Success()) {
130563e5fb76SJonas Devlieghere LLDB_LOGF(log, "Couldn't read from a region on behalf of a StoreInst");
130614cb2aaaSSean Callanan error.SetErrorToGenericError();
130714cb2aaaSSean Callanan error.SetErrorString(memory_read_error);
130814cb2aaaSSean Callanan return false;
130914cb2aaaSSean Callanan }
131014cb2aaaSSean Callanan
131197206d57SZachary Turner lldb_private::Status write_error;
1312b9c1b51eSKate Stone execution_unit.WriteMemory(R, buffer.GetBytes(), buffer.GetByteSize(),
1313b9c1b51eSKate Stone write_error);
1314b9c1b51eSKate Stone if (!write_error.Success()) {
131563e5fb76SJonas Devlieghere LLDB_LOGF(log, "Couldn't write to a region on behalf of a StoreInst");
131614cb2aaaSSean Callanan error.SetErrorToGenericError();
131749630e7fSSean Callanan error.SetErrorString(memory_write_error);
131814cb2aaaSSean Callanan return false;
131914cb2aaaSSean Callanan }
132014cb2aaaSSean Callanan
1321b9c1b51eSKate Stone if (log) {
132263e5fb76SJonas Devlieghere LLDB_LOGF(log, "Interpreted a StoreInst");
132363e5fb76SJonas Devlieghere LLDB_LOGF(log, " D : 0x%" PRIx64, D);
132463e5fb76SJonas Devlieghere LLDB_LOGF(log, " P : 0x%" PRIx64, P);
132563e5fb76SJonas Devlieghere LLDB_LOGF(log, " R : 0x%" PRIx64, R);
132614cb2aaaSSean Callanan }
1327b9c1b51eSKate Stone } break;
1328b9c1b51eSKate Stone case Instruction::Call: {
1329f18370feSRaphael Isemann const CallInst *call_inst = cast<CallInst>(inst);
133090ff7911SEwan Crawford
133190ff7911SEwan Crawford if (CanIgnoreCall(call_inst))
133290ff7911SEwan Crawford break;
133390ff7911SEwan Crawford
133490ff7911SEwan Crawford // Get the return type
133590ff7911SEwan Crawford llvm::Type *returnType = call_inst->getType();
1336b9c1b51eSKate Stone if (returnType == nullptr) {
133790ff7911SEwan Crawford error.SetErrorToGenericError();
133890ff7911SEwan Crawford error.SetErrorString("unable to access return type");
133990ff7911SEwan Crawford return false;
134090ff7911SEwan Crawford }
134190ff7911SEwan Crawford
134290ff7911SEwan Crawford // Work with void, integer and pointer return types
1343b9c1b51eSKate Stone if (!returnType->isVoidTy() && !returnType->isIntegerTy() &&
1344b9c1b51eSKate Stone !returnType->isPointerTy()) {
134590ff7911SEwan Crawford error.SetErrorToGenericError();
134690ff7911SEwan Crawford error.SetErrorString("return type is not supported");
134790ff7911SEwan Crawford return false;
134890ff7911SEwan Crawford }
134990ff7911SEwan Crawford
135090ff7911SEwan Crawford // Check we can actually get a thread
1351b9c1b51eSKate Stone if (exe_ctx.GetThreadPtr() == nullptr) {
135290ff7911SEwan Crawford error.SetErrorToGenericError();
135389533764SJonas Devlieghere error.SetErrorString("unable to acquire thread");
135490ff7911SEwan Crawford return false;
135590ff7911SEwan Crawford }
135690ff7911SEwan Crawford
135790ff7911SEwan Crawford // Make sure we have a valid process
1358b9c1b51eSKate Stone if (!exe_ctx.GetProcessPtr()) {
135990ff7911SEwan Crawford error.SetErrorToGenericError();
136089533764SJonas Devlieghere error.SetErrorString("unable to get the process");
136190ff7911SEwan Crawford return false;
136290ff7911SEwan Crawford }
136390ff7911SEwan Crawford
136490ff7911SEwan Crawford // Find the address of the callee function
136590ff7911SEwan Crawford lldb_private::Scalar I;
1366a58b62b4SCraig Topper const llvm::Value *val = call_inst->getCalledOperand();
136790ff7911SEwan Crawford
1368b9c1b51eSKate Stone if (!frame.EvaluateValue(I, val, module)) {
136990ff7911SEwan Crawford error.SetErrorToGenericError();
137090ff7911SEwan Crawford error.SetErrorString("unable to get address of function");
137190ff7911SEwan Crawford return false;
137290ff7911SEwan Crawford }
137390ff7911SEwan Crawford lldb_private::Address funcAddr(I.ULongLong(LLDB_INVALID_ADDRESS));
137490ff7911SEwan Crawford
1375579e70c9SSean Callanan lldb_private::DiagnosticManager diagnostics;
137690ff7911SEwan Crawford lldb_private::EvaluateExpressionOptions options;
137790ff7911SEwan Crawford
1378ad1feef7SNikita Popov llvm::FunctionType *prototype = call_inst->getFunctionType();
137990ff7911SEwan Crawford
138090ff7911SEwan Crawford // Find number of arguments
138180e39366SKazu Hirata const int numArgs = call_inst->arg_size();
138290ff7911SEwan Crawford
138390ff7911SEwan Crawford // We work with a fixed array of 16 arguments which is our upper limit
138490ff7911SEwan Crawford static lldb_private::ABI::CallArgument rawArgs[16];
1385b9c1b51eSKate Stone if (numArgs >= 16) {
138690ff7911SEwan Crawford error.SetErrorToGenericError();
138789533764SJonas Devlieghere error.SetErrorString("function takes too many arguments");
138890ff7911SEwan Crawford return false;
138990ff7911SEwan Crawford }
139090ff7911SEwan Crawford
139105097246SAdrian Prantl // Push all function arguments to the argument list that will be passed
139205097246SAdrian Prantl // to the call function thread plan
1393b9c1b51eSKate Stone for (int i = 0; i < numArgs; i++) {
139490ff7911SEwan Crawford // Get details of this argument
139590ff7911SEwan Crawford llvm::Value *arg_op = call_inst->getArgOperand(i);
139690ff7911SEwan Crawford llvm::Type *arg_ty = arg_op->getType();
139790ff7911SEwan Crawford
139890ff7911SEwan Crawford // Ensure that this argument is an supported type
1399b9c1b51eSKate Stone if (!arg_ty->isIntegerTy() && !arg_ty->isPointerTy()) {
140090ff7911SEwan Crawford error.SetErrorToGenericError();
140190ff7911SEwan Crawford error.SetErrorStringWithFormat("argument %d must be integer type", i);
140290ff7911SEwan Crawford return false;
140390ff7911SEwan Crawford }
140490ff7911SEwan Crawford
140590ff7911SEwan Crawford // Extract the arguments value
140690ff7911SEwan Crawford lldb_private::Scalar tmp_op = 0;
1407b9c1b51eSKate Stone if (!frame.EvaluateValue(tmp_op, arg_op, module)) {
140890ff7911SEwan Crawford error.SetErrorToGenericError();
140990ff7911SEwan Crawford error.SetErrorStringWithFormat("unable to evaluate argument %d", i);
141090ff7911SEwan Crawford return false;
141190ff7911SEwan Crawford }
141290ff7911SEwan Crawford
141390ff7911SEwan Crawford // Check if this is a string literal or constant string pointer
1414b9c1b51eSKate Stone if (arg_ty->isPointerTy()) {
141590ff7911SEwan Crawford lldb::addr_t addr = tmp_op.ULongLong();
141690ff7911SEwan Crawford size_t dataSize = 0;
141790ff7911SEwan Crawford
1418a322f36cSDavid Blaikie bool Success = execution_unit.GetAllocSize(addr, dataSize);
1419a322f36cSDavid Blaikie (void)Success;
1420a322f36cSDavid Blaikie assert(Success &&
1421a322f36cSDavid Blaikie "unable to locate host data for transfer to device");
142290ff7911SEwan Crawford // Create the required buffer
142390ff7911SEwan Crawford rawArgs[i].size = dataSize;
1424d5b44036SJonas Devlieghere rawArgs[i].data_up.reset(new uint8_t[dataSize + 1]);
142590ff7911SEwan Crawford
142690ff7911SEwan Crawford // Read string from host memory
1427d5b44036SJonas Devlieghere execution_unit.ReadMemory(rawArgs[i].data_up.get(), addr, dataSize,
1428b9c1b51eSKate Stone error);
1429a322f36cSDavid Blaikie assert(!error.Fail() &&
1430a322f36cSDavid Blaikie "we have failed to read the string from memory");
1431a322f36cSDavid Blaikie
143290ff7911SEwan Crawford // Add null terminator
1433d5b44036SJonas Devlieghere rawArgs[i].data_up[dataSize] = '\0';
143490ff7911SEwan Crawford rawArgs[i].type = lldb_private::ABI::CallArgument::HostPointer;
1435b9c1b51eSKate Stone } else /* if ( arg_ty->isPointerTy() ) */
143690ff7911SEwan Crawford {
143790ff7911SEwan Crawford rawArgs[i].type = lldb_private::ABI::CallArgument::TargetValue;
143890ff7911SEwan Crawford // Get argument size in bytes
143990ff7911SEwan Crawford rawArgs[i].size = arg_ty->getIntegerBitWidth() / 8;
144090ff7911SEwan Crawford // Push value into argument list for thread plan
144190ff7911SEwan Crawford rawArgs[i].value = tmp_op.ULongLong();
144290ff7911SEwan Crawford }
144390ff7911SEwan Crawford }
144490ff7911SEwan Crawford
144590ff7911SEwan Crawford // Pack the arguments into an llvm::array
144690ff7911SEwan Crawford llvm::ArrayRef<lldb_private::ABI::CallArgument> args(rawArgs, numArgs);
144790ff7911SEwan Crawford
144890ff7911SEwan Crawford // Setup a thread plan to call the target function
1449b9c1b51eSKate Stone lldb::ThreadPlanSP call_plan_sp(
1450b9c1b51eSKate Stone new lldb_private::ThreadPlanCallFunctionUsingABI(
1451b9c1b51eSKate Stone exe_ctx.GetThreadRef(), funcAddr, *prototype, *returnType, args,
1452b9c1b51eSKate Stone options));
145390ff7911SEwan Crawford
145490ff7911SEwan Crawford // Check if the plan is valid
1455579e70c9SSean Callanan lldb_private::StreamString ss;
1456b9c1b51eSKate Stone if (!call_plan_sp || !call_plan_sp->ValidatePlan(&ss)) {
145790ff7911SEwan Crawford error.SetErrorToGenericError();
1458b9c1b51eSKate Stone error.SetErrorStringWithFormat(
1459b9c1b51eSKate Stone "unable to make ThreadPlanCallFunctionUsingABI for 0x%llx",
1460579e70c9SSean Callanan I.ULongLong());
146190ff7911SEwan Crawford return false;
146290ff7911SEwan Crawford }
146390ff7911SEwan Crawford
146490ff7911SEwan Crawford exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
146590ff7911SEwan Crawford
146690ff7911SEwan Crawford // Execute the actual function call thread plan
1467b9c1b51eSKate Stone lldb::ExpressionResults res = exe_ctx.GetProcessRef().RunThreadPlan(
1468b9c1b51eSKate Stone exe_ctx, call_plan_sp, options, diagnostics);
146990ff7911SEwan Crawford
147090ff7911SEwan Crawford // Check that the thread plan completed successfully
1471b9c1b51eSKate Stone if (res != lldb::ExpressionResults::eExpressionCompleted) {
147290ff7911SEwan Crawford error.SetErrorToGenericError();
147389533764SJonas Devlieghere error.SetErrorString("ThreadPlanCallFunctionUsingABI failed");
147490ff7911SEwan Crawford return false;
147590ff7911SEwan Crawford }
147690ff7911SEwan Crawford
147790ff7911SEwan Crawford exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
147890ff7911SEwan Crawford
147990ff7911SEwan Crawford // Void return type
1480b9c1b51eSKate Stone if (returnType->isVoidTy()) {
148190ff7911SEwan Crawford // Cant assign to void types, so we leave the frame untouched
1482b9c1b51eSKate Stone } else
148390ff7911SEwan Crawford // Integer or pointer return type
1484b9c1b51eSKate Stone if (returnType->isIntegerTy() || returnType->isPointerTy()) {
148590ff7911SEwan Crawford // Get the encapsulated return value
148690ff7911SEwan Crawford lldb::ValueObjectSP retVal = call_plan_sp.get()->GetReturnValueObject();
148790ff7911SEwan Crawford
148890ff7911SEwan Crawford lldb_private::Scalar returnVal = -1;
148990ff7911SEwan Crawford lldb_private::ValueObject *vobj = retVal.get();
149090ff7911SEwan Crawford
149190ff7911SEwan Crawford // Check if the return value is valid
1492363f05b8SPavel Labath if (vobj == nullptr || !retVal) {
149390ff7911SEwan Crawford error.SetErrorToGenericError();
149489533764SJonas Devlieghere error.SetErrorString("unable to get the return value");
149590ff7911SEwan Crawford return false;
149690ff7911SEwan Crawford }
149790ff7911SEwan Crawford
149890ff7911SEwan Crawford // Extract the return value as a integer
149990ff7911SEwan Crawford lldb_private::Value &value = vobj->GetValue();
150090ff7911SEwan Crawford returnVal = value.GetScalar();
150190ff7911SEwan Crawford
150290ff7911SEwan Crawford // Push the return value as the result
150390ff7911SEwan Crawford frame.AssignValue(inst, returnVal, module);
150490ff7911SEwan Crawford }
1505b9c1b51eSKate Stone } break;
150614cb2aaaSSean Callanan }
150714cb2aaaSSean Callanan
150814cb2aaaSSean Callanan ++frame.m_ii;
150914cb2aaaSSean Callanan }
151014cb2aaaSSean Callanan
1511b9c1b51eSKate Stone if (num_insts >= 4096) {
151214cb2aaaSSean Callanan error.SetErrorToGenericError();
151314cb2aaaSSean Callanan error.SetErrorString(infinite_loop_error);
151414cb2aaaSSean Callanan return false;
151514cb2aaaSSean Callanan }
151614cb2aaaSSean Callanan
151714cb2aaaSSean Callanan return false;
151814cb2aaaSSean Callanan }
1519