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