xref: /freebsd-src/contrib/llvm-project/lldb/source/Expression/IRInterpreter.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
15ffd83dbSDimitry Andric //===-- IRInterpreter.cpp -------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "lldb/Expression/IRInterpreter.h"
105f757f3fSDimitry Andric #include "lldb/Core/Debugger.h"
110b57cec5SDimitry Andric #include "lldb/Core/Module.h"
120b57cec5SDimitry Andric #include "lldb/Core/ModuleSpec.h"
130b57cec5SDimitry Andric #include "lldb/Core/ValueObject.h"
140b57cec5SDimitry Andric #include "lldb/Expression/DiagnosticManager.h"
150b57cec5SDimitry Andric #include "lldb/Expression/IRExecutionUnit.h"
160b57cec5SDimitry Andric #include "lldb/Expression/IRMemoryMap.h"
170b57cec5SDimitry Andric #include "lldb/Utility/ConstString.h"
180b57cec5SDimitry Andric #include "lldb/Utility/DataExtractor.h"
190b57cec5SDimitry Andric #include "lldb/Utility/Endian.h"
2081ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h"
210b57cec5SDimitry Andric #include "lldb/Utility/Log.h"
220b57cec5SDimitry Andric #include "lldb/Utility/Scalar.h"
230b57cec5SDimitry Andric #include "lldb/Utility/Status.h"
240b57cec5SDimitry Andric #include "lldb/Utility/StreamString.h"
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric #include "lldb/Target/ABI.h"
270b57cec5SDimitry Andric #include "lldb/Target/ExecutionContext.h"
280b57cec5SDimitry Andric #include "lldb/Target/Target.h"
290b57cec5SDimitry Andric #include "lldb/Target/Thread.h"
300b57cec5SDimitry Andric #include "lldb/Target/ThreadPlan.h"
310b57cec5SDimitry Andric #include "lldb/Target/ThreadPlanCallFunctionUsingABI.h"
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
340b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h"
350b57cec5SDimitry Andric #include "llvm/IR/Function.h"
360b57cec5SDimitry Andric #include "llvm/IR/Instructions.h"
370b57cec5SDimitry Andric #include "llvm/IR/Intrinsics.h"
380b57cec5SDimitry Andric #include "llvm/IR/LLVMContext.h"
390b57cec5SDimitry Andric #include "llvm/IR/Module.h"
400b57cec5SDimitry Andric #include "llvm/IR/Operator.h"
410b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric #include <map>
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric using namespace llvm;
4681ad6265SDimitry Andric using lldb_private::LLDBLog;
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric static std::string PrintValue(const Value *value, bool truncate = false) {
490b57cec5SDimitry Andric   std::string s;
500b57cec5SDimitry Andric   raw_string_ostream rso(s);
510b57cec5SDimitry Andric   value->print(rso);
520b57cec5SDimitry Andric   rso.flush();
530b57cec5SDimitry Andric   if (truncate)
540b57cec5SDimitry Andric     s.resize(s.length() - 1);
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric   size_t offset;
570b57cec5SDimitry Andric   while ((offset = s.find('\n')) != s.npos)
580b57cec5SDimitry Andric     s.erase(offset, 1);
590b57cec5SDimitry Andric   while (s[0] == ' ' || s[0] == '\t')
600b57cec5SDimitry Andric     s.erase(0, 1);
610b57cec5SDimitry Andric 
620b57cec5SDimitry Andric   return s;
630b57cec5SDimitry Andric }
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric static std::string PrintType(const Type *type, bool truncate = false) {
660b57cec5SDimitry Andric   std::string s;
670b57cec5SDimitry Andric   raw_string_ostream rso(s);
680b57cec5SDimitry Andric   type->print(rso);
690b57cec5SDimitry Andric   rso.flush();
700b57cec5SDimitry Andric   if (truncate)
710b57cec5SDimitry Andric     s.resize(s.length() - 1);
720b57cec5SDimitry Andric   return s;
730b57cec5SDimitry Andric }
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric static bool CanIgnoreCall(const CallInst *call) {
760b57cec5SDimitry Andric   const llvm::Function *called_function = call->getCalledFunction();
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric   if (!called_function)
790b57cec5SDimitry Andric     return false;
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric   if (called_function->isIntrinsic()) {
820b57cec5SDimitry Andric     switch (called_function->getIntrinsicID()) {
830b57cec5SDimitry Andric     default:
840b57cec5SDimitry Andric       break;
850b57cec5SDimitry Andric     case llvm::Intrinsic::dbg_declare:
860b57cec5SDimitry Andric     case llvm::Intrinsic::dbg_value:
870b57cec5SDimitry Andric       return true;
880b57cec5SDimitry Andric     }
890b57cec5SDimitry Andric   }
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric   return false;
920b57cec5SDimitry Andric }
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric class InterpreterStackFrame {
950b57cec5SDimitry Andric public:
960b57cec5SDimitry Andric   typedef std::map<const Value *, lldb::addr_t> ValueMap;
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric   ValueMap m_values;
990b57cec5SDimitry Andric   DataLayout &m_target_data;
1000b57cec5SDimitry Andric   lldb_private::IRExecutionUnit &m_execution_unit;
10181ad6265SDimitry Andric   const BasicBlock *m_bb = nullptr;
10281ad6265SDimitry Andric   const BasicBlock *m_prev_bb = nullptr;
1030b57cec5SDimitry Andric   BasicBlock::const_iterator m_ii;
1040b57cec5SDimitry Andric   BasicBlock::const_iterator m_ie;
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric   lldb::addr_t m_frame_process_address;
1070b57cec5SDimitry Andric   size_t m_frame_size;
1080b57cec5SDimitry Andric   lldb::addr_t m_stack_pointer;
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric   lldb::ByteOrder m_byte_order;
1110b57cec5SDimitry Andric   size_t m_addr_byte_size;
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric   InterpreterStackFrame(DataLayout &target_data,
1140b57cec5SDimitry Andric                         lldb_private::IRExecutionUnit &execution_unit,
1150b57cec5SDimitry Andric                         lldb::addr_t stack_frame_bottom,
1160b57cec5SDimitry Andric                         lldb::addr_t stack_frame_top)
11781ad6265SDimitry Andric       : m_target_data(target_data), m_execution_unit(execution_unit) {
1180b57cec5SDimitry Andric     m_byte_order = (target_data.isLittleEndian() ? lldb::eByteOrderLittle
1190b57cec5SDimitry Andric                                                  : lldb::eByteOrderBig);
1200b57cec5SDimitry Andric     m_addr_byte_size = (target_data.getPointerSize(0));
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric     m_frame_process_address = stack_frame_bottom;
1230b57cec5SDimitry Andric     m_frame_size = stack_frame_top - stack_frame_bottom;
1240b57cec5SDimitry Andric     m_stack_pointer = stack_frame_top;
1250b57cec5SDimitry Andric   }
1260b57cec5SDimitry Andric 
127fe6060f1SDimitry Andric   ~InterpreterStackFrame() = default;
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric   void Jump(const BasicBlock *bb) {
1300b57cec5SDimitry Andric     m_prev_bb = m_bb;
1310b57cec5SDimitry Andric     m_bb = bb;
1320b57cec5SDimitry Andric     m_ii = m_bb->begin();
1330b57cec5SDimitry Andric     m_ie = m_bb->end();
1340b57cec5SDimitry Andric   }
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric   std::string SummarizeValue(const Value *value) {
1370b57cec5SDimitry Andric     lldb_private::StreamString ss;
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric     ss.Printf("%s", PrintValue(value).c_str());
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric     ValueMap::iterator i = m_values.find(value);
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric     if (i != m_values.end()) {
1440b57cec5SDimitry Andric       lldb::addr_t addr = i->second;
1450b57cec5SDimitry Andric 
1460b57cec5SDimitry Andric       ss.Printf(" 0x%llx", (unsigned long long)addr);
1470b57cec5SDimitry Andric     }
1480b57cec5SDimitry Andric 
1495ffd83dbSDimitry Andric     return std::string(ss.GetString());
1500b57cec5SDimitry Andric   }
1510b57cec5SDimitry Andric 
1525ffd83dbSDimitry Andric   bool AssignToMatchType(lldb_private::Scalar &scalar, llvm::APInt value,
1530b57cec5SDimitry Andric                          Type *type) {
1540b57cec5SDimitry Andric     size_t type_size = m_target_data.getTypeStoreSize(type);
1550b57cec5SDimitry Andric 
1560b57cec5SDimitry Andric     if (type_size > 8)
1570b57cec5SDimitry Andric       return false;
1580b57cec5SDimitry Andric 
1590b57cec5SDimitry Andric     if (type_size != 1)
1600b57cec5SDimitry Andric       type_size = PowerOf2Ceil(type_size);
1610b57cec5SDimitry Andric 
1625ffd83dbSDimitry Andric     scalar = value.zextOrTrunc(type_size * 8);
1630b57cec5SDimitry Andric     return true;
1640b57cec5SDimitry Andric   }
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric   bool EvaluateValue(lldb_private::Scalar &scalar, const Value *value,
1670b57cec5SDimitry Andric                      Module &module) {
1680b57cec5SDimitry Andric     const Constant *constant = dyn_cast<Constant>(value);
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric     if (constant) {
171bdd1243dSDimitry Andric       if (constant->getValueID() == Value::ConstantFPVal) {
172bdd1243dSDimitry Andric         if (auto *cfp = dyn_cast<ConstantFP>(constant)) {
173bdd1243dSDimitry Andric           if (cfp->getType()->isDoubleTy())
174bdd1243dSDimitry Andric             scalar = cfp->getValueAPF().convertToDouble();
175bdd1243dSDimitry Andric           else if (cfp->getType()->isFloatTy())
176bdd1243dSDimitry Andric             scalar = cfp->getValueAPF().convertToFloat();
177bdd1243dSDimitry Andric           else
178bdd1243dSDimitry Andric             return false;
179bdd1243dSDimitry Andric           return true;
180bdd1243dSDimitry Andric         }
181bdd1243dSDimitry Andric         return false;
182bdd1243dSDimitry Andric       }
1830b57cec5SDimitry Andric       APInt value_apint;
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric       if (!ResolveConstantValue(value_apint, constant))
1860b57cec5SDimitry Andric         return false;
1870b57cec5SDimitry Andric 
1885ffd83dbSDimitry Andric       return AssignToMatchType(scalar, value_apint, value->getType());
1895ffd83dbSDimitry Andric     }
1905ffd83dbSDimitry Andric 
1910b57cec5SDimitry Andric     lldb::addr_t process_address = ResolveValue(value, module);
1920b57cec5SDimitry Andric     size_t value_size = m_target_data.getTypeStoreSize(value->getType());
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric     lldb_private::DataExtractor value_extractor;
1950b57cec5SDimitry Andric     lldb_private::Status extract_error;
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric     m_execution_unit.GetMemoryData(value_extractor, process_address,
1980b57cec5SDimitry Andric                                    value_size, extract_error);
1990b57cec5SDimitry Andric 
2000b57cec5SDimitry Andric     if (!extract_error.Success())
2010b57cec5SDimitry Andric       return false;
2020b57cec5SDimitry Andric 
2030b57cec5SDimitry Andric     lldb::offset_t offset = 0;
2040b57cec5SDimitry Andric     if (value_size <= 8) {
205bdd1243dSDimitry Andric       Type *ty = value->getType();
206bdd1243dSDimitry Andric       if (ty->isDoubleTy()) {
207bdd1243dSDimitry Andric         scalar = value_extractor.GetDouble(&offset);
208bdd1243dSDimitry Andric         return true;
209bdd1243dSDimitry Andric       } else if (ty->isFloatTy()) {
210bdd1243dSDimitry Andric         scalar = value_extractor.GetFloat(&offset);
211bdd1243dSDimitry Andric         return true;
212bdd1243dSDimitry Andric       } else {
2130b57cec5SDimitry Andric         uint64_t u64value = value_extractor.GetMaxU64(&offset, value_size);
2145ffd83dbSDimitry Andric         return AssignToMatchType(scalar, llvm::APInt(64, u64value),
2155ffd83dbSDimitry Andric                                  value->getType());
2160b57cec5SDimitry Andric       }
217bdd1243dSDimitry Andric     }
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric     return false;
2200b57cec5SDimitry Andric   }
2210b57cec5SDimitry Andric 
2225ffd83dbSDimitry Andric   bool AssignValue(const Value *value, lldb_private::Scalar scalar,
2230b57cec5SDimitry Andric                    Module &module) {
2240b57cec5SDimitry Andric     lldb::addr_t process_address = ResolveValue(value, module);
2250b57cec5SDimitry Andric 
2260b57cec5SDimitry Andric     if (process_address == LLDB_INVALID_ADDRESS)
2270b57cec5SDimitry Andric       return false;
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric     lldb_private::Scalar cast_scalar;
230bdd1243dSDimitry Andric     Type *vty = value->getType();
231bdd1243dSDimitry Andric     if (vty->isFloatTy() || vty->isDoubleTy()) {
232bdd1243dSDimitry Andric       cast_scalar = scalar;
233bdd1243dSDimitry Andric     } else {
2345ffd83dbSDimitry Andric       scalar.MakeUnsigned();
2355ffd83dbSDimitry Andric       if (!AssignToMatchType(cast_scalar, scalar.UInt128(llvm::APInt()),
2365ffd83dbSDimitry Andric                              value->getType()))
2370b57cec5SDimitry Andric         return false;
238bdd1243dSDimitry Andric     }
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric     size_t value_byte_size = m_target_data.getTypeStoreSize(value->getType());
2410b57cec5SDimitry Andric 
2420b57cec5SDimitry Andric     lldb_private::DataBufferHeap buf(value_byte_size, 0);
2430b57cec5SDimitry Andric 
2440b57cec5SDimitry Andric     lldb_private::Status get_data_error;
2450b57cec5SDimitry Andric 
2460b57cec5SDimitry Andric     if (!cast_scalar.GetAsMemoryData(buf.GetBytes(), buf.GetByteSize(),
2470b57cec5SDimitry Andric                                      m_byte_order, get_data_error))
2480b57cec5SDimitry Andric       return false;
2490b57cec5SDimitry Andric 
2500b57cec5SDimitry Andric     lldb_private::Status write_error;
2510b57cec5SDimitry Andric 
2520b57cec5SDimitry Andric     m_execution_unit.WriteMemory(process_address, buf.GetBytes(),
2530b57cec5SDimitry Andric                                  buf.GetByteSize(), write_error);
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric     return write_error.Success();
2560b57cec5SDimitry Andric   }
2570b57cec5SDimitry Andric 
2580b57cec5SDimitry Andric   bool ResolveConstantValue(APInt &value, const Constant *constant) {
2590b57cec5SDimitry Andric     switch (constant->getValueID()) {
2600b57cec5SDimitry Andric     default:
2610b57cec5SDimitry Andric       break;
2620b57cec5SDimitry Andric     case Value::FunctionVal:
2630b57cec5SDimitry Andric       if (const Function *constant_func = dyn_cast<Function>(constant)) {
2640b57cec5SDimitry Andric         lldb_private::ConstString name(constant_func->getName());
2650b57cec5SDimitry Andric         bool missing_weak = false;
2660b57cec5SDimitry Andric         lldb::addr_t addr = m_execution_unit.FindSymbol(name, missing_weak);
267*0fca6ea1SDimitry Andric         if (addr == LLDB_INVALID_ADDRESS)
2680b57cec5SDimitry Andric           return false;
2690b57cec5SDimitry Andric         value = APInt(m_target_data.getPointerSizeInBits(), addr);
2700b57cec5SDimitry Andric         return true;
2710b57cec5SDimitry Andric       }
2720b57cec5SDimitry Andric       break;
2730b57cec5SDimitry Andric     case Value::ConstantIntVal:
2740b57cec5SDimitry Andric       if (const ConstantInt *constant_int = dyn_cast<ConstantInt>(constant)) {
2750b57cec5SDimitry Andric         value = constant_int->getValue();
2760b57cec5SDimitry Andric         return true;
2770b57cec5SDimitry Andric       }
2780b57cec5SDimitry Andric       break;
2790b57cec5SDimitry Andric     case Value::ConstantFPVal:
2800b57cec5SDimitry Andric       if (const ConstantFP *constant_fp = dyn_cast<ConstantFP>(constant)) {
2810b57cec5SDimitry Andric         value = constant_fp->getValueAPF().bitcastToAPInt();
2820b57cec5SDimitry Andric         return true;
2830b57cec5SDimitry Andric       }
2840b57cec5SDimitry Andric       break;
2850b57cec5SDimitry Andric     case Value::ConstantExprVal:
2860b57cec5SDimitry Andric       if (const ConstantExpr *constant_expr =
2870b57cec5SDimitry Andric               dyn_cast<ConstantExpr>(constant)) {
2880b57cec5SDimitry Andric         switch (constant_expr->getOpcode()) {
2890b57cec5SDimitry Andric         default:
2900b57cec5SDimitry Andric           return false;
2910b57cec5SDimitry Andric         case Instruction::IntToPtr:
2920b57cec5SDimitry Andric         case Instruction::PtrToInt:
2930b57cec5SDimitry Andric         case Instruction::BitCast:
2940b57cec5SDimitry Andric           return ResolveConstantValue(value, constant_expr->getOperand(0));
2950b57cec5SDimitry Andric         case Instruction::GetElementPtr: {
2960b57cec5SDimitry Andric           ConstantExpr::const_op_iterator op_cursor = constant_expr->op_begin();
2970b57cec5SDimitry Andric           ConstantExpr::const_op_iterator op_end = constant_expr->op_end();
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric           Constant *base = dyn_cast<Constant>(*op_cursor);
3000b57cec5SDimitry Andric 
3010b57cec5SDimitry Andric           if (!base)
3020b57cec5SDimitry Andric             return false;
3030b57cec5SDimitry Andric 
3040b57cec5SDimitry Andric           if (!ResolveConstantValue(value, base))
3050b57cec5SDimitry Andric             return false;
3060b57cec5SDimitry Andric 
3070b57cec5SDimitry Andric           op_cursor++;
3080b57cec5SDimitry Andric 
3090b57cec5SDimitry Andric           if (op_cursor == op_end)
3100b57cec5SDimitry Andric             return true; // no offset to apply!
3110b57cec5SDimitry Andric 
3120b57cec5SDimitry Andric           SmallVector<Value *, 8> indices(op_cursor, op_end);
3130b57cec5SDimitry Andric           Type *src_elem_ty =
3140b57cec5SDimitry Andric               cast<GEPOperator>(constant_expr)->getSourceElementType();
31581ad6265SDimitry Andric 
31681ad6265SDimitry Andric           // DataLayout::getIndexedOffsetInType assumes the indices are
31781ad6265SDimitry Andric           // instances of ConstantInt.
3180b57cec5SDimitry Andric           uint64_t offset =
3190b57cec5SDimitry Andric               m_target_data.getIndexedOffsetInType(src_elem_ty, indices);
3200b57cec5SDimitry Andric 
3210b57cec5SDimitry Andric           const bool is_signed = true;
3220b57cec5SDimitry Andric           value += APInt(value.getBitWidth(), offset, is_signed);
3230b57cec5SDimitry Andric 
3240b57cec5SDimitry Andric           return true;
3250b57cec5SDimitry Andric         }
3260b57cec5SDimitry Andric         }
3270b57cec5SDimitry Andric       }
3280b57cec5SDimitry Andric       break;
3290b57cec5SDimitry Andric     case Value::ConstantPointerNullVal:
3300b57cec5SDimitry Andric       if (isa<ConstantPointerNull>(constant)) {
3310b57cec5SDimitry Andric         value = APInt(m_target_data.getPointerSizeInBits(), 0);
3320b57cec5SDimitry Andric         return true;
3330b57cec5SDimitry Andric       }
3340b57cec5SDimitry Andric       break;
3350b57cec5SDimitry Andric     }
3360b57cec5SDimitry Andric     return false;
3370b57cec5SDimitry Andric   }
3380b57cec5SDimitry Andric 
3390b57cec5SDimitry Andric   bool MakeArgument(const Argument *value, uint64_t address) {
3400b57cec5SDimitry Andric     lldb::addr_t data_address = Malloc(value->getType());
3410b57cec5SDimitry Andric 
3420b57cec5SDimitry Andric     if (data_address == LLDB_INVALID_ADDRESS)
3430b57cec5SDimitry Andric       return false;
3440b57cec5SDimitry Andric 
3450b57cec5SDimitry Andric     lldb_private::Status write_error;
3460b57cec5SDimitry Andric 
3470b57cec5SDimitry Andric     m_execution_unit.WritePointerToMemory(data_address, address, write_error);
3480b57cec5SDimitry Andric 
3490b57cec5SDimitry Andric     if (!write_error.Success()) {
3500b57cec5SDimitry Andric       lldb_private::Status free_error;
3510b57cec5SDimitry Andric       m_execution_unit.Free(data_address, free_error);
3520b57cec5SDimitry Andric       return false;
3530b57cec5SDimitry Andric     }
3540b57cec5SDimitry Andric 
3550b57cec5SDimitry Andric     m_values[value] = data_address;
3560b57cec5SDimitry Andric 
35781ad6265SDimitry Andric     lldb_private::Log *log(GetLog(LLDBLog::Expressions));
3580b57cec5SDimitry Andric 
3590b57cec5SDimitry Andric     if (log) {
3609dba64beSDimitry Andric       LLDB_LOGF(log, "Made an allocation for argument %s",
3610b57cec5SDimitry Andric                 PrintValue(value).c_str());
3629dba64beSDimitry Andric       LLDB_LOGF(log, "  Data region    : %llx", (unsigned long long)address);
3639dba64beSDimitry Andric       LLDB_LOGF(log, "  Ref region     : %llx",
3649dba64beSDimitry Andric                 (unsigned long long)data_address);
3650b57cec5SDimitry Andric     }
3660b57cec5SDimitry Andric 
3670b57cec5SDimitry Andric     return true;
3680b57cec5SDimitry Andric   }
3690b57cec5SDimitry Andric 
3700b57cec5SDimitry Andric   bool ResolveConstant(lldb::addr_t process_address, const Constant *constant) {
3710b57cec5SDimitry Andric     APInt resolved_value;
3720b57cec5SDimitry Andric 
3730b57cec5SDimitry Andric     if (!ResolveConstantValue(resolved_value, constant))
3740b57cec5SDimitry Andric       return false;
3750b57cec5SDimitry Andric 
3760b57cec5SDimitry Andric     size_t constant_size = m_target_data.getTypeStoreSize(constant->getType());
3770b57cec5SDimitry Andric     lldb_private::DataBufferHeap buf(constant_size, 0);
3780b57cec5SDimitry Andric 
3790b57cec5SDimitry Andric     lldb_private::Status get_data_error;
3800b57cec5SDimitry Andric 
3810b57cec5SDimitry Andric     lldb_private::Scalar resolved_scalar(
3820b57cec5SDimitry Andric         resolved_value.zextOrTrunc(llvm::NextPowerOf2(constant_size) * 8));
3830b57cec5SDimitry Andric     if (!resolved_scalar.GetAsMemoryData(buf.GetBytes(), buf.GetByteSize(),
3840b57cec5SDimitry Andric                                          m_byte_order, get_data_error))
3850b57cec5SDimitry Andric       return false;
3860b57cec5SDimitry Andric 
3870b57cec5SDimitry Andric     lldb_private::Status write_error;
3880b57cec5SDimitry Andric 
3890b57cec5SDimitry Andric     m_execution_unit.WriteMemory(process_address, buf.GetBytes(),
3900b57cec5SDimitry Andric                                  buf.GetByteSize(), write_error);
3910b57cec5SDimitry Andric 
3920b57cec5SDimitry Andric     return write_error.Success();
3930b57cec5SDimitry Andric   }
3940b57cec5SDimitry Andric 
3950b57cec5SDimitry Andric   lldb::addr_t Malloc(size_t size, uint8_t byte_alignment) {
3960b57cec5SDimitry Andric     lldb::addr_t ret = m_stack_pointer;
3970b57cec5SDimitry Andric 
3980b57cec5SDimitry Andric     ret -= size;
3990b57cec5SDimitry Andric     ret -= (ret % byte_alignment);
4000b57cec5SDimitry Andric 
4010b57cec5SDimitry Andric     if (ret < m_frame_process_address)
4020b57cec5SDimitry Andric       return LLDB_INVALID_ADDRESS;
4030b57cec5SDimitry Andric 
4040b57cec5SDimitry Andric     m_stack_pointer = ret;
4050b57cec5SDimitry Andric     return ret;
4060b57cec5SDimitry Andric   }
4070b57cec5SDimitry Andric 
4080b57cec5SDimitry Andric   lldb::addr_t Malloc(llvm::Type *type) {
4090b57cec5SDimitry Andric     lldb_private::Status alloc_error;
4100b57cec5SDimitry Andric 
4110b57cec5SDimitry Andric     return Malloc(m_target_data.getTypeAllocSize(type),
412bdd1243dSDimitry Andric                   m_target_data.getPrefTypeAlign(type).value());
4130b57cec5SDimitry Andric   }
4140b57cec5SDimitry Andric 
4150b57cec5SDimitry Andric   std::string PrintData(lldb::addr_t addr, llvm::Type *type) {
4160b57cec5SDimitry Andric     size_t length = m_target_data.getTypeStoreSize(type);
4170b57cec5SDimitry Andric 
4180b57cec5SDimitry Andric     lldb_private::DataBufferHeap buf(length, 0);
4190b57cec5SDimitry Andric 
4200b57cec5SDimitry Andric     lldb_private::Status read_error;
4210b57cec5SDimitry Andric 
4220b57cec5SDimitry Andric     m_execution_unit.ReadMemory(buf.GetBytes(), addr, length, read_error);
4230b57cec5SDimitry Andric 
4240b57cec5SDimitry Andric     if (!read_error.Success())
4250b57cec5SDimitry Andric       return std::string("<couldn't read data>");
4260b57cec5SDimitry Andric 
4270b57cec5SDimitry Andric     lldb_private::StreamString ss;
4280b57cec5SDimitry Andric 
4290b57cec5SDimitry Andric     for (size_t i = 0; i < length; i++) {
4300b57cec5SDimitry Andric       if ((!(i & 0xf)) && i)
4310b57cec5SDimitry Andric         ss.Printf("%02hhx - ", buf.GetBytes()[i]);
4320b57cec5SDimitry Andric       else
4330b57cec5SDimitry Andric         ss.Printf("%02hhx ", buf.GetBytes()[i]);
4340b57cec5SDimitry Andric     }
4350b57cec5SDimitry Andric 
4365ffd83dbSDimitry Andric     return std::string(ss.GetString());
4370b57cec5SDimitry Andric   }
4380b57cec5SDimitry Andric 
4390b57cec5SDimitry Andric   lldb::addr_t ResolveValue(const Value *value, Module &module) {
4400b57cec5SDimitry Andric     ValueMap::iterator i = m_values.find(value);
4410b57cec5SDimitry Andric 
4420b57cec5SDimitry Andric     if (i != m_values.end())
4430b57cec5SDimitry Andric       return i->second;
4440b57cec5SDimitry Andric 
4450b57cec5SDimitry Andric     // Fall back and allocate space [allocation type Alloca]
4460b57cec5SDimitry Andric 
4470b57cec5SDimitry Andric     lldb::addr_t data_address = Malloc(value->getType());
4480b57cec5SDimitry Andric 
4490b57cec5SDimitry Andric     if (const Constant *constant = dyn_cast<Constant>(value)) {
4500b57cec5SDimitry Andric       if (!ResolveConstant(data_address, constant)) {
4510b57cec5SDimitry Andric         lldb_private::Status free_error;
4520b57cec5SDimitry Andric         m_execution_unit.Free(data_address, free_error);
4530b57cec5SDimitry Andric         return LLDB_INVALID_ADDRESS;
4540b57cec5SDimitry Andric       }
4550b57cec5SDimitry Andric     }
4560b57cec5SDimitry Andric 
4570b57cec5SDimitry Andric     m_values[value] = data_address;
4580b57cec5SDimitry Andric     return data_address;
4590b57cec5SDimitry Andric   }
4600b57cec5SDimitry Andric };
4610b57cec5SDimitry Andric 
4620b57cec5SDimitry Andric static const char *unsupported_opcode_error =
4630b57cec5SDimitry Andric     "Interpreter doesn't handle one of the expression's opcodes";
4640b57cec5SDimitry Andric static const char *unsupported_operand_error =
4650b57cec5SDimitry Andric     "Interpreter doesn't handle one of the expression's operands";
4660b57cec5SDimitry Andric static const char *interpreter_internal_error =
4670b57cec5SDimitry Andric     "Interpreter encountered an internal error";
4685f757f3fSDimitry Andric static const char *interrupt_error =
4695f757f3fSDimitry Andric     "Interrupted while interpreting expression";
4700b57cec5SDimitry Andric static const char *bad_value_error =
4710b57cec5SDimitry Andric     "Interpreter couldn't resolve a value during execution";
4720b57cec5SDimitry Andric static const char *memory_allocation_error =
4730b57cec5SDimitry Andric     "Interpreter couldn't allocate memory";
4740b57cec5SDimitry Andric static const char *memory_write_error = "Interpreter couldn't write to memory";
4750b57cec5SDimitry Andric static const char *memory_read_error = "Interpreter couldn't read from memory";
4765f757f3fSDimitry Andric static const char *timeout_error =
4775f757f3fSDimitry Andric     "Reached timeout while interpreting expression";
4780b57cec5SDimitry Andric static const char *too_many_functions_error =
4790b57cec5SDimitry Andric     "Interpreter doesn't handle modules with multiple function bodies.";
4800b57cec5SDimitry Andric 
4810b57cec5SDimitry Andric static bool CanResolveConstant(llvm::Constant *constant) {
4820b57cec5SDimitry Andric   switch (constant->getValueID()) {
4830b57cec5SDimitry Andric   default:
4840b57cec5SDimitry Andric     return false;
4850b57cec5SDimitry Andric   case Value::ConstantIntVal:
4860b57cec5SDimitry Andric   case Value::ConstantFPVal:
4870b57cec5SDimitry Andric   case Value::FunctionVal:
4880b57cec5SDimitry Andric     return true;
4890b57cec5SDimitry Andric   case Value::ConstantExprVal:
4900b57cec5SDimitry Andric     if (const ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(constant)) {
4910b57cec5SDimitry Andric       switch (constant_expr->getOpcode()) {
4920b57cec5SDimitry Andric       default:
4930b57cec5SDimitry Andric         return false;
4940b57cec5SDimitry Andric       case Instruction::IntToPtr:
4950b57cec5SDimitry Andric       case Instruction::PtrToInt:
4960b57cec5SDimitry Andric       case Instruction::BitCast:
4970b57cec5SDimitry Andric         return CanResolveConstant(constant_expr->getOperand(0));
4980b57cec5SDimitry Andric       case Instruction::GetElementPtr: {
49981ad6265SDimitry Andric         // Check that the base can be constant-resolved.
5000b57cec5SDimitry Andric         ConstantExpr::const_op_iterator op_cursor = constant_expr->op_begin();
5010b57cec5SDimitry Andric         Constant *base = dyn_cast<Constant>(*op_cursor);
50281ad6265SDimitry Andric         if (!base || !CanResolveConstant(base))
5030b57cec5SDimitry Andric           return false;
5040b57cec5SDimitry Andric 
50581ad6265SDimitry Andric         // Check that all other operands are just ConstantInt.
50681ad6265SDimitry Andric         for (Value *op : make_range(constant_expr->op_begin() + 1,
50781ad6265SDimitry Andric                                     constant_expr->op_end())) {
50881ad6265SDimitry Andric           ConstantInt *constant_int = dyn_cast<ConstantInt>(op);
50981ad6265SDimitry Andric           if (!constant_int)
51081ad6265SDimitry Andric             return false;
51181ad6265SDimitry Andric         }
51281ad6265SDimitry Andric         return true;
5130b57cec5SDimitry Andric       }
5140b57cec5SDimitry Andric       }
5150b57cec5SDimitry Andric     } else {
5160b57cec5SDimitry Andric       return false;
5170b57cec5SDimitry Andric     }
5180b57cec5SDimitry Andric   case Value::ConstantPointerNullVal:
5190b57cec5SDimitry Andric     return true;
5200b57cec5SDimitry Andric   }
5210b57cec5SDimitry Andric }
5220b57cec5SDimitry Andric 
5230b57cec5SDimitry Andric bool IRInterpreter::CanInterpret(llvm::Module &module, llvm::Function &function,
5240b57cec5SDimitry Andric                                  lldb_private::Status &error,
5250b57cec5SDimitry Andric                                  const bool support_function_calls) {
52681ad6265SDimitry Andric   lldb_private::Log *log(GetLog(LLDBLog::Expressions));
5270b57cec5SDimitry Andric 
5280b57cec5SDimitry Andric   bool saw_function_with_body = false;
529480093f4SDimitry Andric   for (Function &f : module) {
530480093f4SDimitry Andric     if (f.begin() != f.end()) {
5310b57cec5SDimitry Andric       if (saw_function_with_body) {
5329dba64beSDimitry Andric         LLDB_LOGF(log, "More than one function in the module has a body");
5330b57cec5SDimitry Andric         error.SetErrorToGenericError();
5340b57cec5SDimitry Andric         error.SetErrorString(too_many_functions_error);
5350b57cec5SDimitry Andric         return false;
5360b57cec5SDimitry Andric       }
5370b57cec5SDimitry Andric       saw_function_with_body = true;
538bdd1243dSDimitry Andric       LLDB_LOGF(log, "Saw function with body: %s", f.getName().str().c_str());
5390b57cec5SDimitry Andric     }
5400b57cec5SDimitry Andric   }
5410b57cec5SDimitry Andric 
542480093f4SDimitry Andric   for (BasicBlock &bb : function) {
543480093f4SDimitry Andric     for (Instruction &ii : bb) {
544480093f4SDimitry Andric       switch (ii.getOpcode()) {
5450b57cec5SDimitry Andric       default: {
546480093f4SDimitry Andric         LLDB_LOGF(log, "Unsupported instruction: %s", PrintValue(&ii).c_str());
5470b57cec5SDimitry Andric         error.SetErrorToGenericError();
5480b57cec5SDimitry Andric         error.SetErrorString(unsupported_opcode_error);
5490b57cec5SDimitry Andric         return false;
5500b57cec5SDimitry Andric       }
5510b57cec5SDimitry Andric       case Instruction::Add:
5520b57cec5SDimitry Andric       case Instruction::Alloca:
5530b57cec5SDimitry Andric       case Instruction::BitCast:
5540b57cec5SDimitry Andric       case Instruction::Br:
5550b57cec5SDimitry Andric       case Instruction::PHI:
5560b57cec5SDimitry Andric         break;
5570b57cec5SDimitry Andric       case Instruction::Call: {
558480093f4SDimitry Andric         CallInst *call_inst = dyn_cast<CallInst>(&ii);
5590b57cec5SDimitry Andric 
5600b57cec5SDimitry Andric         if (!call_inst) {
5610b57cec5SDimitry Andric           error.SetErrorToGenericError();
5620b57cec5SDimitry Andric           error.SetErrorString(interpreter_internal_error);
5630b57cec5SDimitry Andric           return false;
5640b57cec5SDimitry Andric         }
5650b57cec5SDimitry Andric 
5660b57cec5SDimitry Andric         if (!CanIgnoreCall(call_inst) && !support_function_calls) {
5679dba64beSDimitry Andric           LLDB_LOGF(log, "Unsupported instruction: %s",
568480093f4SDimitry Andric                     PrintValue(&ii).c_str());
5690b57cec5SDimitry Andric           error.SetErrorToGenericError();
5700b57cec5SDimitry Andric           error.SetErrorString(unsupported_opcode_error);
5710b57cec5SDimitry Andric           return false;
5720b57cec5SDimitry Andric         }
5730b57cec5SDimitry Andric       } break;
5740b57cec5SDimitry Andric       case Instruction::GetElementPtr:
5750b57cec5SDimitry Andric         break;
576bdd1243dSDimitry Andric       case Instruction::FCmp:
5770b57cec5SDimitry Andric       case Instruction::ICmp: {
578bdd1243dSDimitry Andric         CmpInst *cmp_inst = dyn_cast<CmpInst>(&ii);
5790b57cec5SDimitry Andric 
580bdd1243dSDimitry Andric         if (!cmp_inst) {
5810b57cec5SDimitry Andric           error.SetErrorToGenericError();
5820b57cec5SDimitry Andric           error.SetErrorString(interpreter_internal_error);
5830b57cec5SDimitry Andric           return false;
5840b57cec5SDimitry Andric         }
5850b57cec5SDimitry Andric 
586bdd1243dSDimitry Andric         switch (cmp_inst->getPredicate()) {
5870b57cec5SDimitry Andric         default: {
5889dba64beSDimitry Andric           LLDB_LOGF(log, "Unsupported ICmp predicate: %s",
589480093f4SDimitry Andric                     PrintValue(&ii).c_str());
5900b57cec5SDimitry Andric 
5910b57cec5SDimitry Andric           error.SetErrorToGenericError();
5920b57cec5SDimitry Andric           error.SetErrorString(unsupported_opcode_error);
5930b57cec5SDimitry Andric           return false;
5940b57cec5SDimitry Andric         }
595bdd1243dSDimitry Andric         case CmpInst::FCMP_OEQ:
5960b57cec5SDimitry Andric         case CmpInst::ICMP_EQ:
597bdd1243dSDimitry Andric         case CmpInst::FCMP_UNE:
5980b57cec5SDimitry Andric         case CmpInst::ICMP_NE:
599bdd1243dSDimitry Andric         case CmpInst::FCMP_OGT:
6000b57cec5SDimitry Andric         case CmpInst::ICMP_UGT:
601bdd1243dSDimitry Andric         case CmpInst::FCMP_OGE:
6020b57cec5SDimitry Andric         case CmpInst::ICMP_UGE:
603bdd1243dSDimitry Andric         case CmpInst::FCMP_OLT:
6040b57cec5SDimitry Andric         case CmpInst::ICMP_ULT:
605bdd1243dSDimitry Andric         case CmpInst::FCMP_OLE:
6060b57cec5SDimitry Andric         case CmpInst::ICMP_ULE:
6070b57cec5SDimitry Andric         case CmpInst::ICMP_SGT:
6080b57cec5SDimitry Andric         case CmpInst::ICMP_SGE:
6090b57cec5SDimitry Andric         case CmpInst::ICMP_SLT:
6100b57cec5SDimitry Andric         case CmpInst::ICMP_SLE:
6110b57cec5SDimitry Andric           break;
6120b57cec5SDimitry Andric         }
6130b57cec5SDimitry Andric       } break;
6140b57cec5SDimitry Andric       case Instruction::And:
6150b57cec5SDimitry Andric       case Instruction::AShr:
6160b57cec5SDimitry Andric       case Instruction::IntToPtr:
6170b57cec5SDimitry Andric       case Instruction::PtrToInt:
6180b57cec5SDimitry Andric       case Instruction::Load:
6190b57cec5SDimitry Andric       case Instruction::LShr:
6200b57cec5SDimitry Andric       case Instruction::Mul:
6210b57cec5SDimitry Andric       case Instruction::Or:
6220b57cec5SDimitry Andric       case Instruction::Ret:
6230b57cec5SDimitry Andric       case Instruction::SDiv:
6240b57cec5SDimitry Andric       case Instruction::SExt:
6250b57cec5SDimitry Andric       case Instruction::Shl:
6260b57cec5SDimitry Andric       case Instruction::SRem:
6270b57cec5SDimitry Andric       case Instruction::Store:
6280b57cec5SDimitry Andric       case Instruction::Sub:
6290b57cec5SDimitry Andric       case Instruction::Trunc:
6300b57cec5SDimitry Andric       case Instruction::UDiv:
6310b57cec5SDimitry Andric       case Instruction::URem:
6320b57cec5SDimitry Andric       case Instruction::Xor:
6330b57cec5SDimitry Andric       case Instruction::ZExt:
6340b57cec5SDimitry Andric         break;
635bdd1243dSDimitry Andric       case Instruction::FAdd:
636bdd1243dSDimitry Andric       case Instruction::FSub:
637bdd1243dSDimitry Andric       case Instruction::FMul:
638bdd1243dSDimitry Andric       case Instruction::FDiv:
639bdd1243dSDimitry Andric         break;
6400b57cec5SDimitry Andric       }
6410b57cec5SDimitry Andric 
642480093f4SDimitry Andric       for (unsigned oi = 0, oe = ii.getNumOperands(); oi != oe; ++oi) {
643480093f4SDimitry Andric         Value *operand = ii.getOperand(oi);
6440b57cec5SDimitry Andric         Type *operand_type = operand->getType();
6450b57cec5SDimitry Andric 
6460b57cec5SDimitry Andric         switch (operand_type->getTypeID()) {
6470b57cec5SDimitry Andric         default:
6480b57cec5SDimitry Andric           break;
6495ffd83dbSDimitry Andric         case Type::FixedVectorTyID:
6505ffd83dbSDimitry Andric         case Type::ScalableVectorTyID: {
6519dba64beSDimitry Andric           LLDB_LOGF(log, "Unsupported operand type: %s",
6520b57cec5SDimitry Andric                     PrintType(operand_type).c_str());
6530b57cec5SDimitry Andric           error.SetErrorString(unsupported_operand_error);
6540b57cec5SDimitry Andric           return false;
6550b57cec5SDimitry Andric         }
6560b57cec5SDimitry Andric         }
6570b57cec5SDimitry Andric 
6580b57cec5SDimitry Andric         // The IR interpreter currently doesn't know about
6590b57cec5SDimitry Andric         // 128-bit integers. As they're not that frequent,
6600b57cec5SDimitry Andric         // we can just fall back to the JIT rather than
6610b57cec5SDimitry Andric         // choking.
6620b57cec5SDimitry Andric         if (operand_type->getPrimitiveSizeInBits() > 64) {
6639dba64beSDimitry Andric           LLDB_LOGF(log, "Unsupported operand type: %s",
6640b57cec5SDimitry Andric                     PrintType(operand_type).c_str());
6650b57cec5SDimitry Andric           error.SetErrorString(unsupported_operand_error);
6660b57cec5SDimitry Andric           return false;
6670b57cec5SDimitry Andric         }
6680b57cec5SDimitry Andric 
6690b57cec5SDimitry Andric         if (Constant *constant = llvm::dyn_cast<Constant>(operand)) {
6700b57cec5SDimitry Andric           if (!CanResolveConstant(constant)) {
6719dba64beSDimitry Andric             LLDB_LOGF(log, "Unsupported constant: %s",
6720b57cec5SDimitry Andric                       PrintValue(constant).c_str());
6730b57cec5SDimitry Andric             error.SetErrorString(unsupported_operand_error);
6740b57cec5SDimitry Andric             return false;
6750b57cec5SDimitry Andric           }
6760b57cec5SDimitry Andric         }
6770b57cec5SDimitry Andric       }
6780b57cec5SDimitry Andric     }
6790b57cec5SDimitry Andric   }
6800b57cec5SDimitry Andric 
6810b57cec5SDimitry Andric   return true;
6820b57cec5SDimitry Andric }
6830b57cec5SDimitry Andric 
6840b57cec5SDimitry Andric bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function,
6850b57cec5SDimitry Andric                               llvm::ArrayRef<lldb::addr_t> args,
6860b57cec5SDimitry Andric                               lldb_private::IRExecutionUnit &execution_unit,
6870b57cec5SDimitry Andric                               lldb_private::Status &error,
6880b57cec5SDimitry Andric                               lldb::addr_t stack_frame_bottom,
6890b57cec5SDimitry Andric                               lldb::addr_t stack_frame_top,
6905f757f3fSDimitry Andric                               lldb_private::ExecutionContext &exe_ctx,
6915f757f3fSDimitry Andric                               lldb_private::Timeout<std::micro> timeout) {
69281ad6265SDimitry Andric   lldb_private::Log *log(GetLog(LLDBLog::Expressions));
6930b57cec5SDimitry Andric 
6940b57cec5SDimitry Andric   if (log) {
6950b57cec5SDimitry Andric     std::string s;
6960b57cec5SDimitry Andric     raw_string_ostream oss(s);
6970b57cec5SDimitry Andric 
6980b57cec5SDimitry Andric     module.print(oss, nullptr);
6990b57cec5SDimitry Andric 
7000b57cec5SDimitry Andric     oss.flush();
7010b57cec5SDimitry Andric 
7029dba64beSDimitry Andric     LLDB_LOGF(log, "Module as passed in to IRInterpreter::Interpret: \n\"%s\"",
7030b57cec5SDimitry Andric               s.c_str());
7040b57cec5SDimitry Andric   }
7050b57cec5SDimitry Andric 
7060b57cec5SDimitry Andric   DataLayout data_layout(&module);
7070b57cec5SDimitry Andric 
7080b57cec5SDimitry Andric   InterpreterStackFrame frame(data_layout, execution_unit, stack_frame_bottom,
7090b57cec5SDimitry Andric                               stack_frame_top);
7100b57cec5SDimitry Andric 
7110b57cec5SDimitry Andric   if (frame.m_frame_process_address == LLDB_INVALID_ADDRESS) {
7120b57cec5SDimitry Andric     error.SetErrorString("Couldn't allocate stack frame");
7130b57cec5SDimitry Andric   }
7140b57cec5SDimitry Andric 
7150b57cec5SDimitry Andric   int arg_index = 0;
7160b57cec5SDimitry Andric 
7170b57cec5SDimitry Andric   for (llvm::Function::arg_iterator ai = function.arg_begin(),
7180b57cec5SDimitry Andric                                     ae = function.arg_end();
7190b57cec5SDimitry Andric        ai != ae; ++ai, ++arg_index) {
7200b57cec5SDimitry Andric     if (args.size() <= static_cast<size_t>(arg_index)) {
7210b57cec5SDimitry Andric       error.SetErrorString("Not enough arguments passed in to function");
7220b57cec5SDimitry Andric       return false;
7230b57cec5SDimitry Andric     }
7240b57cec5SDimitry Andric 
7250b57cec5SDimitry Andric     lldb::addr_t ptr = args[arg_index];
7260b57cec5SDimitry Andric 
7270b57cec5SDimitry Andric     frame.MakeArgument(&*ai, ptr);
7280b57cec5SDimitry Andric   }
7290b57cec5SDimitry Andric 
7300b57cec5SDimitry Andric   frame.Jump(&function.front());
7310b57cec5SDimitry Andric 
7325f757f3fSDimitry Andric   lldb_private::Process *process = exe_ctx.GetProcessPtr();
7335f757f3fSDimitry Andric   lldb_private::Target *target = exe_ctx.GetTargetPtr();
7345f757f3fSDimitry Andric 
7355f757f3fSDimitry Andric   using clock = std::chrono::steady_clock;
7365f757f3fSDimitry Andric 
7375f757f3fSDimitry Andric   // Compute the time at which the timeout has been exceeded.
7385f757f3fSDimitry Andric   std::optional<clock::time_point> end_time;
7395f757f3fSDimitry Andric   if (timeout && timeout->count() > 0)
7405f757f3fSDimitry Andric     end_time = clock::now() + *timeout;
7415f757f3fSDimitry Andric 
7425f757f3fSDimitry Andric   while (frame.m_ii != frame.m_ie) {
7435f757f3fSDimitry Andric     // Timeout reached: stop interpreting.
7445f757f3fSDimitry Andric     if (end_time && clock::now() >= *end_time) {
7455f757f3fSDimitry Andric       error.SetErrorToGenericError();
7465f757f3fSDimitry Andric       error.SetErrorString(timeout_error);
7475f757f3fSDimitry Andric       return false;
7485f757f3fSDimitry Andric     }
7495f757f3fSDimitry Andric 
7505f757f3fSDimitry Andric     // If we have access to the debugger we can honor an interrupt request.
7515f757f3fSDimitry Andric     if (target) {
7525f757f3fSDimitry Andric       if (INTERRUPT_REQUESTED(target->GetDebugger(),
7535f757f3fSDimitry Andric                               "Interrupted in IR interpreting.")) {
7545f757f3fSDimitry Andric         error.SetErrorToGenericError();
7555f757f3fSDimitry Andric         error.SetErrorString(interrupt_error);
7565f757f3fSDimitry Andric         return false;
7575f757f3fSDimitry Andric       }
7585f757f3fSDimitry Andric     }
7595f757f3fSDimitry Andric 
7600b57cec5SDimitry Andric     const Instruction *inst = &*frame.m_ii;
7610b57cec5SDimitry Andric 
7629dba64beSDimitry Andric     LLDB_LOGF(log, "Interpreting %s", PrintValue(inst).c_str());
7630b57cec5SDimitry Andric 
7640b57cec5SDimitry Andric     switch (inst->getOpcode()) {
7650b57cec5SDimitry Andric     default:
7660b57cec5SDimitry Andric       break;
7670b57cec5SDimitry Andric 
7680b57cec5SDimitry Andric     case Instruction::Add:
7690b57cec5SDimitry Andric     case Instruction::Sub:
7700b57cec5SDimitry Andric     case Instruction::Mul:
7710b57cec5SDimitry Andric     case Instruction::SDiv:
7720b57cec5SDimitry Andric     case Instruction::UDiv:
7730b57cec5SDimitry Andric     case Instruction::SRem:
7740b57cec5SDimitry Andric     case Instruction::URem:
7750b57cec5SDimitry Andric     case Instruction::Shl:
7760b57cec5SDimitry Andric     case Instruction::LShr:
7770b57cec5SDimitry Andric     case Instruction::AShr:
7780b57cec5SDimitry Andric     case Instruction::And:
7790b57cec5SDimitry Andric     case Instruction::Or:
780bdd1243dSDimitry Andric     case Instruction::Xor:
781bdd1243dSDimitry Andric     case Instruction::FAdd:
782bdd1243dSDimitry Andric     case Instruction::FSub:
783bdd1243dSDimitry Andric     case Instruction::FMul:
784bdd1243dSDimitry Andric     case Instruction::FDiv: {
7850b57cec5SDimitry Andric       const BinaryOperator *bin_op = dyn_cast<BinaryOperator>(inst);
7860b57cec5SDimitry Andric 
7870b57cec5SDimitry Andric       if (!bin_op) {
7889dba64beSDimitry Andric         LLDB_LOGF(
7899dba64beSDimitry Andric             log,
7900b57cec5SDimitry Andric             "getOpcode() returns %s, but instruction is not a BinaryOperator",
7910b57cec5SDimitry Andric             inst->getOpcodeName());
7920b57cec5SDimitry Andric         error.SetErrorToGenericError();
7930b57cec5SDimitry Andric         error.SetErrorString(interpreter_internal_error);
7940b57cec5SDimitry Andric         return false;
7950b57cec5SDimitry Andric       }
7960b57cec5SDimitry Andric 
7970b57cec5SDimitry Andric       Value *lhs = inst->getOperand(0);
7980b57cec5SDimitry Andric       Value *rhs = inst->getOperand(1);
7990b57cec5SDimitry Andric 
8000b57cec5SDimitry Andric       lldb_private::Scalar L;
8010b57cec5SDimitry Andric       lldb_private::Scalar R;
8020b57cec5SDimitry Andric 
8030b57cec5SDimitry Andric       if (!frame.EvaluateValue(L, lhs, module)) {
8049dba64beSDimitry Andric         LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(lhs).c_str());
8050b57cec5SDimitry Andric         error.SetErrorToGenericError();
8060b57cec5SDimitry Andric         error.SetErrorString(bad_value_error);
8070b57cec5SDimitry Andric         return false;
8080b57cec5SDimitry Andric       }
8090b57cec5SDimitry Andric 
8100b57cec5SDimitry Andric       if (!frame.EvaluateValue(R, rhs, module)) {
8119dba64beSDimitry Andric         LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(rhs).c_str());
8120b57cec5SDimitry Andric         error.SetErrorToGenericError();
8130b57cec5SDimitry Andric         error.SetErrorString(bad_value_error);
8140b57cec5SDimitry Andric         return false;
8150b57cec5SDimitry Andric       }
8160b57cec5SDimitry Andric 
8170b57cec5SDimitry Andric       lldb_private::Scalar result;
8180b57cec5SDimitry Andric 
8190b57cec5SDimitry Andric       switch (inst->getOpcode()) {
8200b57cec5SDimitry Andric       default:
8210b57cec5SDimitry Andric         break;
8220b57cec5SDimitry Andric       case Instruction::Add:
823bdd1243dSDimitry Andric       case Instruction::FAdd:
8240b57cec5SDimitry Andric         result = L + R;
8250b57cec5SDimitry Andric         break;
8260b57cec5SDimitry Andric       case Instruction::Mul:
827bdd1243dSDimitry Andric       case Instruction::FMul:
8280b57cec5SDimitry Andric         result = L * R;
8290b57cec5SDimitry Andric         break;
8300b57cec5SDimitry Andric       case Instruction::Sub:
831bdd1243dSDimitry Andric       case Instruction::FSub:
8320b57cec5SDimitry Andric         result = L - R;
8330b57cec5SDimitry Andric         break;
8340b57cec5SDimitry Andric       case Instruction::SDiv:
8350b57cec5SDimitry Andric         L.MakeSigned();
8360b57cec5SDimitry Andric         R.MakeSigned();
8370b57cec5SDimitry Andric         result = L / R;
8380b57cec5SDimitry Andric         break;
8390b57cec5SDimitry Andric       case Instruction::UDiv:
8400b57cec5SDimitry Andric         L.MakeUnsigned();
8410b57cec5SDimitry Andric         R.MakeUnsigned();
8420b57cec5SDimitry Andric         result = L / R;
8430b57cec5SDimitry Andric         break;
844bdd1243dSDimitry Andric       case Instruction::FDiv:
845bdd1243dSDimitry Andric         result = L / R;
846bdd1243dSDimitry Andric         break;
8470b57cec5SDimitry Andric       case Instruction::SRem:
8480b57cec5SDimitry Andric         L.MakeSigned();
8490b57cec5SDimitry Andric         R.MakeSigned();
8500b57cec5SDimitry Andric         result = L % R;
8510b57cec5SDimitry Andric         break;
8520b57cec5SDimitry Andric       case Instruction::URem:
8530b57cec5SDimitry Andric         L.MakeUnsigned();
8540b57cec5SDimitry Andric         R.MakeUnsigned();
8550b57cec5SDimitry Andric         result = L % R;
8560b57cec5SDimitry Andric         break;
8570b57cec5SDimitry Andric       case Instruction::Shl:
8580b57cec5SDimitry Andric         result = L << R;
8590b57cec5SDimitry Andric         break;
8600b57cec5SDimitry Andric       case Instruction::AShr:
8610b57cec5SDimitry Andric         result = L >> R;
8620b57cec5SDimitry Andric         break;
8630b57cec5SDimitry Andric       case Instruction::LShr:
8640b57cec5SDimitry Andric         result = L;
8650b57cec5SDimitry Andric         result.ShiftRightLogical(R);
8660b57cec5SDimitry Andric         break;
8670b57cec5SDimitry Andric       case Instruction::And:
8680b57cec5SDimitry Andric         result = L & R;
8690b57cec5SDimitry Andric         break;
8700b57cec5SDimitry Andric       case Instruction::Or:
8710b57cec5SDimitry Andric         result = L | R;
8720b57cec5SDimitry Andric         break;
8730b57cec5SDimitry Andric       case Instruction::Xor:
8740b57cec5SDimitry Andric         result = L ^ R;
8750b57cec5SDimitry Andric         break;
8760b57cec5SDimitry Andric       }
8770b57cec5SDimitry Andric 
8780b57cec5SDimitry Andric       frame.AssignValue(inst, result, module);
8790b57cec5SDimitry Andric 
8800b57cec5SDimitry Andric       if (log) {
8819dba64beSDimitry Andric         LLDB_LOGF(log, "Interpreted a %s", inst->getOpcodeName());
8829dba64beSDimitry Andric         LLDB_LOGF(log, "  L : %s", frame.SummarizeValue(lhs).c_str());
8839dba64beSDimitry Andric         LLDB_LOGF(log, "  R : %s", frame.SummarizeValue(rhs).c_str());
8849dba64beSDimitry Andric         LLDB_LOGF(log, "  = : %s", frame.SummarizeValue(inst).c_str());
8850b57cec5SDimitry Andric       }
8860b57cec5SDimitry Andric     } break;
8870b57cec5SDimitry Andric     case Instruction::Alloca: {
888480093f4SDimitry Andric       const AllocaInst *alloca_inst = cast<AllocaInst>(inst);
8890b57cec5SDimitry Andric 
8900b57cec5SDimitry Andric       if (alloca_inst->isArrayAllocation()) {
8919dba64beSDimitry Andric         LLDB_LOGF(log,
8920b57cec5SDimitry Andric                   "AllocaInsts are not handled if isArrayAllocation() is true");
8930b57cec5SDimitry Andric         error.SetErrorToGenericError();
8940b57cec5SDimitry Andric         error.SetErrorString(unsupported_opcode_error);
8950b57cec5SDimitry Andric         return false;
8960b57cec5SDimitry Andric       }
8970b57cec5SDimitry Andric 
8980b57cec5SDimitry Andric       // The semantics of Alloca are:
8990b57cec5SDimitry Andric       //   Create a region R of virtual memory of type T, backed by a data
9000b57cec5SDimitry Andric       //   buffer
9010b57cec5SDimitry Andric       //   Create a region P of virtual memory of type T*, backed by a data
9020b57cec5SDimitry Andric       //   buffer
9030b57cec5SDimitry Andric       //   Write the virtual address of R into P
9040b57cec5SDimitry Andric 
9050b57cec5SDimitry Andric       Type *T = alloca_inst->getAllocatedType();
9060b57cec5SDimitry Andric       Type *Tptr = alloca_inst->getType();
9070b57cec5SDimitry Andric 
9080b57cec5SDimitry Andric       lldb::addr_t R = frame.Malloc(T);
9090b57cec5SDimitry Andric 
9100b57cec5SDimitry Andric       if (R == LLDB_INVALID_ADDRESS) {
9119dba64beSDimitry Andric         LLDB_LOGF(log, "Couldn't allocate memory for an AllocaInst");
9120b57cec5SDimitry Andric         error.SetErrorToGenericError();
9130b57cec5SDimitry Andric         error.SetErrorString(memory_allocation_error);
9140b57cec5SDimitry Andric         return false;
9150b57cec5SDimitry Andric       }
9160b57cec5SDimitry Andric 
9170b57cec5SDimitry Andric       lldb::addr_t P = frame.Malloc(Tptr);
9180b57cec5SDimitry Andric 
9190b57cec5SDimitry Andric       if (P == LLDB_INVALID_ADDRESS) {
9209dba64beSDimitry Andric         LLDB_LOGF(log,
9219dba64beSDimitry Andric                   "Couldn't allocate the result pointer for an AllocaInst");
9220b57cec5SDimitry Andric         error.SetErrorToGenericError();
9230b57cec5SDimitry Andric         error.SetErrorString(memory_allocation_error);
9240b57cec5SDimitry Andric         return false;
9250b57cec5SDimitry Andric       }
9260b57cec5SDimitry Andric 
9270b57cec5SDimitry Andric       lldb_private::Status write_error;
9280b57cec5SDimitry Andric 
9290b57cec5SDimitry Andric       execution_unit.WritePointerToMemory(P, R, write_error);
9300b57cec5SDimitry Andric 
9310b57cec5SDimitry Andric       if (!write_error.Success()) {
9329dba64beSDimitry Andric         LLDB_LOGF(log, "Couldn't write the result pointer for an AllocaInst");
9330b57cec5SDimitry Andric         error.SetErrorToGenericError();
9340b57cec5SDimitry Andric         error.SetErrorString(memory_write_error);
9350b57cec5SDimitry Andric         lldb_private::Status free_error;
9360b57cec5SDimitry Andric         execution_unit.Free(P, free_error);
9370b57cec5SDimitry Andric         execution_unit.Free(R, free_error);
9380b57cec5SDimitry Andric         return false;
9390b57cec5SDimitry Andric       }
9400b57cec5SDimitry Andric 
9410b57cec5SDimitry Andric       frame.m_values[alloca_inst] = P;
9420b57cec5SDimitry Andric 
9430b57cec5SDimitry Andric       if (log) {
9449dba64beSDimitry Andric         LLDB_LOGF(log, "Interpreted an AllocaInst");
9459dba64beSDimitry Andric         LLDB_LOGF(log, "  R : 0x%" PRIx64, R);
9469dba64beSDimitry Andric         LLDB_LOGF(log, "  P : 0x%" PRIx64, P);
9470b57cec5SDimitry Andric       }
9480b57cec5SDimitry Andric     } break;
9490b57cec5SDimitry Andric     case Instruction::BitCast:
9500b57cec5SDimitry Andric     case Instruction::ZExt: {
951480093f4SDimitry Andric       const CastInst *cast_inst = cast<CastInst>(inst);
9520b57cec5SDimitry Andric 
9530b57cec5SDimitry Andric       Value *source = cast_inst->getOperand(0);
9540b57cec5SDimitry Andric 
9550b57cec5SDimitry Andric       lldb_private::Scalar S;
9560b57cec5SDimitry Andric 
9570b57cec5SDimitry Andric       if (!frame.EvaluateValue(S, source, module)) {
9589dba64beSDimitry Andric         LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(source).c_str());
9590b57cec5SDimitry Andric         error.SetErrorToGenericError();
9600b57cec5SDimitry Andric         error.SetErrorString(bad_value_error);
9610b57cec5SDimitry Andric         return false;
9620b57cec5SDimitry Andric       }
9630b57cec5SDimitry Andric 
9640b57cec5SDimitry Andric       frame.AssignValue(inst, S, module);
9650b57cec5SDimitry Andric     } break;
9660b57cec5SDimitry Andric     case Instruction::SExt: {
967480093f4SDimitry Andric       const CastInst *cast_inst = cast<CastInst>(inst);
9680b57cec5SDimitry Andric 
9690b57cec5SDimitry Andric       Value *source = cast_inst->getOperand(0);
9700b57cec5SDimitry Andric 
9710b57cec5SDimitry Andric       lldb_private::Scalar S;
9720b57cec5SDimitry Andric 
9730b57cec5SDimitry Andric       if (!frame.EvaluateValue(S, source, module)) {
9749dba64beSDimitry Andric         LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(source).c_str());
9750b57cec5SDimitry Andric         error.SetErrorToGenericError();
9760b57cec5SDimitry Andric         error.SetErrorString(bad_value_error);
9770b57cec5SDimitry Andric         return false;
9780b57cec5SDimitry Andric       }
9790b57cec5SDimitry Andric 
9800b57cec5SDimitry Andric       S.MakeSigned();
9810b57cec5SDimitry Andric 
9820b57cec5SDimitry Andric       lldb_private::Scalar S_signextend(S.SLongLong());
9830b57cec5SDimitry Andric 
9840b57cec5SDimitry Andric       frame.AssignValue(inst, S_signextend, module);
9850b57cec5SDimitry Andric     } break;
9860b57cec5SDimitry Andric     case Instruction::Br: {
987480093f4SDimitry Andric       const BranchInst *br_inst = cast<BranchInst>(inst);
9880b57cec5SDimitry Andric 
9890b57cec5SDimitry Andric       if (br_inst->isConditional()) {
9900b57cec5SDimitry Andric         Value *condition = br_inst->getCondition();
9910b57cec5SDimitry Andric 
9920b57cec5SDimitry Andric         lldb_private::Scalar C;
9930b57cec5SDimitry Andric 
9940b57cec5SDimitry Andric         if (!frame.EvaluateValue(C, condition, module)) {
9959dba64beSDimitry Andric           LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(condition).c_str());
9960b57cec5SDimitry Andric           error.SetErrorToGenericError();
9970b57cec5SDimitry Andric           error.SetErrorString(bad_value_error);
9980b57cec5SDimitry Andric           return false;
9990b57cec5SDimitry Andric         }
10000b57cec5SDimitry Andric 
10010b57cec5SDimitry Andric         if (!C.IsZero())
10020b57cec5SDimitry Andric           frame.Jump(br_inst->getSuccessor(0));
10030b57cec5SDimitry Andric         else
10040b57cec5SDimitry Andric           frame.Jump(br_inst->getSuccessor(1));
10050b57cec5SDimitry Andric 
10060b57cec5SDimitry Andric         if (log) {
10079dba64beSDimitry Andric           LLDB_LOGF(log, "Interpreted a BrInst with a condition");
10089dba64beSDimitry Andric           LLDB_LOGF(log, "  cond : %s",
10099dba64beSDimitry Andric                     frame.SummarizeValue(condition).c_str());
10100b57cec5SDimitry Andric         }
10110b57cec5SDimitry Andric       } else {
10120b57cec5SDimitry Andric         frame.Jump(br_inst->getSuccessor(0));
10130b57cec5SDimitry Andric 
10140b57cec5SDimitry Andric         if (log) {
10159dba64beSDimitry Andric           LLDB_LOGF(log, "Interpreted a BrInst with no condition");
10160b57cec5SDimitry Andric         }
10170b57cec5SDimitry Andric       }
10180b57cec5SDimitry Andric     }
10190b57cec5SDimitry Andric       continue;
10200b57cec5SDimitry Andric     case Instruction::PHI: {
1021480093f4SDimitry Andric       const PHINode *phi_inst = cast<PHINode>(inst);
10220b57cec5SDimitry Andric       if (!frame.m_prev_bb) {
10239dba64beSDimitry Andric         LLDB_LOGF(log,
10249dba64beSDimitry Andric                   "Encountered PHI node without having jumped from another "
10250b57cec5SDimitry Andric                   "basic block");
10260b57cec5SDimitry Andric         error.SetErrorToGenericError();
10270b57cec5SDimitry Andric         error.SetErrorString(interpreter_internal_error);
10280b57cec5SDimitry Andric         return false;
10290b57cec5SDimitry Andric       }
10300b57cec5SDimitry Andric 
10310b57cec5SDimitry Andric       Value *value = phi_inst->getIncomingValueForBlock(frame.m_prev_bb);
10320b57cec5SDimitry Andric       lldb_private::Scalar result;
10330b57cec5SDimitry Andric       if (!frame.EvaluateValue(result, value, module)) {
10349dba64beSDimitry Andric         LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(value).c_str());
10350b57cec5SDimitry Andric         error.SetErrorToGenericError();
10360b57cec5SDimitry Andric         error.SetErrorString(bad_value_error);
10370b57cec5SDimitry Andric         return false;
10380b57cec5SDimitry Andric       }
10390b57cec5SDimitry Andric       frame.AssignValue(inst, result, module);
10400b57cec5SDimitry Andric 
10410b57cec5SDimitry Andric       if (log) {
10429dba64beSDimitry Andric         LLDB_LOGF(log, "Interpreted a %s", inst->getOpcodeName());
10439dba64beSDimitry Andric         LLDB_LOGF(log, "  Incoming value : %s",
10440b57cec5SDimitry Andric                   frame.SummarizeValue(value).c_str());
10450b57cec5SDimitry Andric       }
10460b57cec5SDimitry Andric     } break;
10470b57cec5SDimitry Andric     case Instruction::GetElementPtr: {
1048480093f4SDimitry Andric       const GetElementPtrInst *gep_inst = cast<GetElementPtrInst>(inst);
10490b57cec5SDimitry Andric 
10500b57cec5SDimitry Andric       const Value *pointer_operand = gep_inst->getPointerOperand();
10510b57cec5SDimitry Andric       Type *src_elem_ty = gep_inst->getSourceElementType();
10520b57cec5SDimitry Andric 
10530b57cec5SDimitry Andric       lldb_private::Scalar P;
10540b57cec5SDimitry Andric 
10550b57cec5SDimitry Andric       if (!frame.EvaluateValue(P, pointer_operand, module)) {
10569dba64beSDimitry Andric         LLDB_LOGF(log, "Couldn't evaluate %s",
10570b57cec5SDimitry Andric                   PrintValue(pointer_operand).c_str());
10580b57cec5SDimitry Andric         error.SetErrorToGenericError();
10590b57cec5SDimitry Andric         error.SetErrorString(bad_value_error);
10600b57cec5SDimitry Andric         return false;
10610b57cec5SDimitry Andric       }
10620b57cec5SDimitry Andric 
10630b57cec5SDimitry Andric       typedef SmallVector<Value *, 8> IndexVector;
10640b57cec5SDimitry Andric       typedef IndexVector::iterator IndexIterator;
10650b57cec5SDimitry Andric 
10660b57cec5SDimitry Andric       SmallVector<Value *, 8> indices(gep_inst->idx_begin(),
10670b57cec5SDimitry Andric                                       gep_inst->idx_end());
10680b57cec5SDimitry Andric 
10690b57cec5SDimitry Andric       SmallVector<Value *, 8> const_indices;
10700b57cec5SDimitry Andric 
10710b57cec5SDimitry Andric       for (IndexIterator ii = indices.begin(), ie = indices.end(); ii != ie;
10720b57cec5SDimitry Andric            ++ii) {
10730b57cec5SDimitry Andric         ConstantInt *constant_index = dyn_cast<ConstantInt>(*ii);
10740b57cec5SDimitry Andric 
10750b57cec5SDimitry Andric         if (!constant_index) {
10760b57cec5SDimitry Andric           lldb_private::Scalar I;
10770b57cec5SDimitry Andric 
10780b57cec5SDimitry Andric           if (!frame.EvaluateValue(I, *ii, module)) {
10799dba64beSDimitry Andric             LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(*ii).c_str());
10800b57cec5SDimitry Andric             error.SetErrorToGenericError();
10810b57cec5SDimitry Andric             error.SetErrorString(bad_value_error);
10820b57cec5SDimitry Andric             return false;
10830b57cec5SDimitry Andric           }
10840b57cec5SDimitry Andric 
10859dba64beSDimitry Andric           LLDB_LOGF(log, "Evaluated constant index %s as %llu",
10869dba64beSDimitry Andric                     PrintValue(*ii).c_str(), I.ULongLong(LLDB_INVALID_ADDRESS));
10870b57cec5SDimitry Andric 
10880b57cec5SDimitry Andric           constant_index = cast<ConstantInt>(ConstantInt::get(
10890b57cec5SDimitry Andric               (*ii)->getType(), I.ULongLong(LLDB_INVALID_ADDRESS)));
10900b57cec5SDimitry Andric         }
10910b57cec5SDimitry Andric 
10920b57cec5SDimitry Andric         const_indices.push_back(constant_index);
10930b57cec5SDimitry Andric       }
10940b57cec5SDimitry Andric 
10950b57cec5SDimitry Andric       uint64_t offset =
10960b57cec5SDimitry Andric           data_layout.getIndexedOffsetInType(src_elem_ty, const_indices);
10970b57cec5SDimitry Andric 
10980b57cec5SDimitry Andric       lldb_private::Scalar Poffset = P + offset;
10990b57cec5SDimitry Andric 
11000b57cec5SDimitry Andric       frame.AssignValue(inst, Poffset, module);
11010b57cec5SDimitry Andric 
11020b57cec5SDimitry Andric       if (log) {
11039dba64beSDimitry Andric         LLDB_LOGF(log, "Interpreted a GetElementPtrInst");
11049dba64beSDimitry Andric         LLDB_LOGF(log, "  P       : %s",
11050b57cec5SDimitry Andric                   frame.SummarizeValue(pointer_operand).c_str());
11069dba64beSDimitry Andric         LLDB_LOGF(log, "  Poffset : %s", frame.SummarizeValue(inst).c_str());
11070b57cec5SDimitry Andric       }
11080b57cec5SDimitry Andric     } break;
1109bdd1243dSDimitry Andric     case Instruction::FCmp:
11100b57cec5SDimitry Andric     case Instruction::ICmp: {
1111bdd1243dSDimitry Andric       const CmpInst *icmp_inst = cast<CmpInst>(inst);
11120b57cec5SDimitry Andric 
11130b57cec5SDimitry Andric       CmpInst::Predicate predicate = icmp_inst->getPredicate();
11140b57cec5SDimitry Andric 
11150b57cec5SDimitry Andric       Value *lhs = inst->getOperand(0);
11160b57cec5SDimitry Andric       Value *rhs = inst->getOperand(1);
11170b57cec5SDimitry Andric 
11180b57cec5SDimitry Andric       lldb_private::Scalar L;
11190b57cec5SDimitry Andric       lldb_private::Scalar R;
11200b57cec5SDimitry Andric 
11210b57cec5SDimitry Andric       if (!frame.EvaluateValue(L, lhs, module)) {
11229dba64beSDimitry Andric         LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(lhs).c_str());
11230b57cec5SDimitry Andric         error.SetErrorToGenericError();
11240b57cec5SDimitry Andric         error.SetErrorString(bad_value_error);
11250b57cec5SDimitry Andric         return false;
11260b57cec5SDimitry Andric       }
11270b57cec5SDimitry Andric 
11280b57cec5SDimitry Andric       if (!frame.EvaluateValue(R, rhs, module)) {
11299dba64beSDimitry Andric         LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(rhs).c_str());
11300b57cec5SDimitry Andric         error.SetErrorToGenericError();
11310b57cec5SDimitry Andric         error.SetErrorString(bad_value_error);
11320b57cec5SDimitry Andric         return false;
11330b57cec5SDimitry Andric       }
11340b57cec5SDimitry Andric 
11350b57cec5SDimitry Andric       lldb_private::Scalar result;
11360b57cec5SDimitry Andric 
11370b57cec5SDimitry Andric       switch (predicate) {
11380b57cec5SDimitry Andric       default:
11390b57cec5SDimitry Andric         return false;
11400b57cec5SDimitry Andric       case CmpInst::ICMP_EQ:
1141bdd1243dSDimitry Andric       case CmpInst::FCMP_OEQ:
11420b57cec5SDimitry Andric         result = (L == R);
11430b57cec5SDimitry Andric         break;
11440b57cec5SDimitry Andric       case CmpInst::ICMP_NE:
1145bdd1243dSDimitry Andric       case CmpInst::FCMP_UNE:
11460b57cec5SDimitry Andric         result = (L != R);
11470b57cec5SDimitry Andric         break;
11480b57cec5SDimitry Andric       case CmpInst::ICMP_UGT:
11490b57cec5SDimitry Andric         L.MakeUnsigned();
11500b57cec5SDimitry Andric         R.MakeUnsigned();
11510b57cec5SDimitry Andric         result = (L > R);
11520b57cec5SDimitry Andric         break;
11530b57cec5SDimitry Andric       case CmpInst::ICMP_UGE:
11540b57cec5SDimitry Andric         L.MakeUnsigned();
11550b57cec5SDimitry Andric         R.MakeUnsigned();
11560b57cec5SDimitry Andric         result = (L >= R);
11570b57cec5SDimitry Andric         break;
1158bdd1243dSDimitry Andric       case CmpInst::FCMP_OGE:
1159bdd1243dSDimitry Andric         result = (L >= R);
1160bdd1243dSDimitry Andric         break;
1161bdd1243dSDimitry Andric       case CmpInst::FCMP_OGT:
1162bdd1243dSDimitry Andric         result = (L > R);
1163bdd1243dSDimitry Andric         break;
11640b57cec5SDimitry Andric       case CmpInst::ICMP_ULT:
11650b57cec5SDimitry Andric         L.MakeUnsigned();
11660b57cec5SDimitry Andric         R.MakeUnsigned();
11670b57cec5SDimitry Andric         result = (L < R);
11680b57cec5SDimitry Andric         break;
1169bdd1243dSDimitry Andric       case CmpInst::FCMP_OLT:
1170bdd1243dSDimitry Andric         result = (L < R);
1171bdd1243dSDimitry Andric         break;
11720b57cec5SDimitry Andric       case CmpInst::ICMP_ULE:
11730b57cec5SDimitry Andric         L.MakeUnsigned();
11740b57cec5SDimitry Andric         R.MakeUnsigned();
11750b57cec5SDimitry Andric         result = (L <= R);
11760b57cec5SDimitry Andric         break;
1177bdd1243dSDimitry Andric       case CmpInst::FCMP_OLE:
1178bdd1243dSDimitry Andric         result = (L <= R);
1179bdd1243dSDimitry Andric         break;
11800b57cec5SDimitry Andric       case CmpInst::ICMP_SGT:
11810b57cec5SDimitry Andric         L.MakeSigned();
11820b57cec5SDimitry Andric         R.MakeSigned();
11830b57cec5SDimitry Andric         result = (L > R);
11840b57cec5SDimitry Andric         break;
11850b57cec5SDimitry Andric       case CmpInst::ICMP_SGE:
11860b57cec5SDimitry Andric         L.MakeSigned();
11870b57cec5SDimitry Andric         R.MakeSigned();
11880b57cec5SDimitry Andric         result = (L >= R);
11890b57cec5SDimitry Andric         break;
11900b57cec5SDimitry Andric       case CmpInst::ICMP_SLT:
11910b57cec5SDimitry Andric         L.MakeSigned();
11920b57cec5SDimitry Andric         R.MakeSigned();
11930b57cec5SDimitry Andric         result = (L < R);
11940b57cec5SDimitry Andric         break;
11950b57cec5SDimitry Andric       case CmpInst::ICMP_SLE:
11960b57cec5SDimitry Andric         L.MakeSigned();
11970b57cec5SDimitry Andric         R.MakeSigned();
11980b57cec5SDimitry Andric         result = (L <= R);
11990b57cec5SDimitry Andric         break;
12000b57cec5SDimitry Andric       }
12010b57cec5SDimitry Andric 
12020b57cec5SDimitry Andric       frame.AssignValue(inst, result, module);
12030b57cec5SDimitry Andric 
12040b57cec5SDimitry Andric       if (log) {
12059dba64beSDimitry Andric         LLDB_LOGF(log, "Interpreted an ICmpInst");
12069dba64beSDimitry Andric         LLDB_LOGF(log, "  L : %s", frame.SummarizeValue(lhs).c_str());
12079dba64beSDimitry Andric         LLDB_LOGF(log, "  R : %s", frame.SummarizeValue(rhs).c_str());
12089dba64beSDimitry Andric         LLDB_LOGF(log, "  = : %s", frame.SummarizeValue(inst).c_str());
12090b57cec5SDimitry Andric       }
12100b57cec5SDimitry Andric     } break;
12110b57cec5SDimitry Andric     case Instruction::IntToPtr: {
1212480093f4SDimitry Andric       const IntToPtrInst *int_to_ptr_inst = cast<IntToPtrInst>(inst);
12130b57cec5SDimitry Andric 
12140b57cec5SDimitry Andric       Value *src_operand = int_to_ptr_inst->getOperand(0);
12150b57cec5SDimitry Andric 
12160b57cec5SDimitry Andric       lldb_private::Scalar I;
12170b57cec5SDimitry Andric 
12180b57cec5SDimitry Andric       if (!frame.EvaluateValue(I, src_operand, module)) {
12199dba64beSDimitry Andric         LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(src_operand).c_str());
12200b57cec5SDimitry Andric         error.SetErrorToGenericError();
12210b57cec5SDimitry Andric         error.SetErrorString(bad_value_error);
12220b57cec5SDimitry Andric         return false;
12230b57cec5SDimitry Andric       }
12240b57cec5SDimitry Andric 
12250b57cec5SDimitry Andric       frame.AssignValue(inst, I, module);
12260b57cec5SDimitry Andric 
12270b57cec5SDimitry Andric       if (log) {
12289dba64beSDimitry Andric         LLDB_LOGF(log, "Interpreted an IntToPtr");
12299dba64beSDimitry Andric         LLDB_LOGF(log, "  Src : %s", frame.SummarizeValue(src_operand).c_str());
12309dba64beSDimitry Andric         LLDB_LOGF(log, "  =   : %s", frame.SummarizeValue(inst).c_str());
12310b57cec5SDimitry Andric       }
12320b57cec5SDimitry Andric     } break;
12330b57cec5SDimitry Andric     case Instruction::PtrToInt: {
1234480093f4SDimitry Andric       const PtrToIntInst *ptr_to_int_inst = cast<PtrToIntInst>(inst);
12350b57cec5SDimitry Andric 
12360b57cec5SDimitry Andric       Value *src_operand = ptr_to_int_inst->getOperand(0);
12370b57cec5SDimitry Andric 
12380b57cec5SDimitry Andric       lldb_private::Scalar I;
12390b57cec5SDimitry Andric 
12400b57cec5SDimitry Andric       if (!frame.EvaluateValue(I, src_operand, module)) {
12419dba64beSDimitry Andric         LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(src_operand).c_str());
12420b57cec5SDimitry Andric         error.SetErrorToGenericError();
12430b57cec5SDimitry Andric         error.SetErrorString(bad_value_error);
12440b57cec5SDimitry Andric         return false;
12450b57cec5SDimitry Andric       }
12460b57cec5SDimitry Andric 
12470b57cec5SDimitry Andric       frame.AssignValue(inst, I, module);
12480b57cec5SDimitry Andric 
12490b57cec5SDimitry Andric       if (log) {
12509dba64beSDimitry Andric         LLDB_LOGF(log, "Interpreted a PtrToInt");
12519dba64beSDimitry Andric         LLDB_LOGF(log, "  Src : %s", frame.SummarizeValue(src_operand).c_str());
12529dba64beSDimitry Andric         LLDB_LOGF(log, "  =   : %s", frame.SummarizeValue(inst).c_str());
12530b57cec5SDimitry Andric       }
12540b57cec5SDimitry Andric     } break;
12550b57cec5SDimitry Andric     case Instruction::Trunc: {
1256480093f4SDimitry Andric       const TruncInst *trunc_inst = cast<TruncInst>(inst);
12570b57cec5SDimitry Andric 
12580b57cec5SDimitry Andric       Value *src_operand = trunc_inst->getOperand(0);
12590b57cec5SDimitry Andric 
12600b57cec5SDimitry Andric       lldb_private::Scalar I;
12610b57cec5SDimitry Andric 
12620b57cec5SDimitry Andric       if (!frame.EvaluateValue(I, src_operand, module)) {
12639dba64beSDimitry Andric         LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(src_operand).c_str());
12640b57cec5SDimitry Andric         error.SetErrorToGenericError();
12650b57cec5SDimitry Andric         error.SetErrorString(bad_value_error);
12660b57cec5SDimitry Andric         return false;
12670b57cec5SDimitry Andric       }
12680b57cec5SDimitry Andric 
12690b57cec5SDimitry Andric       frame.AssignValue(inst, I, module);
12700b57cec5SDimitry Andric 
12710b57cec5SDimitry Andric       if (log) {
12729dba64beSDimitry Andric         LLDB_LOGF(log, "Interpreted a Trunc");
12739dba64beSDimitry Andric         LLDB_LOGF(log, "  Src : %s", frame.SummarizeValue(src_operand).c_str());
12749dba64beSDimitry Andric         LLDB_LOGF(log, "  =   : %s", frame.SummarizeValue(inst).c_str());
12750b57cec5SDimitry Andric       }
12760b57cec5SDimitry Andric     } break;
12770b57cec5SDimitry Andric     case Instruction::Load: {
1278480093f4SDimitry Andric       const LoadInst *load_inst = cast<LoadInst>(inst);
12790b57cec5SDimitry Andric 
12800b57cec5SDimitry Andric       // The semantics of Load are:
12810b57cec5SDimitry Andric       //   Create a region D that will contain the loaded data
12820b57cec5SDimitry Andric       //   Resolve the region P containing a pointer
12830b57cec5SDimitry Andric       //   Dereference P to get the region R that the data should be loaded from
12840b57cec5SDimitry Andric       //   Transfer a unit of type type(D) from R to D
12850b57cec5SDimitry Andric 
12860b57cec5SDimitry Andric       const Value *pointer_operand = load_inst->getPointerOperand();
12870b57cec5SDimitry Andric 
12880b57cec5SDimitry Andric       lldb::addr_t D = frame.ResolveValue(load_inst, module);
12890b57cec5SDimitry Andric       lldb::addr_t P = frame.ResolveValue(pointer_operand, module);
12900b57cec5SDimitry Andric 
12910b57cec5SDimitry Andric       if (D == LLDB_INVALID_ADDRESS) {
12929dba64beSDimitry Andric         LLDB_LOGF(log, "LoadInst's value doesn't resolve to anything");
12930b57cec5SDimitry Andric         error.SetErrorToGenericError();
12940b57cec5SDimitry Andric         error.SetErrorString(bad_value_error);
12950b57cec5SDimitry Andric         return false;
12960b57cec5SDimitry Andric       }
12970b57cec5SDimitry Andric 
12980b57cec5SDimitry Andric       if (P == LLDB_INVALID_ADDRESS) {
12999dba64beSDimitry Andric         LLDB_LOGF(log, "LoadInst's pointer doesn't resolve to anything");
13000b57cec5SDimitry Andric         error.SetErrorToGenericError();
13010b57cec5SDimitry Andric         error.SetErrorString(bad_value_error);
13020b57cec5SDimitry Andric         return false;
13030b57cec5SDimitry Andric       }
13040b57cec5SDimitry Andric 
13050b57cec5SDimitry Andric       lldb::addr_t R;
13060b57cec5SDimitry Andric       lldb_private::Status read_error;
13070b57cec5SDimitry Andric       execution_unit.ReadPointerFromMemory(&R, P, read_error);
13080b57cec5SDimitry Andric 
13090b57cec5SDimitry Andric       if (!read_error.Success()) {
13109dba64beSDimitry Andric         LLDB_LOGF(log, "Couldn't read the address to be loaded for a LoadInst");
13110b57cec5SDimitry Andric         error.SetErrorToGenericError();
13120b57cec5SDimitry Andric         error.SetErrorString(memory_read_error);
13130b57cec5SDimitry Andric         return false;
13140b57cec5SDimitry Andric       }
13150b57cec5SDimitry Andric 
131681ad6265SDimitry Andric       Type *target_ty = load_inst->getType();
13170b57cec5SDimitry Andric       size_t target_size = data_layout.getTypeStoreSize(target_ty);
13180b57cec5SDimitry Andric       lldb_private::DataBufferHeap buffer(target_size, 0);
13190b57cec5SDimitry Andric 
13200b57cec5SDimitry Andric       read_error.Clear();
13210b57cec5SDimitry Andric       execution_unit.ReadMemory(buffer.GetBytes(), R, buffer.GetByteSize(),
13220b57cec5SDimitry Andric                                 read_error);
13230b57cec5SDimitry Andric       if (!read_error.Success()) {
13249dba64beSDimitry Andric         LLDB_LOGF(log, "Couldn't read from a region on behalf of a LoadInst");
13250b57cec5SDimitry Andric         error.SetErrorToGenericError();
13260b57cec5SDimitry Andric         error.SetErrorString(memory_read_error);
13270b57cec5SDimitry Andric         return false;
13280b57cec5SDimitry Andric       }
13290b57cec5SDimitry Andric 
13300b57cec5SDimitry Andric       lldb_private::Status write_error;
13310b57cec5SDimitry Andric       execution_unit.WriteMemory(D, buffer.GetBytes(), buffer.GetByteSize(),
13320b57cec5SDimitry Andric                                  write_error);
13330b57cec5SDimitry Andric       if (!write_error.Success()) {
13349dba64beSDimitry Andric         LLDB_LOGF(log, "Couldn't write to a region on behalf of a LoadInst");
13350b57cec5SDimitry Andric         error.SetErrorToGenericError();
1336fe6060f1SDimitry Andric         error.SetErrorString(memory_write_error);
13370b57cec5SDimitry Andric         return false;
13380b57cec5SDimitry Andric       }
13390b57cec5SDimitry Andric 
13400b57cec5SDimitry Andric       if (log) {
13419dba64beSDimitry Andric         LLDB_LOGF(log, "Interpreted a LoadInst");
13429dba64beSDimitry Andric         LLDB_LOGF(log, "  P : 0x%" PRIx64, P);
13439dba64beSDimitry Andric         LLDB_LOGF(log, "  R : 0x%" PRIx64, R);
13449dba64beSDimitry Andric         LLDB_LOGF(log, "  D : 0x%" PRIx64, D);
13450b57cec5SDimitry Andric       }
13460b57cec5SDimitry Andric     } break;
13470b57cec5SDimitry Andric     case Instruction::Ret: {
13480b57cec5SDimitry Andric       return true;
13490b57cec5SDimitry Andric     }
13500b57cec5SDimitry Andric     case Instruction::Store: {
1351480093f4SDimitry Andric       const StoreInst *store_inst = cast<StoreInst>(inst);
13520b57cec5SDimitry Andric 
13530b57cec5SDimitry Andric       // The semantics of Store are:
13540b57cec5SDimitry Andric       //   Resolve the region D containing the data to be stored
13550b57cec5SDimitry Andric       //   Resolve the region P containing a pointer
13560b57cec5SDimitry Andric       //   Dereference P to get the region R that the data should be stored in
13570b57cec5SDimitry Andric       //   Transfer a unit of type type(D) from D to R
13580b57cec5SDimitry Andric 
13590b57cec5SDimitry Andric       const Value *value_operand = store_inst->getValueOperand();
13600b57cec5SDimitry Andric       const Value *pointer_operand = store_inst->getPointerOperand();
13610b57cec5SDimitry Andric 
13620b57cec5SDimitry Andric       lldb::addr_t D = frame.ResolveValue(value_operand, module);
13630b57cec5SDimitry Andric       lldb::addr_t P = frame.ResolveValue(pointer_operand, module);
13640b57cec5SDimitry Andric 
13650b57cec5SDimitry Andric       if (D == LLDB_INVALID_ADDRESS) {
13669dba64beSDimitry Andric         LLDB_LOGF(log, "StoreInst's value doesn't resolve to anything");
13670b57cec5SDimitry Andric         error.SetErrorToGenericError();
13680b57cec5SDimitry Andric         error.SetErrorString(bad_value_error);
13690b57cec5SDimitry Andric         return false;
13700b57cec5SDimitry Andric       }
13710b57cec5SDimitry Andric 
13720b57cec5SDimitry Andric       if (P == LLDB_INVALID_ADDRESS) {
13739dba64beSDimitry Andric         LLDB_LOGF(log, "StoreInst's pointer doesn't resolve to anything");
13740b57cec5SDimitry Andric         error.SetErrorToGenericError();
13750b57cec5SDimitry Andric         error.SetErrorString(bad_value_error);
13760b57cec5SDimitry Andric         return false;
13770b57cec5SDimitry Andric       }
13780b57cec5SDimitry Andric 
13790b57cec5SDimitry Andric       lldb::addr_t R;
13800b57cec5SDimitry Andric       lldb_private::Status read_error;
13810b57cec5SDimitry Andric       execution_unit.ReadPointerFromMemory(&R, P, read_error);
13820b57cec5SDimitry Andric 
13830b57cec5SDimitry Andric       if (!read_error.Success()) {
13849dba64beSDimitry Andric         LLDB_LOGF(log, "Couldn't read the address to be loaded for a LoadInst");
13850b57cec5SDimitry Andric         error.SetErrorToGenericError();
13860b57cec5SDimitry Andric         error.SetErrorString(memory_read_error);
13870b57cec5SDimitry Andric         return false;
13880b57cec5SDimitry Andric       }
13890b57cec5SDimitry Andric 
139081ad6265SDimitry Andric       Type *target_ty = value_operand->getType();
13910b57cec5SDimitry Andric       size_t target_size = data_layout.getTypeStoreSize(target_ty);
13920b57cec5SDimitry Andric       lldb_private::DataBufferHeap buffer(target_size, 0);
13930b57cec5SDimitry Andric 
13940b57cec5SDimitry Andric       read_error.Clear();
13950b57cec5SDimitry Andric       execution_unit.ReadMemory(buffer.GetBytes(), D, buffer.GetByteSize(),
13960b57cec5SDimitry Andric                                 read_error);
13970b57cec5SDimitry Andric       if (!read_error.Success()) {
13989dba64beSDimitry Andric         LLDB_LOGF(log, "Couldn't read from a region on behalf of a StoreInst");
13990b57cec5SDimitry Andric         error.SetErrorToGenericError();
14000b57cec5SDimitry Andric         error.SetErrorString(memory_read_error);
14010b57cec5SDimitry Andric         return false;
14020b57cec5SDimitry Andric       }
14030b57cec5SDimitry Andric 
14040b57cec5SDimitry Andric       lldb_private::Status write_error;
14050b57cec5SDimitry Andric       execution_unit.WriteMemory(R, buffer.GetBytes(), buffer.GetByteSize(),
14060b57cec5SDimitry Andric                                  write_error);
14070b57cec5SDimitry Andric       if (!write_error.Success()) {
14089dba64beSDimitry Andric         LLDB_LOGF(log, "Couldn't write to a region on behalf of a StoreInst");
14090b57cec5SDimitry Andric         error.SetErrorToGenericError();
14100b57cec5SDimitry Andric         error.SetErrorString(memory_write_error);
14110b57cec5SDimitry Andric         return false;
14120b57cec5SDimitry Andric       }
14130b57cec5SDimitry Andric 
14140b57cec5SDimitry Andric       if (log) {
14159dba64beSDimitry Andric         LLDB_LOGF(log, "Interpreted a StoreInst");
14169dba64beSDimitry Andric         LLDB_LOGF(log, "  D : 0x%" PRIx64, D);
14179dba64beSDimitry Andric         LLDB_LOGF(log, "  P : 0x%" PRIx64, P);
14189dba64beSDimitry Andric         LLDB_LOGF(log, "  R : 0x%" PRIx64, R);
14190b57cec5SDimitry Andric       }
14200b57cec5SDimitry Andric     } break;
14210b57cec5SDimitry Andric     case Instruction::Call: {
1422480093f4SDimitry Andric       const CallInst *call_inst = cast<CallInst>(inst);
14230b57cec5SDimitry Andric 
14240b57cec5SDimitry Andric       if (CanIgnoreCall(call_inst))
14250b57cec5SDimitry Andric         break;
14260b57cec5SDimitry Andric 
14270b57cec5SDimitry Andric       // Get the return type
14280b57cec5SDimitry Andric       llvm::Type *returnType = call_inst->getType();
14290b57cec5SDimitry Andric       if (returnType == nullptr) {
14300b57cec5SDimitry Andric         error.SetErrorToGenericError();
14310b57cec5SDimitry Andric         error.SetErrorString("unable to access return type");
14320b57cec5SDimitry Andric         return false;
14330b57cec5SDimitry Andric       }
14340b57cec5SDimitry Andric 
14350b57cec5SDimitry Andric       // Work with void, integer and pointer return types
14360b57cec5SDimitry Andric       if (!returnType->isVoidTy() && !returnType->isIntegerTy() &&
14370b57cec5SDimitry Andric           !returnType->isPointerTy()) {
14380b57cec5SDimitry Andric         error.SetErrorToGenericError();
14390b57cec5SDimitry Andric         error.SetErrorString("return type is not supported");
14400b57cec5SDimitry Andric         return false;
14410b57cec5SDimitry Andric       }
14420b57cec5SDimitry Andric 
14430b57cec5SDimitry Andric       // Check we can actually get a thread
14440b57cec5SDimitry Andric       if (exe_ctx.GetThreadPtr() == nullptr) {
14450b57cec5SDimitry Andric         error.SetErrorToGenericError();
1446e8d8bef9SDimitry Andric         error.SetErrorString("unable to acquire thread");
14470b57cec5SDimitry Andric         return false;
14480b57cec5SDimitry Andric       }
14490b57cec5SDimitry Andric 
14500b57cec5SDimitry Andric       // Make sure we have a valid process
14515f757f3fSDimitry Andric       if (!process) {
14520b57cec5SDimitry Andric         error.SetErrorToGenericError();
1453e8d8bef9SDimitry Andric         error.SetErrorString("unable to get the process");
14540b57cec5SDimitry Andric         return false;
14550b57cec5SDimitry Andric       }
14560b57cec5SDimitry Andric 
14570b57cec5SDimitry Andric       // Find the address of the callee function
14580b57cec5SDimitry Andric       lldb_private::Scalar I;
14595ffd83dbSDimitry Andric       const llvm::Value *val = call_inst->getCalledOperand();
14600b57cec5SDimitry Andric 
14610b57cec5SDimitry Andric       if (!frame.EvaluateValue(I, val, module)) {
14620b57cec5SDimitry Andric         error.SetErrorToGenericError();
14630b57cec5SDimitry Andric         error.SetErrorString("unable to get address of function");
14640b57cec5SDimitry Andric         return false;
14650b57cec5SDimitry Andric       }
14660b57cec5SDimitry Andric       lldb_private::Address funcAddr(I.ULongLong(LLDB_INVALID_ADDRESS));
14670b57cec5SDimitry Andric 
14680b57cec5SDimitry Andric       lldb_private::DiagnosticManager diagnostics;
14690b57cec5SDimitry Andric       lldb_private::EvaluateExpressionOptions options;
14700b57cec5SDimitry Andric 
147181ad6265SDimitry Andric       llvm::FunctionType *prototype = call_inst->getFunctionType();
14720b57cec5SDimitry Andric 
14730b57cec5SDimitry Andric       // Find number of arguments
1474349cc55cSDimitry Andric       const int numArgs = call_inst->arg_size();
14750b57cec5SDimitry Andric 
14760b57cec5SDimitry Andric       // We work with a fixed array of 16 arguments which is our upper limit
14770b57cec5SDimitry Andric       static lldb_private::ABI::CallArgument rawArgs[16];
14780b57cec5SDimitry Andric       if (numArgs >= 16) {
14790b57cec5SDimitry Andric         error.SetErrorToGenericError();
1480e8d8bef9SDimitry Andric         error.SetErrorString("function takes too many arguments");
14810b57cec5SDimitry Andric         return false;
14820b57cec5SDimitry Andric       }
14830b57cec5SDimitry Andric 
14840b57cec5SDimitry Andric       // Push all function arguments to the argument list that will be passed
14850b57cec5SDimitry Andric       // to the call function thread plan
14860b57cec5SDimitry Andric       for (int i = 0; i < numArgs; i++) {
14870b57cec5SDimitry Andric         // Get details of this argument
14880b57cec5SDimitry Andric         llvm::Value *arg_op = call_inst->getArgOperand(i);
14890b57cec5SDimitry Andric         llvm::Type *arg_ty = arg_op->getType();
14900b57cec5SDimitry Andric 
14910b57cec5SDimitry Andric         // Ensure that this argument is an supported type
14920b57cec5SDimitry Andric         if (!arg_ty->isIntegerTy() && !arg_ty->isPointerTy()) {
14930b57cec5SDimitry Andric           error.SetErrorToGenericError();
14940b57cec5SDimitry Andric           error.SetErrorStringWithFormat("argument %d must be integer type", i);
14950b57cec5SDimitry Andric           return false;
14960b57cec5SDimitry Andric         }
14970b57cec5SDimitry Andric 
14980b57cec5SDimitry Andric         // Extract the arguments value
14990b57cec5SDimitry Andric         lldb_private::Scalar tmp_op = 0;
15000b57cec5SDimitry Andric         if (!frame.EvaluateValue(tmp_op, arg_op, module)) {
15010b57cec5SDimitry Andric           error.SetErrorToGenericError();
15020b57cec5SDimitry Andric           error.SetErrorStringWithFormat("unable to evaluate argument %d", i);
15030b57cec5SDimitry Andric           return false;
15040b57cec5SDimitry Andric         }
15050b57cec5SDimitry Andric 
15060b57cec5SDimitry Andric         // Check if this is a string literal or constant string pointer
15070b57cec5SDimitry Andric         if (arg_ty->isPointerTy()) {
15080b57cec5SDimitry Andric           lldb::addr_t addr = tmp_op.ULongLong();
15090b57cec5SDimitry Andric           size_t dataSize = 0;
15100b57cec5SDimitry Andric 
15110b57cec5SDimitry Andric           bool Success = execution_unit.GetAllocSize(addr, dataSize);
15125f757f3fSDimitry Andric           UNUSED_IF_ASSERT_DISABLED(Success);
15130b57cec5SDimitry Andric           assert(Success &&
15140b57cec5SDimitry Andric                  "unable to locate host data for transfer to device");
15150b57cec5SDimitry Andric           // Create the required buffer
15160b57cec5SDimitry Andric           rawArgs[i].size = dataSize;
15170b57cec5SDimitry Andric           rawArgs[i].data_up.reset(new uint8_t[dataSize + 1]);
15180b57cec5SDimitry Andric 
15190b57cec5SDimitry Andric           // Read string from host memory
15200b57cec5SDimitry Andric           execution_unit.ReadMemory(rawArgs[i].data_up.get(), addr, dataSize,
15210b57cec5SDimitry Andric                                     error);
15220b57cec5SDimitry Andric           assert(!error.Fail() &&
15230b57cec5SDimitry Andric                  "we have failed to read the string from memory");
15240b57cec5SDimitry Andric 
15250b57cec5SDimitry Andric           // Add null terminator
15260b57cec5SDimitry Andric           rawArgs[i].data_up[dataSize] = '\0';
15270b57cec5SDimitry Andric           rawArgs[i].type = lldb_private::ABI::CallArgument::HostPointer;
15280b57cec5SDimitry Andric         } else /* if ( arg_ty->isPointerTy() ) */
15290b57cec5SDimitry Andric         {
15300b57cec5SDimitry Andric           rawArgs[i].type = lldb_private::ABI::CallArgument::TargetValue;
15310b57cec5SDimitry Andric           // Get argument size in bytes
15320b57cec5SDimitry Andric           rawArgs[i].size = arg_ty->getIntegerBitWidth() / 8;
15330b57cec5SDimitry Andric           // Push value into argument list for thread plan
15340b57cec5SDimitry Andric           rawArgs[i].value = tmp_op.ULongLong();
15350b57cec5SDimitry Andric         }
15360b57cec5SDimitry Andric       }
15370b57cec5SDimitry Andric 
15380b57cec5SDimitry Andric       // Pack the arguments into an llvm::array
15390b57cec5SDimitry Andric       llvm::ArrayRef<lldb_private::ABI::CallArgument> args(rawArgs, numArgs);
15400b57cec5SDimitry Andric 
15410b57cec5SDimitry Andric       // Setup a thread plan to call the target function
15420b57cec5SDimitry Andric       lldb::ThreadPlanSP call_plan_sp(
15430b57cec5SDimitry Andric           new lldb_private::ThreadPlanCallFunctionUsingABI(
15440b57cec5SDimitry Andric               exe_ctx.GetThreadRef(), funcAddr, *prototype, *returnType, args,
15450b57cec5SDimitry Andric               options));
15460b57cec5SDimitry Andric 
15470b57cec5SDimitry Andric       // Check if the plan is valid
15480b57cec5SDimitry Andric       lldb_private::StreamString ss;
15490b57cec5SDimitry Andric       if (!call_plan_sp || !call_plan_sp->ValidatePlan(&ss)) {
15500b57cec5SDimitry Andric         error.SetErrorToGenericError();
15510b57cec5SDimitry Andric         error.SetErrorStringWithFormat(
15520b57cec5SDimitry Andric             "unable to make ThreadPlanCallFunctionUsingABI for 0x%llx",
15530b57cec5SDimitry Andric             I.ULongLong());
15540b57cec5SDimitry Andric         return false;
15550b57cec5SDimitry Andric       }
15560b57cec5SDimitry Andric 
15575f757f3fSDimitry Andric       process->SetRunningUserExpression(true);
15580b57cec5SDimitry Andric 
15590b57cec5SDimitry Andric       // Execute the actual function call thread plan
15605f757f3fSDimitry Andric       lldb::ExpressionResults res =
15615f757f3fSDimitry Andric           process->RunThreadPlan(exe_ctx, call_plan_sp, options, diagnostics);
15620b57cec5SDimitry Andric 
15630b57cec5SDimitry Andric       // Check that the thread plan completed successfully
15640b57cec5SDimitry Andric       if (res != lldb::ExpressionResults::eExpressionCompleted) {
15650b57cec5SDimitry Andric         error.SetErrorToGenericError();
1566e8d8bef9SDimitry Andric         error.SetErrorString("ThreadPlanCallFunctionUsingABI failed");
15670b57cec5SDimitry Andric         return false;
15680b57cec5SDimitry Andric       }
15690b57cec5SDimitry Andric 
15705f757f3fSDimitry Andric       process->SetRunningUserExpression(false);
15710b57cec5SDimitry Andric 
15720b57cec5SDimitry Andric       // Void return type
15730b57cec5SDimitry Andric       if (returnType->isVoidTy()) {
15740b57cec5SDimitry Andric         // Cant assign to void types, so we leave the frame untouched
15750b57cec5SDimitry Andric       } else
15760b57cec5SDimitry Andric           // Integer or pointer return type
15770b57cec5SDimitry Andric           if (returnType->isIntegerTy() || returnType->isPointerTy()) {
15780b57cec5SDimitry Andric         // Get the encapsulated return value
15790b57cec5SDimitry Andric         lldb::ValueObjectSP retVal = call_plan_sp.get()->GetReturnValueObject();
15800b57cec5SDimitry Andric 
15810b57cec5SDimitry Andric         lldb_private::Scalar returnVal = -1;
15820b57cec5SDimitry Andric         lldb_private::ValueObject *vobj = retVal.get();
15830b57cec5SDimitry Andric 
15840b57cec5SDimitry Andric         // Check if the return value is valid
15855ffd83dbSDimitry Andric         if (vobj == nullptr || !retVal) {
15860b57cec5SDimitry Andric           error.SetErrorToGenericError();
1587e8d8bef9SDimitry Andric           error.SetErrorString("unable to get the return value");
15880b57cec5SDimitry Andric           return false;
15890b57cec5SDimitry Andric         }
15900b57cec5SDimitry Andric 
15910b57cec5SDimitry Andric         // Extract the return value as a integer
15920b57cec5SDimitry Andric         lldb_private::Value &value = vobj->GetValue();
15930b57cec5SDimitry Andric         returnVal = value.GetScalar();
15940b57cec5SDimitry Andric 
15950b57cec5SDimitry Andric         // Push the return value as the result
15960b57cec5SDimitry Andric         frame.AssignValue(inst, returnVal, module);
15970b57cec5SDimitry Andric       }
15980b57cec5SDimitry Andric     } break;
15990b57cec5SDimitry Andric     }
16000b57cec5SDimitry Andric 
16010b57cec5SDimitry Andric     ++frame.m_ii;
16020b57cec5SDimitry Andric   }
16030b57cec5SDimitry Andric 
16040b57cec5SDimitry Andric   return false;
16050b57cec5SDimitry Andric }
1606