1dda28197Spatrick //===-- IRInterpreter.cpp -------------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick
9061da546Spatrick #include "lldb/Expression/IRInterpreter.h"
10061da546Spatrick #include "lldb/Core/Module.h"
11061da546Spatrick #include "lldb/Core/ModuleSpec.h"
12061da546Spatrick #include "lldb/Core/ValueObject.h"
13061da546Spatrick #include "lldb/Expression/DiagnosticManager.h"
14061da546Spatrick #include "lldb/Expression/IRExecutionUnit.h"
15061da546Spatrick #include "lldb/Expression/IRMemoryMap.h"
16061da546Spatrick #include "lldb/Utility/ConstString.h"
17061da546Spatrick #include "lldb/Utility/DataExtractor.h"
18061da546Spatrick #include "lldb/Utility/Endian.h"
19*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
20061da546Spatrick #include "lldb/Utility/Log.h"
21061da546Spatrick #include "lldb/Utility/Scalar.h"
22061da546Spatrick #include "lldb/Utility/Status.h"
23061da546Spatrick #include "lldb/Utility/StreamString.h"
24061da546Spatrick
25061da546Spatrick #include "lldb/Target/ABI.h"
26061da546Spatrick #include "lldb/Target/ExecutionContext.h"
27061da546Spatrick #include "lldb/Target/Target.h"
28061da546Spatrick #include "lldb/Target/Thread.h"
29061da546Spatrick #include "lldb/Target/ThreadPlan.h"
30061da546Spatrick #include "lldb/Target/ThreadPlanCallFunctionUsingABI.h"
31061da546Spatrick
32061da546Spatrick #include "llvm/IR/Constants.h"
33061da546Spatrick #include "llvm/IR/DataLayout.h"
34061da546Spatrick #include "llvm/IR/Function.h"
35061da546Spatrick #include "llvm/IR/Instructions.h"
36061da546Spatrick #include "llvm/IR/Intrinsics.h"
37061da546Spatrick #include "llvm/IR/LLVMContext.h"
38061da546Spatrick #include "llvm/IR/Module.h"
39061da546Spatrick #include "llvm/IR/Operator.h"
40061da546Spatrick #include "llvm/Support/raw_ostream.h"
41061da546Spatrick
42061da546Spatrick #include <map>
43061da546Spatrick
44061da546Spatrick using namespace llvm;
45*f6aab3d8Srobert using lldb_private::LLDBLog;
46061da546Spatrick
PrintValue(const Value * value,bool truncate=false)47061da546Spatrick static std::string PrintValue(const Value *value, bool truncate = false) {
48061da546Spatrick std::string s;
49061da546Spatrick raw_string_ostream rso(s);
50061da546Spatrick value->print(rso);
51061da546Spatrick rso.flush();
52061da546Spatrick if (truncate)
53061da546Spatrick s.resize(s.length() - 1);
54061da546Spatrick
55061da546Spatrick size_t offset;
56061da546Spatrick while ((offset = s.find('\n')) != s.npos)
57061da546Spatrick s.erase(offset, 1);
58061da546Spatrick while (s[0] == ' ' || s[0] == '\t')
59061da546Spatrick s.erase(0, 1);
60061da546Spatrick
61061da546Spatrick return s;
62061da546Spatrick }
63061da546Spatrick
PrintType(const Type * type,bool truncate=false)64061da546Spatrick static std::string PrintType(const Type *type, bool truncate = false) {
65061da546Spatrick std::string s;
66061da546Spatrick raw_string_ostream rso(s);
67061da546Spatrick type->print(rso);
68061da546Spatrick rso.flush();
69061da546Spatrick if (truncate)
70061da546Spatrick s.resize(s.length() - 1);
71061da546Spatrick return s;
72061da546Spatrick }
73061da546Spatrick
CanIgnoreCall(const CallInst * call)74061da546Spatrick static bool CanIgnoreCall(const CallInst *call) {
75061da546Spatrick const llvm::Function *called_function = call->getCalledFunction();
76061da546Spatrick
77061da546Spatrick if (!called_function)
78061da546Spatrick return false;
79061da546Spatrick
80061da546Spatrick if (called_function->isIntrinsic()) {
81061da546Spatrick switch (called_function->getIntrinsicID()) {
82061da546Spatrick default:
83061da546Spatrick break;
84061da546Spatrick case llvm::Intrinsic::dbg_declare:
85061da546Spatrick case llvm::Intrinsic::dbg_value:
86061da546Spatrick return true;
87061da546Spatrick }
88061da546Spatrick }
89061da546Spatrick
90061da546Spatrick return false;
91061da546Spatrick }
92061da546Spatrick
93061da546Spatrick class InterpreterStackFrame {
94061da546Spatrick public:
95061da546Spatrick typedef std::map<const Value *, lldb::addr_t> ValueMap;
96061da546Spatrick
97061da546Spatrick ValueMap m_values;
98061da546Spatrick DataLayout &m_target_data;
99061da546Spatrick lldb_private::IRExecutionUnit &m_execution_unit;
100*f6aab3d8Srobert const BasicBlock *m_bb = nullptr;
101*f6aab3d8Srobert const BasicBlock *m_prev_bb = nullptr;
102061da546Spatrick BasicBlock::const_iterator m_ii;
103061da546Spatrick BasicBlock::const_iterator m_ie;
104061da546Spatrick
105061da546Spatrick lldb::addr_t m_frame_process_address;
106061da546Spatrick size_t m_frame_size;
107061da546Spatrick lldb::addr_t m_stack_pointer;
108061da546Spatrick
109061da546Spatrick lldb::ByteOrder m_byte_order;
110061da546Spatrick size_t m_addr_byte_size;
111061da546Spatrick
InterpreterStackFrame(DataLayout & target_data,lldb_private::IRExecutionUnit & execution_unit,lldb::addr_t stack_frame_bottom,lldb::addr_t stack_frame_top)112061da546Spatrick InterpreterStackFrame(DataLayout &target_data,
113061da546Spatrick lldb_private::IRExecutionUnit &execution_unit,
114061da546Spatrick lldb::addr_t stack_frame_bottom,
115061da546Spatrick lldb::addr_t stack_frame_top)
116*f6aab3d8Srobert : m_target_data(target_data), m_execution_unit(execution_unit) {
117061da546Spatrick m_byte_order = (target_data.isLittleEndian() ? lldb::eByteOrderLittle
118061da546Spatrick : lldb::eByteOrderBig);
119061da546Spatrick m_addr_byte_size = (target_data.getPointerSize(0));
120061da546Spatrick
121061da546Spatrick m_frame_process_address = stack_frame_bottom;
122061da546Spatrick m_frame_size = stack_frame_top - stack_frame_bottom;
123061da546Spatrick m_stack_pointer = stack_frame_top;
124061da546Spatrick }
125061da546Spatrick
126be691f3bSpatrick ~InterpreterStackFrame() = default;
127061da546Spatrick
Jump(const BasicBlock * bb)128061da546Spatrick void Jump(const BasicBlock *bb) {
129061da546Spatrick m_prev_bb = m_bb;
130061da546Spatrick m_bb = bb;
131061da546Spatrick m_ii = m_bb->begin();
132061da546Spatrick m_ie = m_bb->end();
133061da546Spatrick }
134061da546Spatrick
SummarizeValue(const Value * value)135061da546Spatrick std::string SummarizeValue(const Value *value) {
136061da546Spatrick lldb_private::StreamString ss;
137061da546Spatrick
138061da546Spatrick ss.Printf("%s", PrintValue(value).c_str());
139061da546Spatrick
140061da546Spatrick ValueMap::iterator i = m_values.find(value);
141061da546Spatrick
142061da546Spatrick if (i != m_values.end()) {
143061da546Spatrick lldb::addr_t addr = i->second;
144061da546Spatrick
145061da546Spatrick ss.Printf(" 0x%llx", (unsigned long long)addr);
146061da546Spatrick }
147061da546Spatrick
148dda28197Spatrick return std::string(ss.GetString());
149061da546Spatrick }
150061da546Spatrick
AssignToMatchType(lldb_private::Scalar & scalar,llvm::APInt value,Type * type)151dda28197Spatrick bool AssignToMatchType(lldb_private::Scalar &scalar, llvm::APInt value,
152061da546Spatrick Type *type) {
153061da546Spatrick size_t type_size = m_target_data.getTypeStoreSize(type);
154061da546Spatrick
155061da546Spatrick if (type_size > 8)
156061da546Spatrick return false;
157061da546Spatrick
158061da546Spatrick if (type_size != 1)
159061da546Spatrick type_size = PowerOf2Ceil(type_size);
160061da546Spatrick
161dda28197Spatrick scalar = value.zextOrTrunc(type_size * 8);
162061da546Spatrick return true;
163061da546Spatrick }
164061da546Spatrick
EvaluateValue(lldb_private::Scalar & scalar,const Value * value,Module & module)165061da546Spatrick bool EvaluateValue(lldb_private::Scalar &scalar, const Value *value,
166061da546Spatrick Module &module) {
167061da546Spatrick const Constant *constant = dyn_cast<Constant>(value);
168061da546Spatrick
169061da546Spatrick if (constant) {
170*f6aab3d8Srobert if (constant->getValueID() == Value::ConstantFPVal) {
171*f6aab3d8Srobert if (auto *cfp = dyn_cast<ConstantFP>(constant)) {
172*f6aab3d8Srobert if (cfp->getType()->isDoubleTy())
173*f6aab3d8Srobert scalar = cfp->getValueAPF().convertToDouble();
174*f6aab3d8Srobert else if (cfp->getType()->isFloatTy())
175*f6aab3d8Srobert scalar = cfp->getValueAPF().convertToFloat();
176*f6aab3d8Srobert else
177*f6aab3d8Srobert return false;
178*f6aab3d8Srobert return true;
179*f6aab3d8Srobert }
180*f6aab3d8Srobert return false;
181*f6aab3d8Srobert }
182061da546Spatrick APInt value_apint;
183061da546Spatrick
184061da546Spatrick if (!ResolveConstantValue(value_apint, constant))
185061da546Spatrick return false;
186061da546Spatrick
187dda28197Spatrick return AssignToMatchType(scalar, value_apint, value->getType());
188dda28197Spatrick }
189dda28197Spatrick
190061da546Spatrick lldb::addr_t process_address = ResolveValue(value, module);
191061da546Spatrick size_t value_size = m_target_data.getTypeStoreSize(value->getType());
192061da546Spatrick
193061da546Spatrick lldb_private::DataExtractor value_extractor;
194061da546Spatrick lldb_private::Status extract_error;
195061da546Spatrick
196061da546Spatrick m_execution_unit.GetMemoryData(value_extractor, process_address,
197061da546Spatrick value_size, extract_error);
198061da546Spatrick
199061da546Spatrick if (!extract_error.Success())
200061da546Spatrick return false;
201061da546Spatrick
202061da546Spatrick lldb::offset_t offset = 0;
203061da546Spatrick if (value_size <= 8) {
204*f6aab3d8Srobert Type *ty = value->getType();
205*f6aab3d8Srobert if (ty->isDoubleTy()) {
206*f6aab3d8Srobert scalar = value_extractor.GetDouble(&offset);
207*f6aab3d8Srobert return true;
208*f6aab3d8Srobert } else if (ty->isFloatTy()) {
209*f6aab3d8Srobert scalar = value_extractor.GetFloat(&offset);
210*f6aab3d8Srobert return true;
211*f6aab3d8Srobert } else {
212061da546Spatrick uint64_t u64value = value_extractor.GetMaxU64(&offset, value_size);
213dda28197Spatrick return AssignToMatchType(scalar, llvm::APInt(64, u64value),
214dda28197Spatrick value->getType());
215061da546Spatrick }
216*f6aab3d8Srobert }
217061da546Spatrick
218061da546Spatrick return false;
219061da546Spatrick }
220061da546Spatrick
AssignValue(const Value * value,lldb_private::Scalar scalar,Module & module)221dda28197Spatrick bool AssignValue(const Value *value, lldb_private::Scalar scalar,
222061da546Spatrick Module &module) {
223061da546Spatrick lldb::addr_t process_address = ResolveValue(value, module);
224061da546Spatrick
225061da546Spatrick if (process_address == LLDB_INVALID_ADDRESS)
226061da546Spatrick return false;
227061da546Spatrick
228061da546Spatrick lldb_private::Scalar cast_scalar;
229*f6aab3d8Srobert Type *vty = value->getType();
230*f6aab3d8Srobert if (vty->isFloatTy() || vty->isDoubleTy()) {
231*f6aab3d8Srobert cast_scalar = scalar;
232*f6aab3d8Srobert } else {
233dda28197Spatrick scalar.MakeUnsigned();
234dda28197Spatrick if (!AssignToMatchType(cast_scalar, scalar.UInt128(llvm::APInt()),
235dda28197Spatrick value->getType()))
236061da546Spatrick return false;
237*f6aab3d8Srobert }
238061da546Spatrick
239061da546Spatrick size_t value_byte_size = m_target_data.getTypeStoreSize(value->getType());
240061da546Spatrick
241061da546Spatrick lldb_private::DataBufferHeap buf(value_byte_size, 0);
242061da546Spatrick
243061da546Spatrick lldb_private::Status get_data_error;
244061da546Spatrick
245061da546Spatrick if (!cast_scalar.GetAsMemoryData(buf.GetBytes(), buf.GetByteSize(),
246061da546Spatrick m_byte_order, get_data_error))
247061da546Spatrick return false;
248061da546Spatrick
249061da546Spatrick lldb_private::Status write_error;
250061da546Spatrick
251061da546Spatrick m_execution_unit.WriteMemory(process_address, buf.GetBytes(),
252061da546Spatrick buf.GetByteSize(), write_error);
253061da546Spatrick
254061da546Spatrick return write_error.Success();
255061da546Spatrick }
256061da546Spatrick
ResolveConstantValue(APInt & value,const Constant * constant)257061da546Spatrick bool ResolveConstantValue(APInt &value, const Constant *constant) {
258061da546Spatrick switch (constant->getValueID()) {
259061da546Spatrick default:
260061da546Spatrick break;
261061da546Spatrick case Value::FunctionVal:
262061da546Spatrick if (const Function *constant_func = dyn_cast<Function>(constant)) {
263061da546Spatrick lldb_private::ConstString name(constant_func->getName());
264061da546Spatrick bool missing_weak = false;
265061da546Spatrick lldb::addr_t addr = m_execution_unit.FindSymbol(name, missing_weak);
266061da546Spatrick if (addr == LLDB_INVALID_ADDRESS || missing_weak)
267061da546Spatrick return false;
268061da546Spatrick value = APInt(m_target_data.getPointerSizeInBits(), addr);
269061da546Spatrick return true;
270061da546Spatrick }
271061da546Spatrick break;
272061da546Spatrick case Value::ConstantIntVal:
273061da546Spatrick if (const ConstantInt *constant_int = dyn_cast<ConstantInt>(constant)) {
274061da546Spatrick value = constant_int->getValue();
275061da546Spatrick return true;
276061da546Spatrick }
277061da546Spatrick break;
278061da546Spatrick case Value::ConstantFPVal:
279061da546Spatrick if (const ConstantFP *constant_fp = dyn_cast<ConstantFP>(constant)) {
280061da546Spatrick value = constant_fp->getValueAPF().bitcastToAPInt();
281061da546Spatrick return true;
282061da546Spatrick }
283061da546Spatrick break;
284061da546Spatrick case Value::ConstantExprVal:
285061da546Spatrick if (const ConstantExpr *constant_expr =
286061da546Spatrick dyn_cast<ConstantExpr>(constant)) {
287061da546Spatrick switch (constant_expr->getOpcode()) {
288061da546Spatrick default:
289061da546Spatrick return false;
290061da546Spatrick case Instruction::IntToPtr:
291061da546Spatrick case Instruction::PtrToInt:
292061da546Spatrick case Instruction::BitCast:
293061da546Spatrick return ResolveConstantValue(value, constant_expr->getOperand(0));
294061da546Spatrick case Instruction::GetElementPtr: {
295061da546Spatrick ConstantExpr::const_op_iterator op_cursor = constant_expr->op_begin();
296061da546Spatrick ConstantExpr::const_op_iterator op_end = constant_expr->op_end();
297061da546Spatrick
298061da546Spatrick Constant *base = dyn_cast<Constant>(*op_cursor);
299061da546Spatrick
300061da546Spatrick if (!base)
301061da546Spatrick return false;
302061da546Spatrick
303061da546Spatrick if (!ResolveConstantValue(value, base))
304061da546Spatrick return false;
305061da546Spatrick
306061da546Spatrick op_cursor++;
307061da546Spatrick
308061da546Spatrick if (op_cursor == op_end)
309061da546Spatrick return true; // no offset to apply!
310061da546Spatrick
311061da546Spatrick SmallVector<Value *, 8> indices(op_cursor, op_end);
312061da546Spatrick Type *src_elem_ty =
313061da546Spatrick cast<GEPOperator>(constant_expr)->getSourceElementType();
314*f6aab3d8Srobert
315*f6aab3d8Srobert // DataLayout::getIndexedOffsetInType assumes the indices are
316*f6aab3d8Srobert // instances of ConstantInt.
317061da546Spatrick uint64_t offset =
318061da546Spatrick m_target_data.getIndexedOffsetInType(src_elem_ty, indices);
319061da546Spatrick
320061da546Spatrick const bool is_signed = true;
321061da546Spatrick value += APInt(value.getBitWidth(), offset, is_signed);
322061da546Spatrick
323061da546Spatrick return true;
324061da546Spatrick }
325061da546Spatrick }
326061da546Spatrick }
327061da546Spatrick break;
328061da546Spatrick case Value::ConstantPointerNullVal:
329061da546Spatrick if (isa<ConstantPointerNull>(constant)) {
330061da546Spatrick value = APInt(m_target_data.getPointerSizeInBits(), 0);
331061da546Spatrick return true;
332061da546Spatrick }
333061da546Spatrick break;
334061da546Spatrick }
335061da546Spatrick return false;
336061da546Spatrick }
337061da546Spatrick
MakeArgument(const Argument * value,uint64_t address)338061da546Spatrick bool MakeArgument(const Argument *value, uint64_t address) {
339061da546Spatrick lldb::addr_t data_address = Malloc(value->getType());
340061da546Spatrick
341061da546Spatrick if (data_address == LLDB_INVALID_ADDRESS)
342061da546Spatrick return false;
343061da546Spatrick
344061da546Spatrick lldb_private::Status write_error;
345061da546Spatrick
346061da546Spatrick m_execution_unit.WritePointerToMemory(data_address, address, write_error);
347061da546Spatrick
348061da546Spatrick if (!write_error.Success()) {
349061da546Spatrick lldb_private::Status free_error;
350061da546Spatrick m_execution_unit.Free(data_address, free_error);
351061da546Spatrick return false;
352061da546Spatrick }
353061da546Spatrick
354061da546Spatrick m_values[value] = data_address;
355061da546Spatrick
356*f6aab3d8Srobert lldb_private::Log *log(GetLog(LLDBLog::Expressions));
357061da546Spatrick
358061da546Spatrick if (log) {
359061da546Spatrick LLDB_LOGF(log, "Made an allocation for argument %s",
360061da546Spatrick PrintValue(value).c_str());
361061da546Spatrick LLDB_LOGF(log, " Data region : %llx", (unsigned long long)address);
362061da546Spatrick LLDB_LOGF(log, " Ref region : %llx",
363061da546Spatrick (unsigned long long)data_address);
364061da546Spatrick }
365061da546Spatrick
366061da546Spatrick return true;
367061da546Spatrick }
368061da546Spatrick
ResolveConstant(lldb::addr_t process_address,const Constant * constant)369061da546Spatrick bool ResolveConstant(lldb::addr_t process_address, const Constant *constant) {
370061da546Spatrick APInt resolved_value;
371061da546Spatrick
372061da546Spatrick if (!ResolveConstantValue(resolved_value, constant))
373061da546Spatrick return false;
374061da546Spatrick
375061da546Spatrick size_t constant_size = m_target_data.getTypeStoreSize(constant->getType());
376061da546Spatrick lldb_private::DataBufferHeap buf(constant_size, 0);
377061da546Spatrick
378061da546Spatrick lldb_private::Status get_data_error;
379061da546Spatrick
380061da546Spatrick lldb_private::Scalar resolved_scalar(
381061da546Spatrick resolved_value.zextOrTrunc(llvm::NextPowerOf2(constant_size) * 8));
382061da546Spatrick if (!resolved_scalar.GetAsMemoryData(buf.GetBytes(), buf.GetByteSize(),
383061da546Spatrick m_byte_order, get_data_error))
384061da546Spatrick return false;
385061da546Spatrick
386061da546Spatrick lldb_private::Status write_error;
387061da546Spatrick
388061da546Spatrick m_execution_unit.WriteMemory(process_address, buf.GetBytes(),
389061da546Spatrick buf.GetByteSize(), write_error);
390061da546Spatrick
391061da546Spatrick return write_error.Success();
392061da546Spatrick }
393061da546Spatrick
Malloc(size_t size,uint8_t byte_alignment)394061da546Spatrick lldb::addr_t Malloc(size_t size, uint8_t byte_alignment) {
395061da546Spatrick lldb::addr_t ret = m_stack_pointer;
396061da546Spatrick
397061da546Spatrick ret -= size;
398061da546Spatrick ret -= (ret % byte_alignment);
399061da546Spatrick
400061da546Spatrick if (ret < m_frame_process_address)
401061da546Spatrick return LLDB_INVALID_ADDRESS;
402061da546Spatrick
403061da546Spatrick m_stack_pointer = ret;
404061da546Spatrick return ret;
405061da546Spatrick }
406061da546Spatrick
Malloc(llvm::Type * type)407061da546Spatrick lldb::addr_t Malloc(llvm::Type *type) {
408061da546Spatrick lldb_private::Status alloc_error;
409061da546Spatrick
410061da546Spatrick return Malloc(m_target_data.getTypeAllocSize(type),
411*f6aab3d8Srobert m_target_data.getPrefTypeAlign(type).value());
412061da546Spatrick }
413061da546Spatrick
PrintData(lldb::addr_t addr,llvm::Type * type)414061da546Spatrick std::string PrintData(lldb::addr_t addr, llvm::Type *type) {
415061da546Spatrick size_t length = m_target_data.getTypeStoreSize(type);
416061da546Spatrick
417061da546Spatrick lldb_private::DataBufferHeap buf(length, 0);
418061da546Spatrick
419061da546Spatrick lldb_private::Status read_error;
420061da546Spatrick
421061da546Spatrick m_execution_unit.ReadMemory(buf.GetBytes(), addr, length, read_error);
422061da546Spatrick
423061da546Spatrick if (!read_error.Success())
424061da546Spatrick return std::string("<couldn't read data>");
425061da546Spatrick
426061da546Spatrick lldb_private::StreamString ss;
427061da546Spatrick
428061da546Spatrick for (size_t i = 0; i < length; i++) {
429061da546Spatrick if ((!(i & 0xf)) && i)
430061da546Spatrick ss.Printf("%02hhx - ", buf.GetBytes()[i]);
431061da546Spatrick else
432061da546Spatrick ss.Printf("%02hhx ", buf.GetBytes()[i]);
433061da546Spatrick }
434061da546Spatrick
435dda28197Spatrick return std::string(ss.GetString());
436061da546Spatrick }
437061da546Spatrick
ResolveValue(const Value * value,Module & module)438061da546Spatrick lldb::addr_t ResolveValue(const Value *value, Module &module) {
439061da546Spatrick ValueMap::iterator i = m_values.find(value);
440061da546Spatrick
441061da546Spatrick if (i != m_values.end())
442061da546Spatrick return i->second;
443061da546Spatrick
444061da546Spatrick // Fall back and allocate space [allocation type Alloca]
445061da546Spatrick
446061da546Spatrick lldb::addr_t data_address = Malloc(value->getType());
447061da546Spatrick
448061da546Spatrick if (const Constant *constant = dyn_cast<Constant>(value)) {
449061da546Spatrick if (!ResolveConstant(data_address, constant)) {
450061da546Spatrick lldb_private::Status free_error;
451061da546Spatrick m_execution_unit.Free(data_address, free_error);
452061da546Spatrick return LLDB_INVALID_ADDRESS;
453061da546Spatrick }
454061da546Spatrick }
455061da546Spatrick
456061da546Spatrick m_values[value] = data_address;
457061da546Spatrick return data_address;
458061da546Spatrick }
459061da546Spatrick };
460061da546Spatrick
461061da546Spatrick static const char *unsupported_opcode_error =
462061da546Spatrick "Interpreter doesn't handle one of the expression's opcodes";
463061da546Spatrick static const char *unsupported_operand_error =
464061da546Spatrick "Interpreter doesn't handle one of the expression's operands";
465061da546Spatrick static const char *interpreter_internal_error =
466061da546Spatrick "Interpreter encountered an internal error";
467061da546Spatrick static const char *bad_value_error =
468061da546Spatrick "Interpreter couldn't resolve a value during execution";
469061da546Spatrick static const char *memory_allocation_error =
470061da546Spatrick "Interpreter couldn't allocate memory";
471061da546Spatrick static const char *memory_write_error = "Interpreter couldn't write to memory";
472061da546Spatrick static const char *memory_read_error = "Interpreter couldn't read from memory";
473061da546Spatrick static const char *infinite_loop_error = "Interpreter ran for too many cycles";
474061da546Spatrick static const char *too_many_functions_error =
475061da546Spatrick "Interpreter doesn't handle modules with multiple function bodies.";
476061da546Spatrick
CanResolveConstant(llvm::Constant * constant)477061da546Spatrick static bool CanResolveConstant(llvm::Constant *constant) {
478061da546Spatrick switch (constant->getValueID()) {
479061da546Spatrick default:
480061da546Spatrick return false;
481061da546Spatrick case Value::ConstantIntVal:
482061da546Spatrick case Value::ConstantFPVal:
483061da546Spatrick case Value::FunctionVal:
484061da546Spatrick return true;
485061da546Spatrick case Value::ConstantExprVal:
486061da546Spatrick if (const ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(constant)) {
487061da546Spatrick switch (constant_expr->getOpcode()) {
488061da546Spatrick default:
489061da546Spatrick return false;
490061da546Spatrick case Instruction::IntToPtr:
491061da546Spatrick case Instruction::PtrToInt:
492061da546Spatrick case Instruction::BitCast:
493061da546Spatrick return CanResolveConstant(constant_expr->getOperand(0));
494061da546Spatrick case Instruction::GetElementPtr: {
495*f6aab3d8Srobert // Check that the base can be constant-resolved.
496061da546Spatrick ConstantExpr::const_op_iterator op_cursor = constant_expr->op_begin();
497061da546Spatrick Constant *base = dyn_cast<Constant>(*op_cursor);
498*f6aab3d8Srobert if (!base || !CanResolveConstant(base))
499061da546Spatrick return false;
500061da546Spatrick
501*f6aab3d8Srobert // Check that all other operands are just ConstantInt.
502*f6aab3d8Srobert for (Value *op : make_range(constant_expr->op_begin() + 1,
503*f6aab3d8Srobert constant_expr->op_end())) {
504*f6aab3d8Srobert ConstantInt *constant_int = dyn_cast<ConstantInt>(op);
505*f6aab3d8Srobert if (!constant_int)
506*f6aab3d8Srobert return false;
507*f6aab3d8Srobert }
508*f6aab3d8Srobert return true;
509061da546Spatrick }
510061da546Spatrick }
511061da546Spatrick } else {
512061da546Spatrick return false;
513061da546Spatrick }
514061da546Spatrick case Value::ConstantPointerNullVal:
515061da546Spatrick return true;
516061da546Spatrick }
517061da546Spatrick }
518061da546Spatrick
CanInterpret(llvm::Module & module,llvm::Function & function,lldb_private::Status & error,const bool support_function_calls)519061da546Spatrick bool IRInterpreter::CanInterpret(llvm::Module &module, llvm::Function &function,
520061da546Spatrick lldb_private::Status &error,
521061da546Spatrick const bool support_function_calls) {
522*f6aab3d8Srobert lldb_private::Log *log(GetLog(LLDBLog::Expressions));
523061da546Spatrick
524061da546Spatrick bool saw_function_with_body = false;
525061da546Spatrick for (Function &f : module) {
526061da546Spatrick if (f.begin() != f.end()) {
527061da546Spatrick if (saw_function_with_body) {
528061da546Spatrick LLDB_LOGF(log, "More than one function in the module has a body");
529061da546Spatrick error.SetErrorToGenericError();
530061da546Spatrick error.SetErrorString(too_many_functions_error);
531061da546Spatrick return false;
532061da546Spatrick }
533061da546Spatrick saw_function_with_body = true;
534*f6aab3d8Srobert LLDB_LOGF(log, "Saw function with body: %s", f.getName().str().c_str());
535061da546Spatrick }
536061da546Spatrick }
537061da546Spatrick
538061da546Spatrick for (BasicBlock &bb : function) {
539061da546Spatrick for (Instruction &ii : bb) {
540061da546Spatrick switch (ii.getOpcode()) {
541061da546Spatrick default: {
542061da546Spatrick LLDB_LOGF(log, "Unsupported instruction: %s", PrintValue(&ii).c_str());
543061da546Spatrick error.SetErrorToGenericError();
544061da546Spatrick error.SetErrorString(unsupported_opcode_error);
545061da546Spatrick return false;
546061da546Spatrick }
547061da546Spatrick case Instruction::Add:
548061da546Spatrick case Instruction::Alloca:
549061da546Spatrick case Instruction::BitCast:
550061da546Spatrick case Instruction::Br:
551061da546Spatrick case Instruction::PHI:
552061da546Spatrick break;
553061da546Spatrick case Instruction::Call: {
554061da546Spatrick CallInst *call_inst = dyn_cast<CallInst>(&ii);
555061da546Spatrick
556061da546Spatrick if (!call_inst) {
557061da546Spatrick error.SetErrorToGenericError();
558061da546Spatrick error.SetErrorString(interpreter_internal_error);
559061da546Spatrick return false;
560061da546Spatrick }
561061da546Spatrick
562061da546Spatrick if (!CanIgnoreCall(call_inst) && !support_function_calls) {
563061da546Spatrick LLDB_LOGF(log, "Unsupported instruction: %s",
564061da546Spatrick PrintValue(&ii).c_str());
565061da546Spatrick error.SetErrorToGenericError();
566061da546Spatrick error.SetErrorString(unsupported_opcode_error);
567061da546Spatrick return false;
568061da546Spatrick }
569061da546Spatrick } break;
570061da546Spatrick case Instruction::GetElementPtr:
571061da546Spatrick break;
572*f6aab3d8Srobert case Instruction::FCmp:
573061da546Spatrick case Instruction::ICmp: {
574*f6aab3d8Srobert CmpInst *cmp_inst = dyn_cast<CmpInst>(&ii);
575061da546Spatrick
576*f6aab3d8Srobert if (!cmp_inst) {
577061da546Spatrick error.SetErrorToGenericError();
578061da546Spatrick error.SetErrorString(interpreter_internal_error);
579061da546Spatrick return false;
580061da546Spatrick }
581061da546Spatrick
582*f6aab3d8Srobert switch (cmp_inst->getPredicate()) {
583061da546Spatrick default: {
584061da546Spatrick LLDB_LOGF(log, "Unsupported ICmp predicate: %s",
585061da546Spatrick PrintValue(&ii).c_str());
586061da546Spatrick
587061da546Spatrick error.SetErrorToGenericError();
588061da546Spatrick error.SetErrorString(unsupported_opcode_error);
589061da546Spatrick return false;
590061da546Spatrick }
591*f6aab3d8Srobert case CmpInst::FCMP_OEQ:
592061da546Spatrick case CmpInst::ICMP_EQ:
593*f6aab3d8Srobert case CmpInst::FCMP_UNE:
594061da546Spatrick case CmpInst::ICMP_NE:
595*f6aab3d8Srobert case CmpInst::FCMP_OGT:
596061da546Spatrick case CmpInst::ICMP_UGT:
597*f6aab3d8Srobert case CmpInst::FCMP_OGE:
598061da546Spatrick case CmpInst::ICMP_UGE:
599*f6aab3d8Srobert case CmpInst::FCMP_OLT:
600061da546Spatrick case CmpInst::ICMP_ULT:
601*f6aab3d8Srobert case CmpInst::FCMP_OLE:
602061da546Spatrick case CmpInst::ICMP_ULE:
603061da546Spatrick case CmpInst::ICMP_SGT:
604061da546Spatrick case CmpInst::ICMP_SGE:
605061da546Spatrick case CmpInst::ICMP_SLT:
606061da546Spatrick case CmpInst::ICMP_SLE:
607061da546Spatrick break;
608061da546Spatrick }
609061da546Spatrick } break;
610061da546Spatrick case Instruction::And:
611061da546Spatrick case Instruction::AShr:
612061da546Spatrick case Instruction::IntToPtr:
613061da546Spatrick case Instruction::PtrToInt:
614061da546Spatrick case Instruction::Load:
615061da546Spatrick case Instruction::LShr:
616061da546Spatrick case Instruction::Mul:
617061da546Spatrick case Instruction::Or:
618061da546Spatrick case Instruction::Ret:
619061da546Spatrick case Instruction::SDiv:
620061da546Spatrick case Instruction::SExt:
621061da546Spatrick case Instruction::Shl:
622061da546Spatrick case Instruction::SRem:
623061da546Spatrick case Instruction::Store:
624061da546Spatrick case Instruction::Sub:
625061da546Spatrick case Instruction::Trunc:
626061da546Spatrick case Instruction::UDiv:
627061da546Spatrick case Instruction::URem:
628061da546Spatrick case Instruction::Xor:
629061da546Spatrick case Instruction::ZExt:
630061da546Spatrick break;
631*f6aab3d8Srobert case Instruction::FAdd:
632*f6aab3d8Srobert case Instruction::FSub:
633*f6aab3d8Srobert case Instruction::FMul:
634*f6aab3d8Srobert case Instruction::FDiv:
635*f6aab3d8Srobert break;
636061da546Spatrick }
637061da546Spatrick
638061da546Spatrick for (unsigned oi = 0, oe = ii.getNumOperands(); oi != oe; ++oi) {
639061da546Spatrick Value *operand = ii.getOperand(oi);
640061da546Spatrick Type *operand_type = operand->getType();
641061da546Spatrick
642061da546Spatrick switch (operand_type->getTypeID()) {
643061da546Spatrick default:
644061da546Spatrick break;
645dda28197Spatrick case Type::FixedVectorTyID:
646dda28197Spatrick case Type::ScalableVectorTyID: {
647061da546Spatrick LLDB_LOGF(log, "Unsupported operand type: %s",
648061da546Spatrick PrintType(operand_type).c_str());
649061da546Spatrick error.SetErrorString(unsupported_operand_error);
650061da546Spatrick return false;
651061da546Spatrick }
652061da546Spatrick }
653061da546Spatrick
654061da546Spatrick // The IR interpreter currently doesn't know about
655061da546Spatrick // 128-bit integers. As they're not that frequent,
656061da546Spatrick // we can just fall back to the JIT rather than
657061da546Spatrick // choking.
658061da546Spatrick if (operand_type->getPrimitiveSizeInBits() > 64) {
659061da546Spatrick LLDB_LOGF(log, "Unsupported operand type: %s",
660061da546Spatrick PrintType(operand_type).c_str());
661061da546Spatrick error.SetErrorString(unsupported_operand_error);
662061da546Spatrick return false;
663061da546Spatrick }
664061da546Spatrick
665061da546Spatrick if (Constant *constant = llvm::dyn_cast<Constant>(operand)) {
666061da546Spatrick if (!CanResolveConstant(constant)) {
667061da546Spatrick LLDB_LOGF(log, "Unsupported constant: %s",
668061da546Spatrick PrintValue(constant).c_str());
669061da546Spatrick error.SetErrorString(unsupported_operand_error);
670061da546Spatrick return false;
671061da546Spatrick }
672061da546Spatrick }
673061da546Spatrick }
674061da546Spatrick }
675061da546Spatrick }
676061da546Spatrick
677061da546Spatrick return true;
678061da546Spatrick }
679061da546Spatrick
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)680061da546Spatrick bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function,
681061da546Spatrick llvm::ArrayRef<lldb::addr_t> args,
682061da546Spatrick lldb_private::IRExecutionUnit &execution_unit,
683061da546Spatrick lldb_private::Status &error,
684061da546Spatrick lldb::addr_t stack_frame_bottom,
685061da546Spatrick lldb::addr_t stack_frame_top,
686061da546Spatrick lldb_private::ExecutionContext &exe_ctx) {
687*f6aab3d8Srobert lldb_private::Log *log(GetLog(LLDBLog::Expressions));
688061da546Spatrick
689061da546Spatrick if (log) {
690061da546Spatrick std::string s;
691061da546Spatrick raw_string_ostream oss(s);
692061da546Spatrick
693061da546Spatrick module.print(oss, nullptr);
694061da546Spatrick
695061da546Spatrick oss.flush();
696061da546Spatrick
697061da546Spatrick LLDB_LOGF(log, "Module as passed in to IRInterpreter::Interpret: \n\"%s\"",
698061da546Spatrick s.c_str());
699061da546Spatrick }
700061da546Spatrick
701061da546Spatrick DataLayout data_layout(&module);
702061da546Spatrick
703061da546Spatrick InterpreterStackFrame frame(data_layout, execution_unit, stack_frame_bottom,
704061da546Spatrick stack_frame_top);
705061da546Spatrick
706061da546Spatrick if (frame.m_frame_process_address == LLDB_INVALID_ADDRESS) {
707061da546Spatrick error.SetErrorString("Couldn't allocate stack frame");
708061da546Spatrick }
709061da546Spatrick
710061da546Spatrick int arg_index = 0;
711061da546Spatrick
712061da546Spatrick for (llvm::Function::arg_iterator ai = function.arg_begin(),
713061da546Spatrick ae = function.arg_end();
714061da546Spatrick ai != ae; ++ai, ++arg_index) {
715061da546Spatrick if (args.size() <= static_cast<size_t>(arg_index)) {
716061da546Spatrick error.SetErrorString("Not enough arguments passed in to function");
717061da546Spatrick return false;
718061da546Spatrick }
719061da546Spatrick
720061da546Spatrick lldb::addr_t ptr = args[arg_index];
721061da546Spatrick
722061da546Spatrick frame.MakeArgument(&*ai, ptr);
723061da546Spatrick }
724061da546Spatrick
725061da546Spatrick uint32_t num_insts = 0;
726061da546Spatrick
727061da546Spatrick frame.Jump(&function.front());
728061da546Spatrick
729061da546Spatrick while (frame.m_ii != frame.m_ie && (++num_insts < 4096)) {
730061da546Spatrick const Instruction *inst = &*frame.m_ii;
731061da546Spatrick
732061da546Spatrick LLDB_LOGF(log, "Interpreting %s", PrintValue(inst).c_str());
733061da546Spatrick
734061da546Spatrick switch (inst->getOpcode()) {
735061da546Spatrick default:
736061da546Spatrick break;
737061da546Spatrick
738061da546Spatrick case Instruction::Add:
739061da546Spatrick case Instruction::Sub:
740061da546Spatrick case Instruction::Mul:
741061da546Spatrick case Instruction::SDiv:
742061da546Spatrick case Instruction::UDiv:
743061da546Spatrick case Instruction::SRem:
744061da546Spatrick case Instruction::URem:
745061da546Spatrick case Instruction::Shl:
746061da546Spatrick case Instruction::LShr:
747061da546Spatrick case Instruction::AShr:
748061da546Spatrick case Instruction::And:
749061da546Spatrick case Instruction::Or:
750*f6aab3d8Srobert case Instruction::Xor:
751*f6aab3d8Srobert case Instruction::FAdd:
752*f6aab3d8Srobert case Instruction::FSub:
753*f6aab3d8Srobert case Instruction::FMul:
754*f6aab3d8Srobert case Instruction::FDiv: {
755061da546Spatrick const BinaryOperator *bin_op = dyn_cast<BinaryOperator>(inst);
756061da546Spatrick
757061da546Spatrick if (!bin_op) {
758061da546Spatrick LLDB_LOGF(
759061da546Spatrick log,
760061da546Spatrick "getOpcode() returns %s, but instruction is not a BinaryOperator",
761061da546Spatrick inst->getOpcodeName());
762061da546Spatrick error.SetErrorToGenericError();
763061da546Spatrick error.SetErrorString(interpreter_internal_error);
764061da546Spatrick return false;
765061da546Spatrick }
766061da546Spatrick
767061da546Spatrick Value *lhs = inst->getOperand(0);
768061da546Spatrick Value *rhs = inst->getOperand(1);
769061da546Spatrick
770061da546Spatrick lldb_private::Scalar L;
771061da546Spatrick lldb_private::Scalar R;
772061da546Spatrick
773061da546Spatrick if (!frame.EvaluateValue(L, lhs, module)) {
774061da546Spatrick LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(lhs).c_str());
775061da546Spatrick error.SetErrorToGenericError();
776061da546Spatrick error.SetErrorString(bad_value_error);
777061da546Spatrick return false;
778061da546Spatrick }
779061da546Spatrick
780061da546Spatrick if (!frame.EvaluateValue(R, rhs, module)) {
781061da546Spatrick LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(rhs).c_str());
782061da546Spatrick error.SetErrorToGenericError();
783061da546Spatrick error.SetErrorString(bad_value_error);
784061da546Spatrick return false;
785061da546Spatrick }
786061da546Spatrick
787061da546Spatrick lldb_private::Scalar result;
788061da546Spatrick
789061da546Spatrick switch (inst->getOpcode()) {
790061da546Spatrick default:
791061da546Spatrick break;
792061da546Spatrick case Instruction::Add:
793*f6aab3d8Srobert case Instruction::FAdd:
794061da546Spatrick result = L + R;
795061da546Spatrick break;
796061da546Spatrick case Instruction::Mul:
797*f6aab3d8Srobert case Instruction::FMul:
798061da546Spatrick result = L * R;
799061da546Spatrick break;
800061da546Spatrick case Instruction::Sub:
801*f6aab3d8Srobert case Instruction::FSub:
802061da546Spatrick result = L - R;
803061da546Spatrick break;
804061da546Spatrick case Instruction::SDiv:
805061da546Spatrick L.MakeSigned();
806061da546Spatrick R.MakeSigned();
807061da546Spatrick result = L / R;
808061da546Spatrick break;
809061da546Spatrick case Instruction::UDiv:
810061da546Spatrick L.MakeUnsigned();
811061da546Spatrick R.MakeUnsigned();
812061da546Spatrick result = L / R;
813061da546Spatrick break;
814*f6aab3d8Srobert case Instruction::FDiv:
815*f6aab3d8Srobert result = L / R;
816*f6aab3d8Srobert break;
817061da546Spatrick case Instruction::SRem:
818061da546Spatrick L.MakeSigned();
819061da546Spatrick R.MakeSigned();
820061da546Spatrick result = L % R;
821061da546Spatrick break;
822061da546Spatrick case Instruction::URem:
823061da546Spatrick L.MakeUnsigned();
824061da546Spatrick R.MakeUnsigned();
825061da546Spatrick result = L % R;
826061da546Spatrick break;
827061da546Spatrick case Instruction::Shl:
828061da546Spatrick result = L << R;
829061da546Spatrick break;
830061da546Spatrick case Instruction::AShr:
831061da546Spatrick result = L >> R;
832061da546Spatrick break;
833061da546Spatrick case Instruction::LShr:
834061da546Spatrick result = L;
835061da546Spatrick result.ShiftRightLogical(R);
836061da546Spatrick break;
837061da546Spatrick case Instruction::And:
838061da546Spatrick result = L & R;
839061da546Spatrick break;
840061da546Spatrick case Instruction::Or:
841061da546Spatrick result = L | R;
842061da546Spatrick break;
843061da546Spatrick case Instruction::Xor:
844061da546Spatrick result = L ^ R;
845061da546Spatrick break;
846061da546Spatrick }
847061da546Spatrick
848061da546Spatrick frame.AssignValue(inst, result, module);
849061da546Spatrick
850061da546Spatrick if (log) {
851061da546Spatrick LLDB_LOGF(log, "Interpreted a %s", inst->getOpcodeName());
852061da546Spatrick LLDB_LOGF(log, " L : %s", frame.SummarizeValue(lhs).c_str());
853061da546Spatrick LLDB_LOGF(log, " R : %s", frame.SummarizeValue(rhs).c_str());
854061da546Spatrick LLDB_LOGF(log, " = : %s", frame.SummarizeValue(inst).c_str());
855061da546Spatrick }
856061da546Spatrick } break;
857061da546Spatrick case Instruction::Alloca: {
858061da546Spatrick const AllocaInst *alloca_inst = cast<AllocaInst>(inst);
859061da546Spatrick
860061da546Spatrick if (alloca_inst->isArrayAllocation()) {
861061da546Spatrick LLDB_LOGF(log,
862061da546Spatrick "AllocaInsts are not handled if isArrayAllocation() is true");
863061da546Spatrick error.SetErrorToGenericError();
864061da546Spatrick error.SetErrorString(unsupported_opcode_error);
865061da546Spatrick return false;
866061da546Spatrick }
867061da546Spatrick
868061da546Spatrick // The semantics of Alloca are:
869061da546Spatrick // Create a region R of virtual memory of type T, backed by a data
870061da546Spatrick // buffer
871061da546Spatrick // Create a region P of virtual memory of type T*, backed by a data
872061da546Spatrick // buffer
873061da546Spatrick // Write the virtual address of R into P
874061da546Spatrick
875061da546Spatrick Type *T = alloca_inst->getAllocatedType();
876061da546Spatrick Type *Tptr = alloca_inst->getType();
877061da546Spatrick
878061da546Spatrick lldb::addr_t R = frame.Malloc(T);
879061da546Spatrick
880061da546Spatrick if (R == LLDB_INVALID_ADDRESS) {
881061da546Spatrick LLDB_LOGF(log, "Couldn't allocate memory for an AllocaInst");
882061da546Spatrick error.SetErrorToGenericError();
883061da546Spatrick error.SetErrorString(memory_allocation_error);
884061da546Spatrick return false;
885061da546Spatrick }
886061da546Spatrick
887061da546Spatrick lldb::addr_t P = frame.Malloc(Tptr);
888061da546Spatrick
889061da546Spatrick if (P == LLDB_INVALID_ADDRESS) {
890061da546Spatrick LLDB_LOGF(log,
891061da546Spatrick "Couldn't allocate the result pointer for an AllocaInst");
892061da546Spatrick error.SetErrorToGenericError();
893061da546Spatrick error.SetErrorString(memory_allocation_error);
894061da546Spatrick return false;
895061da546Spatrick }
896061da546Spatrick
897061da546Spatrick lldb_private::Status write_error;
898061da546Spatrick
899061da546Spatrick execution_unit.WritePointerToMemory(P, R, write_error);
900061da546Spatrick
901061da546Spatrick if (!write_error.Success()) {
902061da546Spatrick LLDB_LOGF(log, "Couldn't write the result pointer for an AllocaInst");
903061da546Spatrick error.SetErrorToGenericError();
904061da546Spatrick error.SetErrorString(memory_write_error);
905061da546Spatrick lldb_private::Status free_error;
906061da546Spatrick execution_unit.Free(P, free_error);
907061da546Spatrick execution_unit.Free(R, free_error);
908061da546Spatrick return false;
909061da546Spatrick }
910061da546Spatrick
911061da546Spatrick frame.m_values[alloca_inst] = P;
912061da546Spatrick
913061da546Spatrick if (log) {
914061da546Spatrick LLDB_LOGF(log, "Interpreted an AllocaInst");
915061da546Spatrick LLDB_LOGF(log, " R : 0x%" PRIx64, R);
916061da546Spatrick LLDB_LOGF(log, " P : 0x%" PRIx64, P);
917061da546Spatrick }
918061da546Spatrick } break;
919061da546Spatrick case Instruction::BitCast:
920061da546Spatrick case Instruction::ZExt: {
921061da546Spatrick const CastInst *cast_inst = cast<CastInst>(inst);
922061da546Spatrick
923061da546Spatrick Value *source = cast_inst->getOperand(0);
924061da546Spatrick
925061da546Spatrick lldb_private::Scalar S;
926061da546Spatrick
927061da546Spatrick if (!frame.EvaluateValue(S, source, module)) {
928061da546Spatrick LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(source).c_str());
929061da546Spatrick error.SetErrorToGenericError();
930061da546Spatrick error.SetErrorString(bad_value_error);
931061da546Spatrick return false;
932061da546Spatrick }
933061da546Spatrick
934061da546Spatrick frame.AssignValue(inst, S, module);
935061da546Spatrick } break;
936061da546Spatrick case Instruction::SExt: {
937061da546Spatrick const CastInst *cast_inst = cast<CastInst>(inst);
938061da546Spatrick
939061da546Spatrick Value *source = cast_inst->getOperand(0);
940061da546Spatrick
941061da546Spatrick lldb_private::Scalar S;
942061da546Spatrick
943061da546Spatrick if (!frame.EvaluateValue(S, source, module)) {
944061da546Spatrick LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(source).c_str());
945061da546Spatrick error.SetErrorToGenericError();
946061da546Spatrick error.SetErrorString(bad_value_error);
947061da546Spatrick return false;
948061da546Spatrick }
949061da546Spatrick
950061da546Spatrick S.MakeSigned();
951061da546Spatrick
952061da546Spatrick lldb_private::Scalar S_signextend(S.SLongLong());
953061da546Spatrick
954061da546Spatrick frame.AssignValue(inst, S_signextend, module);
955061da546Spatrick } break;
956061da546Spatrick case Instruction::Br: {
957061da546Spatrick const BranchInst *br_inst = cast<BranchInst>(inst);
958061da546Spatrick
959061da546Spatrick if (br_inst->isConditional()) {
960061da546Spatrick Value *condition = br_inst->getCondition();
961061da546Spatrick
962061da546Spatrick lldb_private::Scalar C;
963061da546Spatrick
964061da546Spatrick if (!frame.EvaluateValue(C, condition, module)) {
965061da546Spatrick LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(condition).c_str());
966061da546Spatrick error.SetErrorToGenericError();
967061da546Spatrick error.SetErrorString(bad_value_error);
968061da546Spatrick return false;
969061da546Spatrick }
970061da546Spatrick
971061da546Spatrick if (!C.IsZero())
972061da546Spatrick frame.Jump(br_inst->getSuccessor(0));
973061da546Spatrick else
974061da546Spatrick frame.Jump(br_inst->getSuccessor(1));
975061da546Spatrick
976061da546Spatrick if (log) {
977061da546Spatrick LLDB_LOGF(log, "Interpreted a BrInst with a condition");
978061da546Spatrick LLDB_LOGF(log, " cond : %s",
979061da546Spatrick frame.SummarizeValue(condition).c_str());
980061da546Spatrick }
981061da546Spatrick } else {
982061da546Spatrick frame.Jump(br_inst->getSuccessor(0));
983061da546Spatrick
984061da546Spatrick if (log) {
985061da546Spatrick LLDB_LOGF(log, "Interpreted a BrInst with no condition");
986061da546Spatrick }
987061da546Spatrick }
988061da546Spatrick }
989061da546Spatrick continue;
990061da546Spatrick case Instruction::PHI: {
991061da546Spatrick const PHINode *phi_inst = cast<PHINode>(inst);
992061da546Spatrick if (!frame.m_prev_bb) {
993061da546Spatrick LLDB_LOGF(log,
994061da546Spatrick "Encountered PHI node without having jumped from another "
995061da546Spatrick "basic block");
996061da546Spatrick error.SetErrorToGenericError();
997061da546Spatrick error.SetErrorString(interpreter_internal_error);
998061da546Spatrick return false;
999061da546Spatrick }
1000061da546Spatrick
1001061da546Spatrick Value *value = phi_inst->getIncomingValueForBlock(frame.m_prev_bb);
1002061da546Spatrick lldb_private::Scalar result;
1003061da546Spatrick if (!frame.EvaluateValue(result, value, module)) {
1004061da546Spatrick LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(value).c_str());
1005061da546Spatrick error.SetErrorToGenericError();
1006061da546Spatrick error.SetErrorString(bad_value_error);
1007061da546Spatrick return false;
1008061da546Spatrick }
1009061da546Spatrick frame.AssignValue(inst, result, module);
1010061da546Spatrick
1011061da546Spatrick if (log) {
1012061da546Spatrick LLDB_LOGF(log, "Interpreted a %s", inst->getOpcodeName());
1013061da546Spatrick LLDB_LOGF(log, " Incoming value : %s",
1014061da546Spatrick frame.SummarizeValue(value).c_str());
1015061da546Spatrick }
1016061da546Spatrick } break;
1017061da546Spatrick case Instruction::GetElementPtr: {
1018061da546Spatrick const GetElementPtrInst *gep_inst = cast<GetElementPtrInst>(inst);
1019061da546Spatrick
1020061da546Spatrick const Value *pointer_operand = gep_inst->getPointerOperand();
1021061da546Spatrick Type *src_elem_ty = gep_inst->getSourceElementType();
1022061da546Spatrick
1023061da546Spatrick lldb_private::Scalar P;
1024061da546Spatrick
1025061da546Spatrick if (!frame.EvaluateValue(P, pointer_operand, module)) {
1026061da546Spatrick LLDB_LOGF(log, "Couldn't evaluate %s",
1027061da546Spatrick PrintValue(pointer_operand).c_str());
1028061da546Spatrick error.SetErrorToGenericError();
1029061da546Spatrick error.SetErrorString(bad_value_error);
1030061da546Spatrick return false;
1031061da546Spatrick }
1032061da546Spatrick
1033061da546Spatrick typedef SmallVector<Value *, 8> IndexVector;
1034061da546Spatrick typedef IndexVector::iterator IndexIterator;
1035061da546Spatrick
1036061da546Spatrick SmallVector<Value *, 8> indices(gep_inst->idx_begin(),
1037061da546Spatrick gep_inst->idx_end());
1038061da546Spatrick
1039061da546Spatrick SmallVector<Value *, 8> const_indices;
1040061da546Spatrick
1041061da546Spatrick for (IndexIterator ii = indices.begin(), ie = indices.end(); ii != ie;
1042061da546Spatrick ++ii) {
1043061da546Spatrick ConstantInt *constant_index = dyn_cast<ConstantInt>(*ii);
1044061da546Spatrick
1045061da546Spatrick if (!constant_index) {
1046061da546Spatrick lldb_private::Scalar I;
1047061da546Spatrick
1048061da546Spatrick if (!frame.EvaluateValue(I, *ii, module)) {
1049061da546Spatrick LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(*ii).c_str());
1050061da546Spatrick error.SetErrorToGenericError();
1051061da546Spatrick error.SetErrorString(bad_value_error);
1052061da546Spatrick return false;
1053061da546Spatrick }
1054061da546Spatrick
1055061da546Spatrick LLDB_LOGF(log, "Evaluated constant index %s as %llu",
1056061da546Spatrick PrintValue(*ii).c_str(), I.ULongLong(LLDB_INVALID_ADDRESS));
1057061da546Spatrick
1058061da546Spatrick constant_index = cast<ConstantInt>(ConstantInt::get(
1059061da546Spatrick (*ii)->getType(), I.ULongLong(LLDB_INVALID_ADDRESS)));
1060061da546Spatrick }
1061061da546Spatrick
1062061da546Spatrick const_indices.push_back(constant_index);
1063061da546Spatrick }
1064061da546Spatrick
1065061da546Spatrick uint64_t offset =
1066061da546Spatrick data_layout.getIndexedOffsetInType(src_elem_ty, const_indices);
1067061da546Spatrick
1068061da546Spatrick lldb_private::Scalar Poffset = P + offset;
1069061da546Spatrick
1070061da546Spatrick frame.AssignValue(inst, Poffset, module);
1071061da546Spatrick
1072061da546Spatrick if (log) {
1073061da546Spatrick LLDB_LOGF(log, "Interpreted a GetElementPtrInst");
1074061da546Spatrick LLDB_LOGF(log, " P : %s",
1075061da546Spatrick frame.SummarizeValue(pointer_operand).c_str());
1076061da546Spatrick LLDB_LOGF(log, " Poffset : %s", frame.SummarizeValue(inst).c_str());
1077061da546Spatrick }
1078061da546Spatrick } break;
1079*f6aab3d8Srobert case Instruction::FCmp:
1080061da546Spatrick case Instruction::ICmp: {
1081*f6aab3d8Srobert const CmpInst *icmp_inst = cast<CmpInst>(inst);
1082061da546Spatrick
1083061da546Spatrick CmpInst::Predicate predicate = icmp_inst->getPredicate();
1084061da546Spatrick
1085061da546Spatrick Value *lhs = inst->getOperand(0);
1086061da546Spatrick Value *rhs = inst->getOperand(1);
1087061da546Spatrick
1088061da546Spatrick lldb_private::Scalar L;
1089061da546Spatrick lldb_private::Scalar R;
1090061da546Spatrick
1091061da546Spatrick if (!frame.EvaluateValue(L, lhs, module)) {
1092061da546Spatrick LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(lhs).c_str());
1093061da546Spatrick error.SetErrorToGenericError();
1094061da546Spatrick error.SetErrorString(bad_value_error);
1095061da546Spatrick return false;
1096061da546Spatrick }
1097061da546Spatrick
1098061da546Spatrick if (!frame.EvaluateValue(R, rhs, module)) {
1099061da546Spatrick LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(rhs).c_str());
1100061da546Spatrick error.SetErrorToGenericError();
1101061da546Spatrick error.SetErrorString(bad_value_error);
1102061da546Spatrick return false;
1103061da546Spatrick }
1104061da546Spatrick
1105061da546Spatrick lldb_private::Scalar result;
1106061da546Spatrick
1107061da546Spatrick switch (predicate) {
1108061da546Spatrick default:
1109061da546Spatrick return false;
1110061da546Spatrick case CmpInst::ICMP_EQ:
1111*f6aab3d8Srobert case CmpInst::FCMP_OEQ:
1112061da546Spatrick result = (L == R);
1113061da546Spatrick break;
1114061da546Spatrick case CmpInst::ICMP_NE:
1115*f6aab3d8Srobert case CmpInst::FCMP_UNE:
1116061da546Spatrick result = (L != R);
1117061da546Spatrick break;
1118061da546Spatrick case CmpInst::ICMP_UGT:
1119061da546Spatrick L.MakeUnsigned();
1120061da546Spatrick R.MakeUnsigned();
1121061da546Spatrick result = (L > R);
1122061da546Spatrick break;
1123061da546Spatrick case CmpInst::ICMP_UGE:
1124061da546Spatrick L.MakeUnsigned();
1125061da546Spatrick R.MakeUnsigned();
1126061da546Spatrick result = (L >= R);
1127061da546Spatrick break;
1128*f6aab3d8Srobert case CmpInst::FCMP_OGE:
1129*f6aab3d8Srobert result = (L >= R);
1130*f6aab3d8Srobert break;
1131*f6aab3d8Srobert case CmpInst::FCMP_OGT:
1132*f6aab3d8Srobert result = (L > R);
1133*f6aab3d8Srobert break;
1134061da546Spatrick case CmpInst::ICMP_ULT:
1135061da546Spatrick L.MakeUnsigned();
1136061da546Spatrick R.MakeUnsigned();
1137061da546Spatrick result = (L < R);
1138061da546Spatrick break;
1139*f6aab3d8Srobert case CmpInst::FCMP_OLT:
1140*f6aab3d8Srobert result = (L < R);
1141*f6aab3d8Srobert break;
1142061da546Spatrick case CmpInst::ICMP_ULE:
1143061da546Spatrick L.MakeUnsigned();
1144061da546Spatrick R.MakeUnsigned();
1145061da546Spatrick result = (L <= R);
1146061da546Spatrick break;
1147*f6aab3d8Srobert case CmpInst::FCMP_OLE:
1148*f6aab3d8Srobert result = (L <= R);
1149*f6aab3d8Srobert break;
1150061da546Spatrick case CmpInst::ICMP_SGT:
1151061da546Spatrick L.MakeSigned();
1152061da546Spatrick R.MakeSigned();
1153061da546Spatrick result = (L > R);
1154061da546Spatrick break;
1155061da546Spatrick case CmpInst::ICMP_SGE:
1156061da546Spatrick L.MakeSigned();
1157061da546Spatrick R.MakeSigned();
1158061da546Spatrick result = (L >= R);
1159061da546Spatrick break;
1160061da546Spatrick case CmpInst::ICMP_SLT:
1161061da546Spatrick L.MakeSigned();
1162061da546Spatrick R.MakeSigned();
1163061da546Spatrick result = (L < R);
1164061da546Spatrick break;
1165061da546Spatrick case CmpInst::ICMP_SLE:
1166061da546Spatrick L.MakeSigned();
1167061da546Spatrick R.MakeSigned();
1168061da546Spatrick result = (L <= R);
1169061da546Spatrick break;
1170061da546Spatrick }
1171061da546Spatrick
1172061da546Spatrick frame.AssignValue(inst, result, module);
1173061da546Spatrick
1174061da546Spatrick if (log) {
1175061da546Spatrick LLDB_LOGF(log, "Interpreted an ICmpInst");
1176061da546Spatrick LLDB_LOGF(log, " L : %s", frame.SummarizeValue(lhs).c_str());
1177061da546Spatrick LLDB_LOGF(log, " R : %s", frame.SummarizeValue(rhs).c_str());
1178061da546Spatrick LLDB_LOGF(log, " = : %s", frame.SummarizeValue(inst).c_str());
1179061da546Spatrick }
1180061da546Spatrick } break;
1181061da546Spatrick case Instruction::IntToPtr: {
1182061da546Spatrick const IntToPtrInst *int_to_ptr_inst = cast<IntToPtrInst>(inst);
1183061da546Spatrick
1184061da546Spatrick Value *src_operand = int_to_ptr_inst->getOperand(0);
1185061da546Spatrick
1186061da546Spatrick lldb_private::Scalar I;
1187061da546Spatrick
1188061da546Spatrick if (!frame.EvaluateValue(I, src_operand, module)) {
1189061da546Spatrick LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(src_operand).c_str());
1190061da546Spatrick error.SetErrorToGenericError();
1191061da546Spatrick error.SetErrorString(bad_value_error);
1192061da546Spatrick return false;
1193061da546Spatrick }
1194061da546Spatrick
1195061da546Spatrick frame.AssignValue(inst, I, module);
1196061da546Spatrick
1197061da546Spatrick if (log) {
1198061da546Spatrick LLDB_LOGF(log, "Interpreted an IntToPtr");
1199061da546Spatrick LLDB_LOGF(log, " Src : %s", frame.SummarizeValue(src_operand).c_str());
1200061da546Spatrick LLDB_LOGF(log, " = : %s", frame.SummarizeValue(inst).c_str());
1201061da546Spatrick }
1202061da546Spatrick } break;
1203061da546Spatrick case Instruction::PtrToInt: {
1204061da546Spatrick const PtrToIntInst *ptr_to_int_inst = cast<PtrToIntInst>(inst);
1205061da546Spatrick
1206061da546Spatrick Value *src_operand = ptr_to_int_inst->getOperand(0);
1207061da546Spatrick
1208061da546Spatrick lldb_private::Scalar I;
1209061da546Spatrick
1210061da546Spatrick if (!frame.EvaluateValue(I, src_operand, module)) {
1211061da546Spatrick LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(src_operand).c_str());
1212061da546Spatrick error.SetErrorToGenericError();
1213061da546Spatrick error.SetErrorString(bad_value_error);
1214061da546Spatrick return false;
1215061da546Spatrick }
1216061da546Spatrick
1217061da546Spatrick frame.AssignValue(inst, I, module);
1218061da546Spatrick
1219061da546Spatrick if (log) {
1220061da546Spatrick LLDB_LOGF(log, "Interpreted a PtrToInt");
1221061da546Spatrick LLDB_LOGF(log, " Src : %s", frame.SummarizeValue(src_operand).c_str());
1222061da546Spatrick LLDB_LOGF(log, " = : %s", frame.SummarizeValue(inst).c_str());
1223061da546Spatrick }
1224061da546Spatrick } break;
1225061da546Spatrick case Instruction::Trunc: {
1226061da546Spatrick const TruncInst *trunc_inst = cast<TruncInst>(inst);
1227061da546Spatrick
1228061da546Spatrick Value *src_operand = trunc_inst->getOperand(0);
1229061da546Spatrick
1230061da546Spatrick lldb_private::Scalar I;
1231061da546Spatrick
1232061da546Spatrick if (!frame.EvaluateValue(I, src_operand, module)) {
1233061da546Spatrick LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(src_operand).c_str());
1234061da546Spatrick error.SetErrorToGenericError();
1235061da546Spatrick error.SetErrorString(bad_value_error);
1236061da546Spatrick return false;
1237061da546Spatrick }
1238061da546Spatrick
1239061da546Spatrick frame.AssignValue(inst, I, module);
1240061da546Spatrick
1241061da546Spatrick if (log) {
1242061da546Spatrick LLDB_LOGF(log, "Interpreted a Trunc");
1243061da546Spatrick LLDB_LOGF(log, " Src : %s", frame.SummarizeValue(src_operand).c_str());
1244061da546Spatrick LLDB_LOGF(log, " = : %s", frame.SummarizeValue(inst).c_str());
1245061da546Spatrick }
1246061da546Spatrick } break;
1247061da546Spatrick case Instruction::Load: {
1248061da546Spatrick const LoadInst *load_inst = cast<LoadInst>(inst);
1249061da546Spatrick
1250061da546Spatrick // The semantics of Load are:
1251061da546Spatrick // Create a region D that will contain the loaded data
1252061da546Spatrick // Resolve the region P containing a pointer
1253061da546Spatrick // Dereference P to get the region R that the data should be loaded from
1254061da546Spatrick // Transfer a unit of type type(D) from R to D
1255061da546Spatrick
1256061da546Spatrick const Value *pointer_operand = load_inst->getPointerOperand();
1257061da546Spatrick
1258061da546Spatrick lldb::addr_t D = frame.ResolveValue(load_inst, module);
1259061da546Spatrick lldb::addr_t P = frame.ResolveValue(pointer_operand, module);
1260061da546Spatrick
1261061da546Spatrick if (D == LLDB_INVALID_ADDRESS) {
1262061da546Spatrick LLDB_LOGF(log, "LoadInst's value doesn't resolve to anything");
1263061da546Spatrick error.SetErrorToGenericError();
1264061da546Spatrick error.SetErrorString(bad_value_error);
1265061da546Spatrick return false;
1266061da546Spatrick }
1267061da546Spatrick
1268061da546Spatrick if (P == LLDB_INVALID_ADDRESS) {
1269061da546Spatrick LLDB_LOGF(log, "LoadInst's pointer doesn't resolve to anything");
1270061da546Spatrick error.SetErrorToGenericError();
1271061da546Spatrick error.SetErrorString(bad_value_error);
1272061da546Spatrick return false;
1273061da546Spatrick }
1274061da546Spatrick
1275061da546Spatrick lldb::addr_t R;
1276061da546Spatrick lldb_private::Status read_error;
1277061da546Spatrick execution_unit.ReadPointerFromMemory(&R, P, read_error);
1278061da546Spatrick
1279061da546Spatrick if (!read_error.Success()) {
1280061da546Spatrick LLDB_LOGF(log, "Couldn't read the address to be loaded for a LoadInst");
1281061da546Spatrick error.SetErrorToGenericError();
1282061da546Spatrick error.SetErrorString(memory_read_error);
1283061da546Spatrick return false;
1284061da546Spatrick }
1285061da546Spatrick
1286*f6aab3d8Srobert Type *target_ty = load_inst->getType();
1287061da546Spatrick size_t target_size = data_layout.getTypeStoreSize(target_ty);
1288061da546Spatrick lldb_private::DataBufferHeap buffer(target_size, 0);
1289061da546Spatrick
1290061da546Spatrick read_error.Clear();
1291061da546Spatrick execution_unit.ReadMemory(buffer.GetBytes(), R, buffer.GetByteSize(),
1292061da546Spatrick read_error);
1293061da546Spatrick if (!read_error.Success()) {
1294061da546Spatrick LLDB_LOGF(log, "Couldn't read from a region on behalf of a LoadInst");
1295061da546Spatrick error.SetErrorToGenericError();
1296061da546Spatrick error.SetErrorString(memory_read_error);
1297061da546Spatrick return false;
1298061da546Spatrick }
1299061da546Spatrick
1300061da546Spatrick lldb_private::Status write_error;
1301061da546Spatrick execution_unit.WriteMemory(D, buffer.GetBytes(), buffer.GetByteSize(),
1302061da546Spatrick write_error);
1303061da546Spatrick if (!write_error.Success()) {
1304061da546Spatrick LLDB_LOGF(log, "Couldn't write to a region on behalf of a LoadInst");
1305061da546Spatrick error.SetErrorToGenericError();
1306be691f3bSpatrick error.SetErrorString(memory_write_error);
1307061da546Spatrick return false;
1308061da546Spatrick }
1309061da546Spatrick
1310061da546Spatrick if (log) {
1311061da546Spatrick LLDB_LOGF(log, "Interpreted a LoadInst");
1312061da546Spatrick LLDB_LOGF(log, " P : 0x%" PRIx64, P);
1313061da546Spatrick LLDB_LOGF(log, " R : 0x%" PRIx64, R);
1314061da546Spatrick LLDB_LOGF(log, " D : 0x%" PRIx64, D);
1315061da546Spatrick }
1316061da546Spatrick } break;
1317061da546Spatrick case Instruction::Ret: {
1318061da546Spatrick return true;
1319061da546Spatrick }
1320061da546Spatrick case Instruction::Store: {
1321061da546Spatrick const StoreInst *store_inst = cast<StoreInst>(inst);
1322061da546Spatrick
1323061da546Spatrick // The semantics of Store are:
1324061da546Spatrick // Resolve the region D containing the data to be stored
1325061da546Spatrick // Resolve the region P containing a pointer
1326061da546Spatrick // Dereference P to get the region R that the data should be stored in
1327061da546Spatrick // Transfer a unit of type type(D) from D to R
1328061da546Spatrick
1329061da546Spatrick const Value *value_operand = store_inst->getValueOperand();
1330061da546Spatrick const Value *pointer_operand = store_inst->getPointerOperand();
1331061da546Spatrick
1332061da546Spatrick lldb::addr_t D = frame.ResolveValue(value_operand, module);
1333061da546Spatrick lldb::addr_t P = frame.ResolveValue(pointer_operand, module);
1334061da546Spatrick
1335061da546Spatrick if (D == LLDB_INVALID_ADDRESS) {
1336061da546Spatrick LLDB_LOGF(log, "StoreInst's value doesn't resolve to anything");
1337061da546Spatrick error.SetErrorToGenericError();
1338061da546Spatrick error.SetErrorString(bad_value_error);
1339061da546Spatrick return false;
1340061da546Spatrick }
1341061da546Spatrick
1342061da546Spatrick if (P == LLDB_INVALID_ADDRESS) {
1343061da546Spatrick LLDB_LOGF(log, "StoreInst's pointer doesn't resolve to anything");
1344061da546Spatrick error.SetErrorToGenericError();
1345061da546Spatrick error.SetErrorString(bad_value_error);
1346061da546Spatrick return false;
1347061da546Spatrick }
1348061da546Spatrick
1349061da546Spatrick lldb::addr_t R;
1350061da546Spatrick lldb_private::Status read_error;
1351061da546Spatrick execution_unit.ReadPointerFromMemory(&R, P, read_error);
1352061da546Spatrick
1353061da546Spatrick if (!read_error.Success()) {
1354061da546Spatrick LLDB_LOGF(log, "Couldn't read the address to be loaded for a LoadInst");
1355061da546Spatrick error.SetErrorToGenericError();
1356061da546Spatrick error.SetErrorString(memory_read_error);
1357061da546Spatrick return false;
1358061da546Spatrick }
1359061da546Spatrick
1360*f6aab3d8Srobert Type *target_ty = value_operand->getType();
1361061da546Spatrick size_t target_size = data_layout.getTypeStoreSize(target_ty);
1362061da546Spatrick lldb_private::DataBufferHeap buffer(target_size, 0);
1363061da546Spatrick
1364061da546Spatrick read_error.Clear();
1365061da546Spatrick execution_unit.ReadMemory(buffer.GetBytes(), D, buffer.GetByteSize(),
1366061da546Spatrick read_error);
1367061da546Spatrick if (!read_error.Success()) {
1368061da546Spatrick LLDB_LOGF(log, "Couldn't read from a region on behalf of a StoreInst");
1369061da546Spatrick error.SetErrorToGenericError();
1370061da546Spatrick error.SetErrorString(memory_read_error);
1371061da546Spatrick return false;
1372061da546Spatrick }
1373061da546Spatrick
1374061da546Spatrick lldb_private::Status write_error;
1375061da546Spatrick execution_unit.WriteMemory(R, buffer.GetBytes(), buffer.GetByteSize(),
1376061da546Spatrick write_error);
1377061da546Spatrick if (!write_error.Success()) {
1378061da546Spatrick LLDB_LOGF(log, "Couldn't write to a region on behalf of a StoreInst");
1379061da546Spatrick error.SetErrorToGenericError();
1380061da546Spatrick error.SetErrorString(memory_write_error);
1381061da546Spatrick return false;
1382061da546Spatrick }
1383061da546Spatrick
1384061da546Spatrick if (log) {
1385061da546Spatrick LLDB_LOGF(log, "Interpreted a StoreInst");
1386061da546Spatrick LLDB_LOGF(log, " D : 0x%" PRIx64, D);
1387061da546Spatrick LLDB_LOGF(log, " P : 0x%" PRIx64, P);
1388061da546Spatrick LLDB_LOGF(log, " R : 0x%" PRIx64, R);
1389061da546Spatrick }
1390061da546Spatrick } break;
1391061da546Spatrick case Instruction::Call: {
1392061da546Spatrick const CallInst *call_inst = cast<CallInst>(inst);
1393061da546Spatrick
1394061da546Spatrick if (CanIgnoreCall(call_inst))
1395061da546Spatrick break;
1396061da546Spatrick
1397061da546Spatrick // Get the return type
1398061da546Spatrick llvm::Type *returnType = call_inst->getType();
1399061da546Spatrick if (returnType == nullptr) {
1400061da546Spatrick error.SetErrorToGenericError();
1401061da546Spatrick error.SetErrorString("unable to access return type");
1402061da546Spatrick return false;
1403061da546Spatrick }
1404061da546Spatrick
1405061da546Spatrick // Work with void, integer and pointer return types
1406061da546Spatrick if (!returnType->isVoidTy() && !returnType->isIntegerTy() &&
1407061da546Spatrick !returnType->isPointerTy()) {
1408061da546Spatrick error.SetErrorToGenericError();
1409061da546Spatrick error.SetErrorString("return type is not supported");
1410061da546Spatrick return false;
1411061da546Spatrick }
1412061da546Spatrick
1413061da546Spatrick // Check we can actually get a thread
1414061da546Spatrick if (exe_ctx.GetThreadPtr() == nullptr) {
1415061da546Spatrick error.SetErrorToGenericError();
1416be691f3bSpatrick error.SetErrorString("unable to acquire thread");
1417061da546Spatrick return false;
1418061da546Spatrick }
1419061da546Spatrick
1420061da546Spatrick // Make sure we have a valid process
1421061da546Spatrick if (!exe_ctx.GetProcessPtr()) {
1422061da546Spatrick error.SetErrorToGenericError();
1423be691f3bSpatrick error.SetErrorString("unable to get the process");
1424061da546Spatrick return false;
1425061da546Spatrick }
1426061da546Spatrick
1427061da546Spatrick // Find the address of the callee function
1428061da546Spatrick lldb_private::Scalar I;
1429dda28197Spatrick const llvm::Value *val = call_inst->getCalledOperand();
1430061da546Spatrick
1431061da546Spatrick if (!frame.EvaluateValue(I, val, module)) {
1432061da546Spatrick error.SetErrorToGenericError();
1433061da546Spatrick error.SetErrorString("unable to get address of function");
1434061da546Spatrick return false;
1435061da546Spatrick }
1436061da546Spatrick lldb_private::Address funcAddr(I.ULongLong(LLDB_INVALID_ADDRESS));
1437061da546Spatrick
1438061da546Spatrick lldb_private::DiagnosticManager diagnostics;
1439061da546Spatrick lldb_private::EvaluateExpressionOptions options;
1440061da546Spatrick
1441*f6aab3d8Srobert llvm::FunctionType *prototype = call_inst->getFunctionType();
1442061da546Spatrick
1443061da546Spatrick // Find number of arguments
1444*f6aab3d8Srobert const int numArgs = call_inst->arg_size();
1445061da546Spatrick
1446061da546Spatrick // We work with a fixed array of 16 arguments which is our upper limit
1447061da546Spatrick static lldb_private::ABI::CallArgument rawArgs[16];
1448061da546Spatrick if (numArgs >= 16) {
1449061da546Spatrick error.SetErrorToGenericError();
1450be691f3bSpatrick error.SetErrorString("function takes too many arguments");
1451061da546Spatrick return false;
1452061da546Spatrick }
1453061da546Spatrick
1454061da546Spatrick // Push all function arguments to the argument list that will be passed
1455061da546Spatrick // to the call function thread plan
1456061da546Spatrick for (int i = 0; i < numArgs; i++) {
1457061da546Spatrick // Get details of this argument
1458061da546Spatrick llvm::Value *arg_op = call_inst->getArgOperand(i);
1459061da546Spatrick llvm::Type *arg_ty = arg_op->getType();
1460061da546Spatrick
1461061da546Spatrick // Ensure that this argument is an supported type
1462061da546Spatrick if (!arg_ty->isIntegerTy() && !arg_ty->isPointerTy()) {
1463061da546Spatrick error.SetErrorToGenericError();
1464061da546Spatrick error.SetErrorStringWithFormat("argument %d must be integer type", i);
1465061da546Spatrick return false;
1466061da546Spatrick }
1467061da546Spatrick
1468061da546Spatrick // Extract the arguments value
1469061da546Spatrick lldb_private::Scalar tmp_op = 0;
1470061da546Spatrick if (!frame.EvaluateValue(tmp_op, arg_op, module)) {
1471061da546Spatrick error.SetErrorToGenericError();
1472061da546Spatrick error.SetErrorStringWithFormat("unable to evaluate argument %d", i);
1473061da546Spatrick return false;
1474061da546Spatrick }
1475061da546Spatrick
1476061da546Spatrick // Check if this is a string literal or constant string pointer
1477061da546Spatrick if (arg_ty->isPointerTy()) {
1478061da546Spatrick lldb::addr_t addr = tmp_op.ULongLong();
1479061da546Spatrick size_t dataSize = 0;
1480061da546Spatrick
1481061da546Spatrick bool Success = execution_unit.GetAllocSize(addr, dataSize);
1482061da546Spatrick (void)Success;
1483061da546Spatrick assert(Success &&
1484061da546Spatrick "unable to locate host data for transfer to device");
1485061da546Spatrick // Create the required buffer
1486061da546Spatrick rawArgs[i].size = dataSize;
1487061da546Spatrick rawArgs[i].data_up.reset(new uint8_t[dataSize + 1]);
1488061da546Spatrick
1489061da546Spatrick // Read string from host memory
1490061da546Spatrick execution_unit.ReadMemory(rawArgs[i].data_up.get(), addr, dataSize,
1491061da546Spatrick error);
1492061da546Spatrick assert(!error.Fail() &&
1493061da546Spatrick "we have failed to read the string from memory");
1494061da546Spatrick
1495061da546Spatrick // Add null terminator
1496061da546Spatrick rawArgs[i].data_up[dataSize] = '\0';
1497061da546Spatrick rawArgs[i].type = lldb_private::ABI::CallArgument::HostPointer;
1498061da546Spatrick } else /* if ( arg_ty->isPointerTy() ) */
1499061da546Spatrick {
1500061da546Spatrick rawArgs[i].type = lldb_private::ABI::CallArgument::TargetValue;
1501061da546Spatrick // Get argument size in bytes
1502061da546Spatrick rawArgs[i].size = arg_ty->getIntegerBitWidth() / 8;
1503061da546Spatrick // Push value into argument list for thread plan
1504061da546Spatrick rawArgs[i].value = tmp_op.ULongLong();
1505061da546Spatrick }
1506061da546Spatrick }
1507061da546Spatrick
1508061da546Spatrick // Pack the arguments into an llvm::array
1509061da546Spatrick llvm::ArrayRef<lldb_private::ABI::CallArgument> args(rawArgs, numArgs);
1510061da546Spatrick
1511061da546Spatrick // Setup a thread plan to call the target function
1512061da546Spatrick lldb::ThreadPlanSP call_plan_sp(
1513061da546Spatrick new lldb_private::ThreadPlanCallFunctionUsingABI(
1514061da546Spatrick exe_ctx.GetThreadRef(), funcAddr, *prototype, *returnType, args,
1515061da546Spatrick options));
1516061da546Spatrick
1517061da546Spatrick // Check if the plan is valid
1518061da546Spatrick lldb_private::StreamString ss;
1519061da546Spatrick if (!call_plan_sp || !call_plan_sp->ValidatePlan(&ss)) {
1520061da546Spatrick error.SetErrorToGenericError();
1521061da546Spatrick error.SetErrorStringWithFormat(
1522061da546Spatrick "unable to make ThreadPlanCallFunctionUsingABI for 0x%llx",
1523061da546Spatrick I.ULongLong());
1524061da546Spatrick return false;
1525061da546Spatrick }
1526061da546Spatrick
1527061da546Spatrick exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
1528061da546Spatrick
1529061da546Spatrick // Execute the actual function call thread plan
1530061da546Spatrick lldb::ExpressionResults res = exe_ctx.GetProcessRef().RunThreadPlan(
1531061da546Spatrick exe_ctx, call_plan_sp, options, diagnostics);
1532061da546Spatrick
1533061da546Spatrick // Check that the thread plan completed successfully
1534061da546Spatrick if (res != lldb::ExpressionResults::eExpressionCompleted) {
1535061da546Spatrick error.SetErrorToGenericError();
1536be691f3bSpatrick error.SetErrorString("ThreadPlanCallFunctionUsingABI failed");
1537061da546Spatrick return false;
1538061da546Spatrick }
1539061da546Spatrick
1540061da546Spatrick exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
1541061da546Spatrick
1542061da546Spatrick // Void return type
1543061da546Spatrick if (returnType->isVoidTy()) {
1544061da546Spatrick // Cant assign to void types, so we leave the frame untouched
1545061da546Spatrick } else
1546061da546Spatrick // Integer or pointer return type
1547061da546Spatrick if (returnType->isIntegerTy() || returnType->isPointerTy()) {
1548061da546Spatrick // Get the encapsulated return value
1549061da546Spatrick lldb::ValueObjectSP retVal = call_plan_sp.get()->GetReturnValueObject();
1550061da546Spatrick
1551061da546Spatrick lldb_private::Scalar returnVal = -1;
1552061da546Spatrick lldb_private::ValueObject *vobj = retVal.get();
1553061da546Spatrick
1554061da546Spatrick // Check if the return value is valid
1555dda28197Spatrick if (vobj == nullptr || !retVal) {
1556061da546Spatrick error.SetErrorToGenericError();
1557be691f3bSpatrick error.SetErrorString("unable to get the return value");
1558061da546Spatrick return false;
1559061da546Spatrick }
1560061da546Spatrick
1561061da546Spatrick // Extract the return value as a integer
1562061da546Spatrick lldb_private::Value &value = vobj->GetValue();
1563061da546Spatrick returnVal = value.GetScalar();
1564061da546Spatrick
1565061da546Spatrick // Push the return value as the result
1566061da546Spatrick frame.AssignValue(inst, returnVal, module);
1567061da546Spatrick }
1568061da546Spatrick } break;
1569061da546Spatrick }
1570061da546Spatrick
1571061da546Spatrick ++frame.m_ii;
1572061da546Spatrick }
1573061da546Spatrick
1574061da546Spatrick if (num_insts >= 4096) {
1575061da546Spatrick error.SetErrorToGenericError();
1576061da546Spatrick error.SetErrorString(infinite_loop_error);
1577061da546Spatrick return false;
1578061da546Spatrick }
1579061da546Spatrick
1580061da546Spatrick return false;
1581061da546Spatrick }
1582