15ffd83dbSDimitry Andric //===-- IRForTarget.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 "IRForTarget.h" 100b57cec5SDimitry Andric 110b57cec5SDimitry Andric #include "ClangExpressionDeclMap.h" 125ffd83dbSDimitry Andric #include "ClangUtil.h" 130b57cec5SDimitry Andric 145ffd83dbSDimitry Andric #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" 150b57cec5SDimitry Andric #include "llvm/IR/Constants.h" 160b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h" 17fe6060f1SDimitry Andric #include "llvm/IR/Operator.h" 180b57cec5SDimitry Andric #include "llvm/IR/InstrTypes.h" 190b57cec5SDimitry Andric #include "llvm/IR/Instructions.h" 200b57cec5SDimitry Andric #include "llvm/IR/Intrinsics.h" 210b57cec5SDimitry Andric #include "llvm/IR/LegacyPassManager.h" 220b57cec5SDimitry Andric #include "llvm/IR/Metadata.h" 230b57cec5SDimitry Andric #include "llvm/IR/Module.h" 240b57cec5SDimitry Andric #include "llvm/IR/ValueSymbolTable.h" 250b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 260b57cec5SDimitry Andric #include "llvm/Transforms/IPO.h" 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric #include "clang/AST/ASTContext.h" 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric #include "lldb/Core/dwarf.h" 310b57cec5SDimitry Andric #include "lldb/Expression/IRExecutionUnit.h" 320b57cec5SDimitry Andric #include "lldb/Expression/IRInterpreter.h" 330b57cec5SDimitry Andric #include "lldb/Symbol/CompilerType.h" 340b57cec5SDimitry Andric #include "lldb/Utility/ConstString.h" 350b57cec5SDimitry Andric #include "lldb/Utility/DataBufferHeap.h" 360b57cec5SDimitry Andric #include "lldb/Utility/Endian.h" 3781ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h" 380b57cec5SDimitry Andric #include "lldb/Utility/Log.h" 390b57cec5SDimitry Andric #include "lldb/Utility/Scalar.h" 400b57cec5SDimitry Andric #include "lldb/Utility/StreamString.h" 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric #include <map> 43bdd1243dSDimitry Andric #include <optional> 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric using namespace llvm; 4681ad6265SDimitry Andric using lldb_private::LLDBLog; 470b57cec5SDimitry Andric 489dba64beSDimitry Andric typedef SmallVector<Instruction *, 2> InstrList; 499dba64beSDimitry Andric 500b57cec5SDimitry Andric IRForTarget::FunctionValueCache::FunctionValueCache(Maker const &maker) 510b57cec5SDimitry Andric : m_maker(maker), m_values() {} 520b57cec5SDimitry Andric 53fe6060f1SDimitry Andric IRForTarget::FunctionValueCache::~FunctionValueCache() = default; 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric llvm::Value * 560b57cec5SDimitry Andric IRForTarget::FunctionValueCache::GetValue(llvm::Function *function) { 570b57cec5SDimitry Andric if (!m_values.count(function)) { 580b57cec5SDimitry Andric llvm::Value *ret = m_maker(function); 590b57cec5SDimitry Andric m_values[function] = ret; 600b57cec5SDimitry Andric return ret; 610b57cec5SDimitry Andric } 620b57cec5SDimitry Andric return m_values[function]; 630b57cec5SDimitry Andric } 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric static llvm::Value *FindEntryInstruction(llvm::Function *function) { 660b57cec5SDimitry Andric if (function->empty()) 670b57cec5SDimitry Andric return nullptr; 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric return function->getEntryBlock().getFirstNonPHIOrDbg(); 700b57cec5SDimitry Andric } 710b57cec5SDimitry Andric 720b57cec5SDimitry Andric IRForTarget::IRForTarget(lldb_private::ClangExpressionDeclMap *decl_map, 730b57cec5SDimitry Andric bool resolve_vars, 740b57cec5SDimitry Andric lldb_private::IRExecutionUnit &execution_unit, 750b57cec5SDimitry Andric lldb_private::Stream &error_stream, 760b57cec5SDimitry Andric const char *func_name) 77fe6060f1SDimitry Andric : m_resolve_vars(resolve_vars), m_func_name(func_name), 78fe6060f1SDimitry Andric m_decl_map(decl_map), m_error_stream(error_stream), 79fe6060f1SDimitry Andric m_execution_unit(execution_unit), 800b57cec5SDimitry Andric m_entry_instruction_finder(FindEntryInstruction) {} 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric /* Handy utility functions used at several places in the code */ 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric static std::string PrintValue(const Value *value, bool truncate = false) { 850b57cec5SDimitry Andric std::string s; 860b57cec5SDimitry Andric if (value) { 870b57cec5SDimitry Andric raw_string_ostream rso(s); 880b57cec5SDimitry Andric value->print(rso); 890b57cec5SDimitry Andric rso.flush(); 900b57cec5SDimitry Andric if (truncate) 910b57cec5SDimitry Andric s.resize(s.length() - 1); 920b57cec5SDimitry Andric } 930b57cec5SDimitry Andric return s; 940b57cec5SDimitry Andric } 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric static std::string PrintType(const llvm::Type *type, bool truncate = false) { 970b57cec5SDimitry Andric std::string s; 980b57cec5SDimitry Andric raw_string_ostream rso(s); 990b57cec5SDimitry Andric type->print(rso); 1000b57cec5SDimitry Andric rso.flush(); 1010b57cec5SDimitry Andric if (truncate) 1020b57cec5SDimitry Andric s.resize(s.length() - 1); 1030b57cec5SDimitry Andric return s; 1040b57cec5SDimitry Andric } 1050b57cec5SDimitry Andric 1060b57cec5SDimitry Andric bool IRForTarget::FixFunctionLinkage(llvm::Function &llvm_function) { 1070b57cec5SDimitry Andric llvm_function.setLinkage(GlobalValue::ExternalLinkage); 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric return true; 1100b57cec5SDimitry Andric } 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric clang::NamedDecl *IRForTarget::DeclForGlobal(const GlobalValue *global_val, 1130b57cec5SDimitry Andric Module *module) { 1140b57cec5SDimitry Andric NamedMDNode *named_metadata = 1150b57cec5SDimitry Andric module->getNamedMetadata("clang.global.decl.ptrs"); 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric if (!named_metadata) 1180b57cec5SDimitry Andric return nullptr; 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric unsigned num_nodes = named_metadata->getNumOperands(); 1210b57cec5SDimitry Andric unsigned node_index; 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric for (node_index = 0; node_index < num_nodes; ++node_index) { 1240b57cec5SDimitry Andric llvm::MDNode *metadata_node = 1250b57cec5SDimitry Andric dyn_cast<llvm::MDNode>(named_metadata->getOperand(node_index)); 1260b57cec5SDimitry Andric if (!metadata_node) 1270b57cec5SDimitry Andric return nullptr; 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric if (metadata_node->getNumOperands() != 2) 1300b57cec5SDimitry Andric continue; 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric if (mdconst::dyn_extract_or_null<GlobalValue>( 1330b57cec5SDimitry Andric metadata_node->getOperand(0)) != global_val) 1340b57cec5SDimitry Andric continue; 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric ConstantInt *constant_int = 1370b57cec5SDimitry Andric mdconst::dyn_extract<ConstantInt>(metadata_node->getOperand(1)); 1380b57cec5SDimitry Andric 1390b57cec5SDimitry Andric if (!constant_int) 1400b57cec5SDimitry Andric return nullptr; 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric uintptr_t ptr = constant_int->getZExtValue(); 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric return reinterpret_cast<clang::NamedDecl *>(ptr); 1450b57cec5SDimitry Andric } 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric return nullptr; 1480b57cec5SDimitry Andric } 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric clang::NamedDecl *IRForTarget::DeclForGlobal(GlobalValue *global_val) { 1510b57cec5SDimitry Andric return DeclForGlobal(global_val, m_module); 1520b57cec5SDimitry Andric } 1530b57cec5SDimitry Andric 1549dba64beSDimitry Andric /// Returns true iff the mangled symbol is for a static guard variable. 1559dba64beSDimitry Andric static bool isGuardVariableSymbol(llvm::StringRef mangled_symbol, 1569dba64beSDimitry Andric bool check_ms_abi = true) { 1575f757f3fSDimitry Andric bool result = 1585f757f3fSDimitry Andric mangled_symbol.starts_with("_ZGV"); // Itanium ABI guard variable 1599dba64beSDimitry Andric if (check_ms_abi) 1605f757f3fSDimitry Andric result |= mangled_symbol.ends_with("@4IA"); // Microsoft ABI 1619dba64beSDimitry Andric return result; 1629dba64beSDimitry Andric } 1639dba64beSDimitry Andric 1640b57cec5SDimitry Andric bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) { 16581ad6265SDimitry Andric lldb_private::Log *log(GetLog(LLDBLog::Expressions)); 1660b57cec5SDimitry Andric 1670b57cec5SDimitry Andric if (!m_resolve_vars) 1680b57cec5SDimitry Andric return true; 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric // Find the result variable. If it doesn't exist, we can give up right here. 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric ValueSymbolTable &value_symbol_table = m_module->getValueSymbolTable(); 1730b57cec5SDimitry Andric 1749dba64beSDimitry Andric llvm::StringRef result_name; 1759dba64beSDimitry Andric bool found_result = false; 1760b57cec5SDimitry Andric 1779dba64beSDimitry Andric for (StringMapEntry<llvm::Value *> &value_symbol : value_symbol_table) { 1789dba64beSDimitry Andric result_name = value_symbol.first(); 1790b57cec5SDimitry Andric 1809dba64beSDimitry Andric // Check if this is a guard variable. It seems this causes some hiccups 1819dba64beSDimitry Andric // on Windows, so let's only check for Itanium guard variables. 1829dba64beSDimitry Andric bool is_guard_var = isGuardVariableSymbol(result_name, /*MS ABI*/ false); 1839dba64beSDimitry Andric 1849dba64beSDimitry Andric if (result_name.contains("$__lldb_expr_result_ptr") && !is_guard_var) { 1859dba64beSDimitry Andric found_result = true; 1860b57cec5SDimitry Andric m_result_is_pointer = true; 1870b57cec5SDimitry Andric break; 1880b57cec5SDimitry Andric } 1890b57cec5SDimitry Andric 1909dba64beSDimitry Andric if (result_name.contains("$__lldb_expr_result") && !is_guard_var) { 1919dba64beSDimitry Andric found_result = true; 1920b57cec5SDimitry Andric m_result_is_pointer = false; 1930b57cec5SDimitry Andric break; 1940b57cec5SDimitry Andric } 1950b57cec5SDimitry Andric } 1960b57cec5SDimitry Andric 1979dba64beSDimitry Andric if (!found_result) { 1989dba64beSDimitry Andric LLDB_LOG(log, "Couldn't find result variable"); 1990b57cec5SDimitry Andric 2000b57cec5SDimitry Andric return true; 2010b57cec5SDimitry Andric } 2020b57cec5SDimitry Andric 2039dba64beSDimitry Andric LLDB_LOG(log, "Result name: \"{0}\"", result_name); 2040b57cec5SDimitry Andric 2050b57cec5SDimitry Andric Value *result_value = m_module->getNamedValue(result_name); 2060b57cec5SDimitry Andric 2070b57cec5SDimitry Andric if (!result_value) { 2089dba64beSDimitry Andric LLDB_LOG(log, "Result variable had no data"); 2090b57cec5SDimitry Andric 2109dba64beSDimitry Andric m_error_stream.Format("Internal error [IRForTarget]: Result variable's " 2119dba64beSDimitry Andric "name ({0}) exists, but not its definition\n", 2120b57cec5SDimitry Andric result_name); 2130b57cec5SDimitry Andric 2140b57cec5SDimitry Andric return false; 2150b57cec5SDimitry Andric } 2160b57cec5SDimitry Andric 2179dba64beSDimitry Andric LLDB_LOG(log, "Found result in the IR: \"{0}\"", 2189dba64beSDimitry Andric PrintValue(result_value, false)); 2190b57cec5SDimitry Andric 2200b57cec5SDimitry Andric GlobalVariable *result_global = dyn_cast<GlobalVariable>(result_value); 2210b57cec5SDimitry Andric 2220b57cec5SDimitry Andric if (!result_global) { 2239dba64beSDimitry Andric LLDB_LOG(log, "Result variable isn't a GlobalVariable"); 2240b57cec5SDimitry Andric 2259dba64beSDimitry Andric m_error_stream.Format("Internal error [IRForTarget]: Result variable ({0}) " 2260b57cec5SDimitry Andric "is defined, but is not a global variable\n", 2270b57cec5SDimitry Andric result_name); 2280b57cec5SDimitry Andric 2290b57cec5SDimitry Andric return false; 2300b57cec5SDimitry Andric } 2310b57cec5SDimitry Andric 2320b57cec5SDimitry Andric clang::NamedDecl *result_decl = DeclForGlobal(result_global); 2330b57cec5SDimitry Andric if (!result_decl) { 2349dba64beSDimitry Andric LLDB_LOG(log, "Result variable doesn't have a corresponding Decl"); 2350b57cec5SDimitry Andric 2369dba64beSDimitry Andric m_error_stream.Format("Internal error [IRForTarget]: Result variable ({0}) " 2370b57cec5SDimitry Andric "does not have a corresponding Clang entity\n", 2380b57cec5SDimitry Andric result_name); 2390b57cec5SDimitry Andric 2400b57cec5SDimitry Andric return false; 2410b57cec5SDimitry Andric } 2420b57cec5SDimitry Andric 2430b57cec5SDimitry Andric if (log) { 2440b57cec5SDimitry Andric std::string decl_desc_str; 2450b57cec5SDimitry Andric raw_string_ostream decl_desc_stream(decl_desc_str); 2460b57cec5SDimitry Andric result_decl->print(decl_desc_stream); 2470b57cec5SDimitry Andric decl_desc_stream.flush(); 2480b57cec5SDimitry Andric 2499dba64beSDimitry Andric LLDB_LOG(log, "Found result decl: \"{0}\"", decl_desc_str); 2500b57cec5SDimitry Andric } 2510b57cec5SDimitry Andric 2520b57cec5SDimitry Andric clang::VarDecl *result_var = dyn_cast<clang::VarDecl>(result_decl); 2530b57cec5SDimitry Andric if (!result_var) { 2549dba64beSDimitry Andric LLDB_LOG(log, "Result variable Decl isn't a VarDecl"); 2550b57cec5SDimitry Andric 2569dba64beSDimitry Andric m_error_stream.Format("Internal error [IRForTarget]: Result variable " 2579dba64beSDimitry Andric "({0})'s corresponding Clang entity isn't a " 2580b57cec5SDimitry Andric "variable\n", 2590b57cec5SDimitry Andric result_name); 2600b57cec5SDimitry Andric 2610b57cec5SDimitry Andric return false; 2620b57cec5SDimitry Andric } 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric // Get the next available result name from m_decl_map and create the 2650b57cec5SDimitry Andric // persistent variable for it 2660b57cec5SDimitry Andric 2670b57cec5SDimitry Andric // If the result is an Lvalue, it is emitted as a pointer; see 2680b57cec5SDimitry Andric // ASTResultSynthesizer::SynthesizeBodyResult. 2690b57cec5SDimitry Andric if (m_result_is_pointer) { 2700b57cec5SDimitry Andric clang::QualType pointer_qual_type = result_var->getType(); 2710b57cec5SDimitry Andric const clang::Type *pointer_type = pointer_qual_type.getTypePtr(); 2720b57cec5SDimitry Andric 2730b57cec5SDimitry Andric const clang::PointerType *pointer_pointertype = 2740b57cec5SDimitry Andric pointer_type->getAs<clang::PointerType>(); 2750b57cec5SDimitry Andric const clang::ObjCObjectPointerType *pointer_objcobjpointertype = 2760b57cec5SDimitry Andric pointer_type->getAs<clang::ObjCObjectPointerType>(); 2770b57cec5SDimitry Andric 2780b57cec5SDimitry Andric if (pointer_pointertype) { 2790b57cec5SDimitry Andric clang::QualType element_qual_type = pointer_pointertype->getPointeeType(); 2800b57cec5SDimitry Andric 2810b57cec5SDimitry Andric m_result_type = lldb_private::TypeFromParser( 2825ffd83dbSDimitry Andric m_decl_map->GetTypeSystem()->GetType(element_qual_type)); 2830b57cec5SDimitry Andric } else if (pointer_objcobjpointertype) { 2840b57cec5SDimitry Andric clang::QualType element_qual_type = 2850b57cec5SDimitry Andric clang::QualType(pointer_objcobjpointertype->getObjectType(), 0); 2860b57cec5SDimitry Andric 2870b57cec5SDimitry Andric m_result_type = lldb_private::TypeFromParser( 2885ffd83dbSDimitry Andric m_decl_map->GetTypeSystem()->GetType(element_qual_type)); 2890b57cec5SDimitry Andric } else { 2909dba64beSDimitry Andric LLDB_LOG(log, "Expected result to have pointer type, but it did not"); 2910b57cec5SDimitry Andric 2929dba64beSDimitry Andric m_error_stream.Format("Internal error [IRForTarget]: Lvalue result ({0}) " 2930b57cec5SDimitry Andric "is not a pointer variable\n", 2940b57cec5SDimitry Andric result_name); 2950b57cec5SDimitry Andric 2960b57cec5SDimitry Andric return false; 2970b57cec5SDimitry Andric } 2980b57cec5SDimitry Andric } else { 2990b57cec5SDimitry Andric m_result_type = lldb_private::TypeFromParser( 3005ffd83dbSDimitry Andric m_decl_map->GetTypeSystem()->GetType(result_var->getType())); 3010b57cec5SDimitry Andric } 3020b57cec5SDimitry Andric 3030b57cec5SDimitry Andric lldb::TargetSP target_sp(m_execution_unit.GetTarget()); 304bdd1243dSDimitry Andric std::optional<uint64_t> bit_size = m_result_type.GetBitSize(target_sp.get()); 3050b57cec5SDimitry Andric if (!bit_size) { 3060b57cec5SDimitry Andric lldb_private::StreamString type_desc_stream; 3070b57cec5SDimitry Andric m_result_type.DumpTypeDescription(&type_desc_stream); 3080b57cec5SDimitry Andric 3099dba64beSDimitry Andric LLDB_LOG(log, "Result type has unknown size"); 3100b57cec5SDimitry Andric 3110b57cec5SDimitry Andric m_error_stream.Printf("Error [IRForTarget]: Size of result type '%s' " 3120b57cec5SDimitry Andric "couldn't be determined\n", 3130b57cec5SDimitry Andric type_desc_stream.GetData()); 3140b57cec5SDimitry Andric return false; 3150b57cec5SDimitry Andric } 3160b57cec5SDimitry Andric 3170b57cec5SDimitry Andric if (log) { 3180b57cec5SDimitry Andric lldb_private::StreamString type_desc_stream; 3190b57cec5SDimitry Andric m_result_type.DumpTypeDescription(&type_desc_stream); 3200b57cec5SDimitry Andric 3219dba64beSDimitry Andric LLDB_LOG(log, "Result decl type: \"{0}\"", type_desc_stream.GetData()); 3220b57cec5SDimitry Andric } 3230b57cec5SDimitry Andric 3240b57cec5SDimitry Andric m_result_name = lldb_private::ConstString("$RESULT_NAME"); 3250b57cec5SDimitry Andric 3269dba64beSDimitry Andric LLDB_LOG(log, "Creating a new result global: \"{0}\" with size {1}", 327e8d8bef9SDimitry Andric m_result_name, 32881ad6265SDimitry Andric m_result_type.GetByteSize(target_sp.get()).value_or(0)); 3290b57cec5SDimitry Andric 3300b57cec5SDimitry Andric // Construct a new result global and set up its metadata 3310b57cec5SDimitry Andric 3320b57cec5SDimitry Andric GlobalVariable *new_result_global = new GlobalVariable( 33381ad6265SDimitry Andric (*m_module), result_global->getValueType(), false, /* not constant */ 3340b57cec5SDimitry Andric GlobalValue::ExternalLinkage, nullptr, /* no initializer */ 3350b57cec5SDimitry Andric m_result_name.GetCString()); 3360b57cec5SDimitry Andric 3370b57cec5SDimitry Andric // It's too late in compilation to create a new VarDecl for this, but we 3380b57cec5SDimitry Andric // don't need to. We point the metadata at the old VarDecl. This creates an 3390b57cec5SDimitry Andric // odd anomaly: a variable with a Value whose name is something like $0 and a 3400b57cec5SDimitry Andric // Decl whose name is $__lldb_expr_result. This condition is handled in 3410b57cec5SDimitry Andric // ClangExpressionDeclMap::DoMaterialize, and the name of the variable is 3420b57cec5SDimitry Andric // fixed up. 3430b57cec5SDimitry Andric 3440b57cec5SDimitry Andric ConstantInt *new_constant_int = 3450b57cec5SDimitry Andric ConstantInt::get(llvm::Type::getInt64Ty(m_module->getContext()), 346480093f4SDimitry Andric reinterpret_cast<uintptr_t>(result_decl), false); 3470b57cec5SDimitry Andric 3480b57cec5SDimitry Andric llvm::Metadata *values[2]; 3490b57cec5SDimitry Andric values[0] = ConstantAsMetadata::get(new_result_global); 3500b57cec5SDimitry Andric values[1] = ConstantAsMetadata::get(new_constant_int); 3510b57cec5SDimitry Andric 3520b57cec5SDimitry Andric ArrayRef<Metadata *> value_ref(values, 2); 3530b57cec5SDimitry Andric 3540b57cec5SDimitry Andric MDNode *persistent_global_md = MDNode::get(m_module->getContext(), value_ref); 3550b57cec5SDimitry Andric NamedMDNode *named_metadata = 3560b57cec5SDimitry Andric m_module->getNamedMetadata("clang.global.decl.ptrs"); 3570b57cec5SDimitry Andric named_metadata->addOperand(persistent_global_md); 3580b57cec5SDimitry Andric 3599dba64beSDimitry Andric LLDB_LOG(log, "Replacing \"{0}\" with \"{1}\"", PrintValue(result_global), 3609dba64beSDimitry Andric PrintValue(new_result_global)); 3610b57cec5SDimitry Andric 3620b57cec5SDimitry Andric if (result_global->use_empty()) { 3630b57cec5SDimitry Andric // We need to synthesize a store for this variable, because otherwise 3640b57cec5SDimitry Andric // there's nothing to put into its equivalent persistent variable. 3650b57cec5SDimitry Andric 3660b57cec5SDimitry Andric BasicBlock &entry_block(llvm_function.getEntryBlock()); 3670b57cec5SDimitry Andric Instruction *first_entry_instruction(entry_block.getFirstNonPHIOrDbg()); 3680b57cec5SDimitry Andric 3690b57cec5SDimitry Andric if (!first_entry_instruction) 3700b57cec5SDimitry Andric return false; 3710b57cec5SDimitry Andric 3720b57cec5SDimitry Andric if (!result_global->hasInitializer()) { 3739dba64beSDimitry Andric LLDB_LOG(log, "Couldn't find initializer for unused variable"); 3740b57cec5SDimitry Andric 3759dba64beSDimitry Andric m_error_stream.Format("Internal error [IRForTarget]: Result variable " 3769dba64beSDimitry Andric "({0}) has no writes and no initializer\n", 3770b57cec5SDimitry Andric result_name); 3780b57cec5SDimitry Andric 3790b57cec5SDimitry Andric return false; 3800b57cec5SDimitry Andric } 3810b57cec5SDimitry Andric 3820b57cec5SDimitry Andric Constant *initializer = result_global->getInitializer(); 3830b57cec5SDimitry Andric 3840b57cec5SDimitry Andric StoreInst *synthesized_store = 3850b57cec5SDimitry Andric new StoreInst(initializer, new_result_global, first_entry_instruction); 3860b57cec5SDimitry Andric 3879dba64beSDimitry Andric LLDB_LOG(log, "Synthesized result store \"{0}\"\n", 3889dba64beSDimitry Andric PrintValue(synthesized_store)); 3890b57cec5SDimitry Andric } else { 3900b57cec5SDimitry Andric result_global->replaceAllUsesWith(new_result_global); 3910b57cec5SDimitry Andric } 3920b57cec5SDimitry Andric 3930b57cec5SDimitry Andric if (!m_decl_map->AddPersistentVariable( 3940b57cec5SDimitry Andric result_decl, m_result_name, m_result_type, true, m_result_is_pointer)) 3950b57cec5SDimitry Andric return false; 3960b57cec5SDimitry Andric 3970b57cec5SDimitry Andric result_global->eraseFromParent(); 3980b57cec5SDimitry Andric 3990b57cec5SDimitry Andric return true; 4000b57cec5SDimitry Andric } 4010b57cec5SDimitry Andric 4020b57cec5SDimitry Andric bool IRForTarget::RewriteObjCConstString(llvm::GlobalVariable *ns_str, 4030b57cec5SDimitry Andric llvm::GlobalVariable *cstr) { 40481ad6265SDimitry Andric lldb_private::Log *log(GetLog(LLDBLog::Expressions)); 4050b57cec5SDimitry Andric 4060b57cec5SDimitry Andric Type *ns_str_ty = ns_str->getType(); 4070b57cec5SDimitry Andric 4085f757f3fSDimitry Andric Type *i8_ptr_ty = PointerType::getUnqual(m_module->getContext()); 4090b57cec5SDimitry Andric Type *i32_ty = Type::getInt32Ty(m_module->getContext()); 4100b57cec5SDimitry Andric Type *i8_ty = Type::getInt8Ty(m_module->getContext()); 4110b57cec5SDimitry Andric 4120b57cec5SDimitry Andric if (!m_CFStringCreateWithBytes) { 4130b57cec5SDimitry Andric lldb::addr_t CFStringCreateWithBytes_addr; 4140b57cec5SDimitry Andric 4150b57cec5SDimitry Andric static lldb_private::ConstString g_CFStringCreateWithBytes_str( 4160b57cec5SDimitry Andric "CFStringCreateWithBytes"); 4170b57cec5SDimitry Andric 4180b57cec5SDimitry Andric bool missing_weak = false; 4190b57cec5SDimitry Andric CFStringCreateWithBytes_addr = 4200b57cec5SDimitry Andric m_execution_unit.FindSymbol(g_CFStringCreateWithBytes_str, 4210b57cec5SDimitry Andric missing_weak); 4220b57cec5SDimitry Andric if (CFStringCreateWithBytes_addr == LLDB_INVALID_ADDRESS || missing_weak) { 4235ffd83dbSDimitry Andric LLDB_LOG(log, "Couldn't find CFStringCreateWithBytes in the target"); 4240b57cec5SDimitry Andric 4250b57cec5SDimitry Andric m_error_stream.Printf("Error [IRForTarget]: Rewriting an Objective-C " 4260b57cec5SDimitry Andric "constant string requires " 4270b57cec5SDimitry Andric "CFStringCreateWithBytes\n"); 4280b57cec5SDimitry Andric 4290b57cec5SDimitry Andric return false; 4300b57cec5SDimitry Andric } 4310b57cec5SDimitry Andric 4329dba64beSDimitry Andric LLDB_LOG(log, "Found CFStringCreateWithBytes at {0}", 4330b57cec5SDimitry Andric CFStringCreateWithBytes_addr); 4340b57cec5SDimitry Andric 4350b57cec5SDimitry Andric // Build the function type: 4360b57cec5SDimitry Andric // 4370b57cec5SDimitry Andric // CFStringRef CFStringCreateWithBytes ( 4380b57cec5SDimitry Andric // CFAllocatorRef alloc, 4390b57cec5SDimitry Andric // const UInt8 *bytes, 4400b57cec5SDimitry Andric // CFIndex numBytes, 4410b57cec5SDimitry Andric // CFStringEncoding encoding, 4420b57cec5SDimitry Andric // Boolean isExternalRepresentation 4430b57cec5SDimitry Andric // ); 4440b57cec5SDimitry Andric // 4450b57cec5SDimitry Andric // We make the following substitutions: 4460b57cec5SDimitry Andric // 4470b57cec5SDimitry Andric // CFStringRef -> i8* 4480b57cec5SDimitry Andric // CFAllocatorRef -> i8* 4490b57cec5SDimitry Andric // UInt8 * -> i8* 4500b57cec5SDimitry Andric // CFIndex -> long (i32 or i64, as appropriate; we ask the module for its 4510b57cec5SDimitry Andric // pointer size for now) CFStringEncoding -> i32 Boolean -> i8 4520b57cec5SDimitry Andric 4530b57cec5SDimitry Andric Type *arg_type_array[5]; 4540b57cec5SDimitry Andric 4550b57cec5SDimitry Andric arg_type_array[0] = i8_ptr_ty; 4560b57cec5SDimitry Andric arg_type_array[1] = i8_ptr_ty; 4570b57cec5SDimitry Andric arg_type_array[2] = m_intptr_ty; 4580b57cec5SDimitry Andric arg_type_array[3] = i32_ty; 4590b57cec5SDimitry Andric arg_type_array[4] = i8_ty; 4600b57cec5SDimitry Andric 4610b57cec5SDimitry Andric ArrayRef<Type *> CFSCWB_arg_types(arg_type_array, 5); 4620b57cec5SDimitry Andric 4630b57cec5SDimitry Andric llvm::FunctionType *CFSCWB_ty = 4640b57cec5SDimitry Andric FunctionType::get(ns_str_ty, CFSCWB_arg_types, false); 4650b57cec5SDimitry Andric 4660b57cec5SDimitry Andric // Build the constant containing the pointer to the function 4670b57cec5SDimitry Andric PointerType *CFSCWB_ptr_ty = PointerType::getUnqual(CFSCWB_ty); 4680b57cec5SDimitry Andric Constant *CFSCWB_addr_int = 4690b57cec5SDimitry Andric ConstantInt::get(m_intptr_ty, CFStringCreateWithBytes_addr, false); 4700b57cec5SDimitry Andric m_CFStringCreateWithBytes = { 4710b57cec5SDimitry Andric CFSCWB_ty, ConstantExpr::getIntToPtr(CFSCWB_addr_int, CFSCWB_ptr_ty)}; 4720b57cec5SDimitry Andric } 4730b57cec5SDimitry Andric 4740b57cec5SDimitry Andric ConstantDataSequential *string_array = nullptr; 4750b57cec5SDimitry Andric 4760b57cec5SDimitry Andric if (cstr) 4770b57cec5SDimitry Andric string_array = dyn_cast<ConstantDataSequential>(cstr->getInitializer()); 4780b57cec5SDimitry Andric 4790b57cec5SDimitry Andric Constant *alloc_arg = Constant::getNullValue(i8_ptr_ty); 48006c3fb27SDimitry Andric Constant *bytes_arg = cstr ? cstr : Constant::getNullValue(i8_ptr_ty); 4810b57cec5SDimitry Andric Constant *numBytes_arg = ConstantInt::get( 4820b57cec5SDimitry Andric m_intptr_ty, cstr ? (string_array->getNumElements() - 1) * string_array->getElementByteSize() : 0, false); 4830b57cec5SDimitry Andric int encoding_flags = 0; 4840b57cec5SDimitry Andric switch (cstr ? string_array->getElementByteSize() : 1) { 4850b57cec5SDimitry Andric case 1: 4860b57cec5SDimitry Andric encoding_flags = 0x08000100; /* 0x08000100 is kCFStringEncodingUTF8 */ 4870b57cec5SDimitry Andric break; 4880b57cec5SDimitry Andric case 2: 4890b57cec5SDimitry Andric encoding_flags = 0x0100; /* 0x0100 is kCFStringEncodingUTF16 */ 4900b57cec5SDimitry Andric break; 4910b57cec5SDimitry Andric case 4: 4920b57cec5SDimitry Andric encoding_flags = 0x0c000100; /* 0x0c000100 is kCFStringEncodingUTF32 */ 4930b57cec5SDimitry Andric break; 4940b57cec5SDimitry Andric default: 4950b57cec5SDimitry Andric encoding_flags = 0x0600; /* fall back to 0x0600, kCFStringEncodingASCII */ 4960b57cec5SDimitry Andric LLDB_LOG(log, "Encountered an Objective-C constant string with unusual " 4970b57cec5SDimitry Andric "element size {0}", 4980b57cec5SDimitry Andric string_array->getElementByteSize()); 4990b57cec5SDimitry Andric } 5000b57cec5SDimitry Andric Constant *encoding_arg = ConstantInt::get(i32_ty, encoding_flags, false); 5010b57cec5SDimitry Andric Constant *isExternal_arg = 5020b57cec5SDimitry Andric ConstantInt::get(i8_ty, 0x0, false); /* 0x0 is false */ 5030b57cec5SDimitry Andric 5040b57cec5SDimitry Andric Value *argument_array[5]; 5050b57cec5SDimitry Andric 5060b57cec5SDimitry Andric argument_array[0] = alloc_arg; 5070b57cec5SDimitry Andric argument_array[1] = bytes_arg; 5080b57cec5SDimitry Andric argument_array[2] = numBytes_arg; 5090b57cec5SDimitry Andric argument_array[3] = encoding_arg; 5100b57cec5SDimitry Andric argument_array[4] = isExternal_arg; 5110b57cec5SDimitry Andric 5120b57cec5SDimitry Andric ArrayRef<Value *> CFSCWB_arguments(argument_array, 5); 5130b57cec5SDimitry Andric 5140b57cec5SDimitry Andric FunctionValueCache CFSCWB_Caller( 5150b57cec5SDimitry Andric [this, &CFSCWB_arguments](llvm::Function *function) -> llvm::Value * { 5160b57cec5SDimitry Andric return CallInst::Create( 5170b57cec5SDimitry Andric m_CFStringCreateWithBytes, CFSCWB_arguments, 5180b57cec5SDimitry Andric "CFStringCreateWithBytes", 5190b57cec5SDimitry Andric llvm::cast<Instruction>( 5200b57cec5SDimitry Andric m_entry_instruction_finder.GetValue(function))); 5210b57cec5SDimitry Andric }); 5220b57cec5SDimitry Andric 5230b57cec5SDimitry Andric if (!UnfoldConstant(ns_str, nullptr, CFSCWB_Caller, m_entry_instruction_finder, 5240b57cec5SDimitry Andric m_error_stream)) { 5259dba64beSDimitry Andric LLDB_LOG(log, "Couldn't replace the NSString with the result of the call"); 5260b57cec5SDimitry Andric 5270b57cec5SDimitry Andric m_error_stream.Printf("error [IRForTarget internal]: Couldn't replace an " 5280b57cec5SDimitry Andric "Objective-C constant string with a dynamic " 5290b57cec5SDimitry Andric "string\n"); 5300b57cec5SDimitry Andric 5310b57cec5SDimitry Andric return false; 5320b57cec5SDimitry Andric } 5330b57cec5SDimitry Andric 5340b57cec5SDimitry Andric ns_str->eraseFromParent(); 5350b57cec5SDimitry Andric 5360b57cec5SDimitry Andric return true; 5370b57cec5SDimitry Andric } 5380b57cec5SDimitry Andric 5390b57cec5SDimitry Andric bool IRForTarget::RewriteObjCConstStrings() { 54081ad6265SDimitry Andric lldb_private::Log *log(GetLog(LLDBLog::Expressions)); 5410b57cec5SDimitry Andric 5420b57cec5SDimitry Andric ValueSymbolTable &value_symbol_table = m_module->getValueSymbolTable(); 5430b57cec5SDimitry Andric 5449dba64beSDimitry Andric for (StringMapEntry<llvm::Value *> &value_symbol : value_symbol_table) { 5459dba64beSDimitry Andric llvm::StringRef value_name = value_symbol.first(); 5460b57cec5SDimitry Andric 5479dba64beSDimitry Andric if (value_name.contains("_unnamed_cfstring_")) { 5489dba64beSDimitry Andric Value *nsstring_value = value_symbol.second; 5490b57cec5SDimitry Andric 5500b57cec5SDimitry Andric GlobalVariable *nsstring_global = 5510b57cec5SDimitry Andric dyn_cast<GlobalVariable>(nsstring_value); 5520b57cec5SDimitry Andric 5530b57cec5SDimitry Andric if (!nsstring_global) { 5549dba64beSDimitry Andric LLDB_LOG(log, "NSString variable is not a GlobalVariable"); 5550b57cec5SDimitry Andric 5560b57cec5SDimitry Andric m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C " 5570b57cec5SDimitry Andric "constant string is not a global variable\n"); 5580b57cec5SDimitry Andric 5590b57cec5SDimitry Andric return false; 5600b57cec5SDimitry Andric } 5610b57cec5SDimitry Andric 5620b57cec5SDimitry Andric if (!nsstring_global->hasInitializer()) { 5639dba64beSDimitry Andric LLDB_LOG(log, "NSString variable does not have an initializer"); 5640b57cec5SDimitry Andric 5650b57cec5SDimitry Andric m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C " 5660b57cec5SDimitry Andric "constant string does not have an initializer\n"); 5670b57cec5SDimitry Andric 5680b57cec5SDimitry Andric return false; 5690b57cec5SDimitry Andric } 5700b57cec5SDimitry Andric 5710b57cec5SDimitry Andric ConstantStruct *nsstring_struct = 5720b57cec5SDimitry Andric dyn_cast<ConstantStruct>(nsstring_global->getInitializer()); 5730b57cec5SDimitry Andric 5740b57cec5SDimitry Andric if (!nsstring_struct) { 5759dba64beSDimitry Andric LLDB_LOG(log, 5760b57cec5SDimitry Andric "NSString variable's initializer is not a ConstantStruct"); 5770b57cec5SDimitry Andric 5780b57cec5SDimitry Andric m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C " 5790b57cec5SDimitry Andric "constant string is not a structure constant\n"); 5800b57cec5SDimitry Andric 5810b57cec5SDimitry Andric return false; 5820b57cec5SDimitry Andric } 5830b57cec5SDimitry Andric 5840b57cec5SDimitry Andric // We expect the following structure: 5850b57cec5SDimitry Andric // 5860b57cec5SDimitry Andric // struct { 5870b57cec5SDimitry Andric // int *isa; 5880b57cec5SDimitry Andric // int flags; 5890b57cec5SDimitry Andric // char *str; 5900b57cec5SDimitry Andric // long length; 5910b57cec5SDimitry Andric // }; 5920b57cec5SDimitry Andric 5930b57cec5SDimitry Andric if (nsstring_struct->getNumOperands() != 4) { 5949dba64beSDimitry Andric 5959dba64beSDimitry Andric LLDB_LOG(log, 5969dba64beSDimitry Andric "NSString variable's initializer structure has an " 5979dba64beSDimitry Andric "unexpected number of members. Should be 4, is {0}", 5980b57cec5SDimitry Andric nsstring_struct->getNumOperands()); 5990b57cec5SDimitry Andric 6000b57cec5SDimitry Andric m_error_stream.Printf("Internal error [IRForTarget]: The struct for an " 6010b57cec5SDimitry Andric "Objective-C constant string is not as " 6020b57cec5SDimitry Andric "expected\n"); 6030b57cec5SDimitry Andric 6040b57cec5SDimitry Andric return false; 6050b57cec5SDimitry Andric } 6060b57cec5SDimitry Andric 6070b57cec5SDimitry Andric Constant *nsstring_member = nsstring_struct->getOperand(2); 6080b57cec5SDimitry Andric 6090b57cec5SDimitry Andric if (!nsstring_member) { 6109dba64beSDimitry Andric LLDB_LOG(log, "NSString initializer's str element was empty"); 6110b57cec5SDimitry Andric 6120b57cec5SDimitry Andric m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C " 6130b57cec5SDimitry Andric "constant string does not have a string " 6140b57cec5SDimitry Andric "initializer\n"); 6150b57cec5SDimitry Andric 6160b57cec5SDimitry Andric return false; 6170b57cec5SDimitry Andric } 6180b57cec5SDimitry Andric 61981ad6265SDimitry Andric auto *cstr_global = dyn_cast<GlobalVariable>(nsstring_member); 6200b57cec5SDimitry Andric if (!cstr_global) { 6219dba64beSDimitry Andric LLDB_LOG(log, 6220b57cec5SDimitry Andric "NSString initializer's str element is not a GlobalVariable"); 6230b57cec5SDimitry Andric 6240b57cec5SDimitry Andric m_error_stream.Printf("Internal error [IRForTarget]: Unhandled" 6250b57cec5SDimitry Andric "constant string initializer\n"); 6260b57cec5SDimitry Andric 6270b57cec5SDimitry Andric return false; 6280b57cec5SDimitry Andric } 6290b57cec5SDimitry Andric 6300b57cec5SDimitry Andric if (!cstr_global->hasInitializer()) { 6319dba64beSDimitry Andric LLDB_LOG(log, "NSString initializer's str element does not have an " 6320b57cec5SDimitry Andric "initializer"); 6330b57cec5SDimitry Andric 6340b57cec5SDimitry Andric m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C " 6350b57cec5SDimitry Andric "constant string's string initializer doesn't " 6360b57cec5SDimitry Andric "point to initialized data\n"); 6370b57cec5SDimitry Andric 6380b57cec5SDimitry Andric return false; 6390b57cec5SDimitry Andric } 6400b57cec5SDimitry Andric 6410b57cec5SDimitry Andric /* 6420b57cec5SDimitry Andric if (!cstr_array) 6430b57cec5SDimitry Andric { 6440b57cec5SDimitry Andric if (log) 6450b57cec5SDimitry Andric log->PutCString("NSString initializer's str element is not a 6460b57cec5SDimitry Andric ConstantArray"); 6470b57cec5SDimitry Andric 6480b57cec5SDimitry Andric if (m_error_stream) 6490b57cec5SDimitry Andric m_error_stream.Printf("Internal error [IRForTarget]: An 6500b57cec5SDimitry Andric Objective-C constant string's string initializer doesn't point to an 6510b57cec5SDimitry Andric array\n"); 6520b57cec5SDimitry Andric 6530b57cec5SDimitry Andric return false; 6540b57cec5SDimitry Andric } 6550b57cec5SDimitry Andric 6560b57cec5SDimitry Andric if (!cstr_array->isCString()) 6570b57cec5SDimitry Andric { 6580b57cec5SDimitry Andric if (log) 6590b57cec5SDimitry Andric log->PutCString("NSString initializer's str element is not a C 6600b57cec5SDimitry Andric string array"); 6610b57cec5SDimitry Andric 6620b57cec5SDimitry Andric if (m_error_stream) 6630b57cec5SDimitry Andric m_error_stream.Printf("Internal error [IRForTarget]: An 6640b57cec5SDimitry Andric Objective-C constant string's string initializer doesn't point to a C 6650b57cec5SDimitry Andric string\n"); 6660b57cec5SDimitry Andric 6670b57cec5SDimitry Andric return false; 6680b57cec5SDimitry Andric } 6690b57cec5SDimitry Andric */ 6700b57cec5SDimitry Andric 6710b57cec5SDimitry Andric ConstantDataArray *cstr_array = 6720b57cec5SDimitry Andric dyn_cast<ConstantDataArray>(cstr_global->getInitializer()); 6730b57cec5SDimitry Andric 6740b57cec5SDimitry Andric if (cstr_array) 6759dba64beSDimitry Andric LLDB_LOG(log, "Found NSString constant {0}, which contains \"{1}\"", 6769dba64beSDimitry Andric value_name, cstr_array->getAsString()); 6770b57cec5SDimitry Andric else 6789dba64beSDimitry Andric LLDB_LOG(log, "Found NSString constant {0}, which contains \"\"", 6799dba64beSDimitry Andric value_name); 6800b57cec5SDimitry Andric 6810b57cec5SDimitry Andric if (!cstr_array) 6820b57cec5SDimitry Andric cstr_global = nullptr; 6830b57cec5SDimitry Andric 6840b57cec5SDimitry Andric if (!RewriteObjCConstString(nsstring_global, cstr_global)) { 6859dba64beSDimitry Andric LLDB_LOG(log, "Error rewriting the constant string"); 6860b57cec5SDimitry Andric 6870b57cec5SDimitry Andric // We don't print an error message here because RewriteObjCConstString 6880b57cec5SDimitry Andric // has done so for us. 6890b57cec5SDimitry Andric 6900b57cec5SDimitry Andric return false; 6910b57cec5SDimitry Andric } 6920b57cec5SDimitry Andric } 6930b57cec5SDimitry Andric } 6940b57cec5SDimitry Andric 6959dba64beSDimitry Andric for (StringMapEntry<llvm::Value *> &value_symbol : value_symbol_table) { 6969dba64beSDimitry Andric llvm::StringRef value_name = value_symbol.first(); 6970b57cec5SDimitry Andric 6989dba64beSDimitry Andric if (value_name == "__CFConstantStringClassReference") { 6999dba64beSDimitry Andric GlobalVariable *gv = dyn_cast<GlobalVariable>(value_symbol.second); 7000b57cec5SDimitry Andric 7010b57cec5SDimitry Andric if (!gv) { 7029dba64beSDimitry Andric LLDB_LOG(log, 7030b57cec5SDimitry Andric "__CFConstantStringClassReference is not a global variable"); 7040b57cec5SDimitry Andric 7050b57cec5SDimitry Andric m_error_stream.Printf("Internal error [IRForTarget]: Found a " 7060b57cec5SDimitry Andric "CFConstantStringClassReference, but it is not a " 7070b57cec5SDimitry Andric "global object\n"); 7080b57cec5SDimitry Andric 7090b57cec5SDimitry Andric return false; 7100b57cec5SDimitry Andric } 7110b57cec5SDimitry Andric 7120b57cec5SDimitry Andric gv->eraseFromParent(); 7130b57cec5SDimitry Andric 7140b57cec5SDimitry Andric break; 7150b57cec5SDimitry Andric } 7160b57cec5SDimitry Andric } 7170b57cec5SDimitry Andric 7180b57cec5SDimitry Andric return true; 7190b57cec5SDimitry Andric } 7200b57cec5SDimitry Andric 7210b57cec5SDimitry Andric static bool IsObjCSelectorRef(Value *value) { 7220b57cec5SDimitry Andric GlobalVariable *global_variable = dyn_cast<GlobalVariable>(value); 7230b57cec5SDimitry Andric 7245f757f3fSDimitry Andric return !( 7255f757f3fSDimitry Andric !global_variable || !global_variable->hasName() || 7265f757f3fSDimitry Andric !global_variable->getName().starts_with("OBJC_SELECTOR_REFERENCES_")); 7270b57cec5SDimitry Andric } 7280b57cec5SDimitry Andric 7290b57cec5SDimitry Andric // This function does not report errors; its callers are responsible. 7300b57cec5SDimitry Andric bool IRForTarget::RewriteObjCSelector(Instruction *selector_load) { 73181ad6265SDimitry Andric lldb_private::Log *log(GetLog(LLDBLog::Expressions)); 7320b57cec5SDimitry Andric 7330b57cec5SDimitry Andric LoadInst *load = dyn_cast<LoadInst>(selector_load); 7340b57cec5SDimitry Andric 7350b57cec5SDimitry Andric if (!load) 7360b57cec5SDimitry Andric return false; 7370b57cec5SDimitry Andric 7380b57cec5SDimitry Andric // Unpack the message name from the selector. In LLVM IR, an objc_msgSend 7390b57cec5SDimitry Andric // gets represented as 7400b57cec5SDimitry Andric // 74181ad6265SDimitry Andric // %sel = load ptr, ptr @OBJC_SELECTOR_REFERENCES_, align 8 74281ad6265SDimitry Andric // call i8 @objc_msgSend(ptr %obj, ptr %sel, ...) 7430b57cec5SDimitry Andric // 74481ad6265SDimitry Andric // where %obj is the object pointer and %sel is the selector. 7450b57cec5SDimitry Andric // 7460b57cec5SDimitry Andric // @"OBJC_SELECTOR_REFERENCES_" is a pointer to a character array called 74706c3fb27SDimitry Andric // @"\01L_OBJC_METH_VAR_NAME_". 74806c3fb27SDimitry Andric // @"\01L_OBJC_METH_VAR_NAME_" contains the string. 7490b57cec5SDimitry Andric 75081ad6265SDimitry Andric // Find the pointer's initializer and get the string from its target. 7510b57cec5SDimitry Andric 7520b57cec5SDimitry Andric GlobalVariable *_objc_selector_references_ = 7530b57cec5SDimitry Andric dyn_cast<GlobalVariable>(load->getPointerOperand()); 7540b57cec5SDimitry Andric 7550b57cec5SDimitry Andric if (!_objc_selector_references_ || 7560b57cec5SDimitry Andric !_objc_selector_references_->hasInitializer()) 7570b57cec5SDimitry Andric return false; 7580b57cec5SDimitry Andric 7590b57cec5SDimitry Andric Constant *osr_initializer = _objc_selector_references_->getInitializer(); 76081ad6265SDimitry Andric if (!osr_initializer) 7610b57cec5SDimitry Andric return false; 7620b57cec5SDimitry Andric 7630b57cec5SDimitry Andric // Find the string's initializer (a ConstantArray) and get the string from it 7640b57cec5SDimitry Andric 7650b57cec5SDimitry Andric GlobalVariable *_objc_meth_var_name_ = 76681ad6265SDimitry Andric dyn_cast<GlobalVariable>(osr_initializer); 7670b57cec5SDimitry Andric 7680b57cec5SDimitry Andric if (!_objc_meth_var_name_ || !_objc_meth_var_name_->hasInitializer()) 7690b57cec5SDimitry Andric return false; 7700b57cec5SDimitry Andric 7710b57cec5SDimitry Andric Constant *omvn_initializer = _objc_meth_var_name_->getInitializer(); 7720b57cec5SDimitry Andric 7730b57cec5SDimitry Andric ConstantDataArray *omvn_initializer_array = 7740b57cec5SDimitry Andric dyn_cast<ConstantDataArray>(omvn_initializer); 7750b57cec5SDimitry Andric 7760b57cec5SDimitry Andric if (!omvn_initializer_array->isString()) 7770b57cec5SDimitry Andric return false; 7780b57cec5SDimitry Andric 7795ffd83dbSDimitry Andric std::string omvn_initializer_string = 7805ffd83dbSDimitry Andric std::string(omvn_initializer_array->getAsString()); 7810b57cec5SDimitry Andric 7829dba64beSDimitry Andric LLDB_LOG(log, "Found Objective-C selector reference \"{0}\"", 7839dba64beSDimitry Andric omvn_initializer_string); 7840b57cec5SDimitry Andric 7850b57cec5SDimitry Andric // Construct a call to sel_registerName 7860b57cec5SDimitry Andric 7870b57cec5SDimitry Andric if (!m_sel_registerName) { 7880b57cec5SDimitry Andric lldb::addr_t sel_registerName_addr; 7890b57cec5SDimitry Andric 7900b57cec5SDimitry Andric bool missing_weak = false; 7910b57cec5SDimitry Andric static lldb_private::ConstString g_sel_registerName_str("sel_registerName"); 7920b57cec5SDimitry Andric sel_registerName_addr = m_execution_unit.FindSymbol(g_sel_registerName_str, 7930b57cec5SDimitry Andric missing_weak); 7940b57cec5SDimitry Andric if (sel_registerName_addr == LLDB_INVALID_ADDRESS || missing_weak) 7950b57cec5SDimitry Andric return false; 7960b57cec5SDimitry Andric 7979dba64beSDimitry Andric LLDB_LOG(log, "Found sel_registerName at {0}", sel_registerName_addr); 7980b57cec5SDimitry Andric 7990b57cec5SDimitry Andric // Build the function type: struct objc_selector 8000b57cec5SDimitry Andric // *sel_registerName(uint8_t*) 8010b57cec5SDimitry Andric 8020b57cec5SDimitry Andric // The below code would be "more correct," but in actuality what's required 8030b57cec5SDimitry Andric // is uint8_t* 8040b57cec5SDimitry Andric // Type *sel_type = StructType::get(m_module->getContext()); 8050b57cec5SDimitry Andric // Type *sel_ptr_type = PointerType::getUnqual(sel_type); 8065f757f3fSDimitry Andric Type *sel_ptr_type = PointerType::getUnqual(m_module->getContext()); 8070b57cec5SDimitry Andric 8080b57cec5SDimitry Andric Type *type_array[1]; 8090b57cec5SDimitry Andric 8105f757f3fSDimitry Andric type_array[0] = llvm::PointerType::getUnqual(m_module->getContext()); 8110b57cec5SDimitry Andric 8120b57cec5SDimitry Andric ArrayRef<Type *> srN_arg_types(type_array, 1); 8130b57cec5SDimitry Andric 8140b57cec5SDimitry Andric llvm::FunctionType *srN_type = 8150b57cec5SDimitry Andric FunctionType::get(sel_ptr_type, srN_arg_types, false); 8160b57cec5SDimitry Andric 8170b57cec5SDimitry Andric // Build the constant containing the pointer to the function 8180b57cec5SDimitry Andric PointerType *srN_ptr_ty = PointerType::getUnqual(srN_type); 8190b57cec5SDimitry Andric Constant *srN_addr_int = 8200b57cec5SDimitry Andric ConstantInt::get(m_intptr_ty, sel_registerName_addr, false); 8210b57cec5SDimitry Andric m_sel_registerName = {srN_type, 8220b57cec5SDimitry Andric ConstantExpr::getIntToPtr(srN_addr_int, srN_ptr_ty)}; 8230b57cec5SDimitry Andric } 8240b57cec5SDimitry Andric 82506c3fb27SDimitry Andric CallInst *srN_call = 82606c3fb27SDimitry Andric CallInst::Create(m_sel_registerName, _objc_meth_var_name_, 8270b57cec5SDimitry Andric "sel_registerName", selector_load); 8280b57cec5SDimitry Andric 8290b57cec5SDimitry Andric // Replace the load with the call in all users 8300b57cec5SDimitry Andric 8310b57cec5SDimitry Andric selector_load->replaceAllUsesWith(srN_call); 8320b57cec5SDimitry Andric 8330b57cec5SDimitry Andric selector_load->eraseFromParent(); 8340b57cec5SDimitry Andric 8350b57cec5SDimitry Andric return true; 8360b57cec5SDimitry Andric } 8370b57cec5SDimitry Andric 8380b57cec5SDimitry Andric bool IRForTarget::RewriteObjCSelectors(BasicBlock &basic_block) { 83981ad6265SDimitry Andric lldb_private::Log *log(GetLog(LLDBLog::Expressions)); 8400b57cec5SDimitry Andric 8410b57cec5SDimitry Andric InstrList selector_loads; 8420b57cec5SDimitry Andric 8439dba64beSDimitry Andric for (Instruction &inst : basic_block) { 8440b57cec5SDimitry Andric if (LoadInst *load = dyn_cast<LoadInst>(&inst)) 8450b57cec5SDimitry Andric if (IsObjCSelectorRef(load->getPointerOperand())) 8460b57cec5SDimitry Andric selector_loads.push_back(&inst); 8470b57cec5SDimitry Andric } 8480b57cec5SDimitry Andric 8499dba64beSDimitry Andric for (Instruction *inst : selector_loads) { 8509dba64beSDimitry Andric if (!RewriteObjCSelector(inst)) { 8510b57cec5SDimitry Andric m_error_stream.Printf("Internal error [IRForTarget]: Couldn't change a " 8520b57cec5SDimitry Andric "static reference to an Objective-C selector to a " 8530b57cec5SDimitry Andric "dynamic reference\n"); 8540b57cec5SDimitry Andric 8559dba64beSDimitry Andric LLDB_LOG(log, "Couldn't rewrite a reference to an Objective-C selector"); 8560b57cec5SDimitry Andric 8570b57cec5SDimitry Andric return false; 8580b57cec5SDimitry Andric } 8590b57cec5SDimitry Andric } 8600b57cec5SDimitry Andric 8610b57cec5SDimitry Andric return true; 8620b57cec5SDimitry Andric } 8630b57cec5SDimitry Andric 8640b57cec5SDimitry Andric // This function does not report errors; its callers are responsible. 8650b57cec5SDimitry Andric bool IRForTarget::RewritePersistentAlloc(llvm::Instruction *persistent_alloc) { 86681ad6265SDimitry Andric lldb_private::Log *log(GetLog(LLDBLog::Expressions)); 8670b57cec5SDimitry Andric 8680b57cec5SDimitry Andric AllocaInst *alloc = dyn_cast<AllocaInst>(persistent_alloc); 8690b57cec5SDimitry Andric 8700b57cec5SDimitry Andric MDNode *alloc_md = alloc->getMetadata("clang.decl.ptr"); 8710b57cec5SDimitry Andric 8720b57cec5SDimitry Andric if (!alloc_md || !alloc_md->getNumOperands()) 8730b57cec5SDimitry Andric return false; 8740b57cec5SDimitry Andric 8750b57cec5SDimitry Andric ConstantInt *constant_int = 8760b57cec5SDimitry Andric mdconst::dyn_extract<ConstantInt>(alloc_md->getOperand(0)); 8770b57cec5SDimitry Andric 8780b57cec5SDimitry Andric if (!constant_int) 8790b57cec5SDimitry Andric return false; 8800b57cec5SDimitry Andric 8810b57cec5SDimitry Andric // We attempt to register this as a new persistent variable with the DeclMap. 8820b57cec5SDimitry Andric 8830b57cec5SDimitry Andric uintptr_t ptr = constant_int->getZExtValue(); 8840b57cec5SDimitry Andric 8850b57cec5SDimitry Andric clang::VarDecl *decl = reinterpret_cast<clang::VarDecl *>(ptr); 8860b57cec5SDimitry Andric 8870b57cec5SDimitry Andric lldb_private::TypeFromParser result_decl_type( 8885ffd83dbSDimitry Andric m_decl_map->GetTypeSystem()->GetType(decl->getType())); 8890b57cec5SDimitry Andric 8900b57cec5SDimitry Andric StringRef decl_name(decl->getName()); 8910b57cec5SDimitry Andric lldb_private::ConstString persistent_variable_name(decl_name.data(), 8920b57cec5SDimitry Andric decl_name.size()); 8930b57cec5SDimitry Andric if (!m_decl_map->AddPersistentVariable(decl, persistent_variable_name, 8940b57cec5SDimitry Andric result_decl_type, false, false)) 8950b57cec5SDimitry Andric return false; 8960b57cec5SDimitry Andric 8970b57cec5SDimitry Andric GlobalVariable *persistent_global = new GlobalVariable( 8980b57cec5SDimitry Andric (*m_module), alloc->getType(), false, /* not constant */ 8990b57cec5SDimitry Andric GlobalValue::ExternalLinkage, nullptr, /* no initializer */ 9000b57cec5SDimitry Andric alloc->getName().str()); 9010b57cec5SDimitry Andric 9020b57cec5SDimitry Andric // What we're going to do here is make believe this was a regular old 9030b57cec5SDimitry Andric // external variable. That means we need to make the metadata valid. 9040b57cec5SDimitry Andric 9050b57cec5SDimitry Andric NamedMDNode *named_metadata = 9060b57cec5SDimitry Andric m_module->getOrInsertNamedMetadata("clang.global.decl.ptrs"); 9070b57cec5SDimitry Andric 9080b57cec5SDimitry Andric llvm::Metadata *values[2]; 9090b57cec5SDimitry Andric values[0] = ConstantAsMetadata::get(persistent_global); 9100b57cec5SDimitry Andric values[1] = ConstantAsMetadata::get(constant_int); 9110b57cec5SDimitry Andric 9120b57cec5SDimitry Andric ArrayRef<llvm::Metadata *> value_ref(values, 2); 9130b57cec5SDimitry Andric 9140b57cec5SDimitry Andric MDNode *persistent_global_md = MDNode::get(m_module->getContext(), value_ref); 9150b57cec5SDimitry Andric named_metadata->addOperand(persistent_global_md); 9160b57cec5SDimitry Andric 9170b57cec5SDimitry Andric // Now, since the variable is a pointer variable, we will drop in a load of 9180b57cec5SDimitry Andric // that pointer variable. 9190b57cec5SDimitry Andric 92081ad6265SDimitry Andric LoadInst *persistent_load = new LoadInst(persistent_global->getValueType(), 9215ffd83dbSDimitry Andric persistent_global, "", alloc); 9220b57cec5SDimitry Andric 9239dba64beSDimitry Andric LLDB_LOG(log, "Replacing \"{0}\" with \"{1}\"", PrintValue(alloc), 9249dba64beSDimitry Andric PrintValue(persistent_load)); 9250b57cec5SDimitry Andric 9260b57cec5SDimitry Andric alloc->replaceAllUsesWith(persistent_load); 9270b57cec5SDimitry Andric alloc->eraseFromParent(); 9280b57cec5SDimitry Andric 9290b57cec5SDimitry Andric return true; 9300b57cec5SDimitry Andric } 9310b57cec5SDimitry Andric 9320b57cec5SDimitry Andric bool IRForTarget::RewritePersistentAllocs(llvm::BasicBlock &basic_block) { 9330b57cec5SDimitry Andric if (!m_resolve_vars) 9340b57cec5SDimitry Andric return true; 9350b57cec5SDimitry Andric 93681ad6265SDimitry Andric lldb_private::Log *log(GetLog(LLDBLog::Expressions)); 9370b57cec5SDimitry Andric 9380b57cec5SDimitry Andric InstrList pvar_allocs; 9390b57cec5SDimitry Andric 9409dba64beSDimitry Andric for (Instruction &inst : basic_block) { 9410b57cec5SDimitry Andric 9420b57cec5SDimitry Andric if (AllocaInst *alloc = dyn_cast<AllocaInst>(&inst)) { 9430b57cec5SDimitry Andric llvm::StringRef alloc_name = alloc->getName(); 9440b57cec5SDimitry Andric 9455f757f3fSDimitry Andric if (alloc_name.starts_with("$") && !alloc_name.starts_with("$__lldb")) { 9460b57cec5SDimitry Andric if (alloc_name.find_first_of("0123456789") == 1) { 9479dba64beSDimitry Andric LLDB_LOG(log, "Rejecting a numeric persistent variable."); 9480b57cec5SDimitry Andric 9490b57cec5SDimitry Andric m_error_stream.Printf("Error [IRForTarget]: Names starting with $0, " 9500b57cec5SDimitry Andric "$1, ... are reserved for use as result " 9510b57cec5SDimitry Andric "names\n"); 9520b57cec5SDimitry Andric 9530b57cec5SDimitry Andric return false; 9540b57cec5SDimitry Andric } 9550b57cec5SDimitry Andric 9560b57cec5SDimitry Andric pvar_allocs.push_back(alloc); 9570b57cec5SDimitry Andric } 9580b57cec5SDimitry Andric } 9590b57cec5SDimitry Andric } 9600b57cec5SDimitry Andric 9619dba64beSDimitry Andric for (Instruction *inst : pvar_allocs) { 9629dba64beSDimitry Andric if (!RewritePersistentAlloc(inst)) { 9630b57cec5SDimitry Andric m_error_stream.Printf("Internal error [IRForTarget]: Couldn't rewrite " 9640b57cec5SDimitry Andric "the creation of a persistent variable\n"); 9650b57cec5SDimitry Andric 9669dba64beSDimitry Andric LLDB_LOG(log, "Couldn't rewrite the creation of a persistent variable"); 9670b57cec5SDimitry Andric 9680b57cec5SDimitry Andric return false; 9690b57cec5SDimitry Andric } 9700b57cec5SDimitry Andric } 9710b57cec5SDimitry Andric 9720b57cec5SDimitry Andric return true; 9730b57cec5SDimitry Andric } 9740b57cec5SDimitry Andric 9750b57cec5SDimitry Andric // This function does not report errors; its callers are responsible. 9760b57cec5SDimitry Andric bool IRForTarget::MaybeHandleVariable(Value *llvm_value_ptr) { 97781ad6265SDimitry Andric lldb_private::Log *log(GetLog(LLDBLog::Expressions)); 9780b57cec5SDimitry Andric 9799dba64beSDimitry Andric LLDB_LOG(log, "MaybeHandleVariable ({0})", PrintValue(llvm_value_ptr)); 9800b57cec5SDimitry Andric 9810b57cec5SDimitry Andric if (ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(llvm_value_ptr)) { 9820b57cec5SDimitry Andric switch (constant_expr->getOpcode()) { 9830b57cec5SDimitry Andric default: 9840b57cec5SDimitry Andric break; 9850b57cec5SDimitry Andric case Instruction::GetElementPtr: 9860b57cec5SDimitry Andric case Instruction::BitCast: 9870b57cec5SDimitry Andric Value *s = constant_expr->getOperand(0); 9880b57cec5SDimitry Andric if (!MaybeHandleVariable(s)) 9890b57cec5SDimitry Andric return false; 9900b57cec5SDimitry Andric } 9910b57cec5SDimitry Andric } else if (GlobalVariable *global_variable = 9920b57cec5SDimitry Andric dyn_cast<GlobalVariable>(llvm_value_ptr)) { 9930b57cec5SDimitry Andric if (!GlobalValue::isExternalLinkage(global_variable->getLinkage())) 9940b57cec5SDimitry Andric return true; 9950b57cec5SDimitry Andric 9960b57cec5SDimitry Andric clang::NamedDecl *named_decl = DeclForGlobal(global_variable); 9970b57cec5SDimitry Andric 9980b57cec5SDimitry Andric if (!named_decl) { 9990b57cec5SDimitry Andric if (IsObjCSelectorRef(llvm_value_ptr)) 10000b57cec5SDimitry Andric return true; 10010b57cec5SDimitry Andric 10020b57cec5SDimitry Andric if (!global_variable->hasExternalLinkage()) 10030b57cec5SDimitry Andric return true; 10040b57cec5SDimitry Andric 10059dba64beSDimitry Andric LLDB_LOG(log, "Found global variable \"{0}\" without metadata", 10069dba64beSDimitry Andric global_variable->getName()); 10070b57cec5SDimitry Andric 10080b57cec5SDimitry Andric return false; 10090b57cec5SDimitry Andric } 10100b57cec5SDimitry Andric 10119dba64beSDimitry Andric llvm::StringRef name(named_decl->getName()); 10120b57cec5SDimitry Andric 10130b57cec5SDimitry Andric clang::ValueDecl *value_decl = dyn_cast<clang::ValueDecl>(named_decl); 10140b57cec5SDimitry Andric if (value_decl == nullptr) 10150b57cec5SDimitry Andric return false; 10160b57cec5SDimitry Andric 10175ffd83dbSDimitry Andric lldb_private::CompilerType compiler_type = 10185ffd83dbSDimitry Andric m_decl_map->GetTypeSystem()->GetType(value_decl->getType()); 10190b57cec5SDimitry Andric 10200b57cec5SDimitry Andric const Type *value_type = nullptr; 10210b57cec5SDimitry Andric 10225f757f3fSDimitry Andric if (name.starts_with("$")) { 10230b57cec5SDimitry Andric // The $__lldb_expr_result name indicates the return value has allocated 10240b57cec5SDimitry Andric // as a static variable. Per the comment at 10250b57cec5SDimitry Andric // ASTResultSynthesizer::SynthesizeBodyResult, accesses to this static 10260b57cec5SDimitry Andric // variable need to be redirected to the result of dereferencing a 10270b57cec5SDimitry Andric // pointer that is passed in as one of the arguments. 10280b57cec5SDimitry Andric // 10290b57cec5SDimitry Andric // Consequently, when reporting the size of the type, we report a pointer 10300b57cec5SDimitry Andric // type pointing to the type of $__lldb_expr_result, not the type itself. 10310b57cec5SDimitry Andric // 10320b57cec5SDimitry Andric // We also do this for any user-declared persistent variables. 10330b57cec5SDimitry Andric compiler_type = compiler_type.GetPointerType(); 10340b57cec5SDimitry Andric value_type = PointerType::get(global_variable->getType(), 0); 10350b57cec5SDimitry Andric } else { 10360b57cec5SDimitry Andric value_type = global_variable->getType(); 10370b57cec5SDimitry Andric } 10380b57cec5SDimitry Andric 1039e8d8bef9SDimitry Andric auto *target = m_execution_unit.GetTarget().get(); 1040bdd1243dSDimitry Andric std::optional<uint64_t> value_size = compiler_type.GetByteSize(target); 10410b57cec5SDimitry Andric if (!value_size) 10420b57cec5SDimitry Andric return false; 1043bdd1243dSDimitry Andric std::optional<size_t> opt_alignment = compiler_type.GetTypeBitAlign(target); 10449dba64beSDimitry Andric if (!opt_alignment) 10459dba64beSDimitry Andric return false; 10469dba64beSDimitry Andric lldb::offset_t value_alignment = (*opt_alignment + 7ull) / 8ull; 10470b57cec5SDimitry Andric 10489dba64beSDimitry Andric LLDB_LOG(log, 10499dba64beSDimitry Andric "Type of \"{0}\" is [clang \"{1}\", llvm \"{2}\"] [size {3}, " 10509dba64beSDimitry Andric "align {4}]", 10519dba64beSDimitry Andric name, 10529dba64beSDimitry Andric lldb_private::ClangUtil::GetQualType(compiler_type).getAsString(), 10539dba64beSDimitry Andric PrintType(value_type), *value_size, value_alignment); 10540b57cec5SDimitry Andric 10559dba64beSDimitry Andric if (named_decl) 10569dba64beSDimitry Andric m_decl_map->AddValueToStruct(named_decl, lldb_private::ConstString(name), 10579dba64beSDimitry Andric llvm_value_ptr, *value_size, 10589dba64beSDimitry Andric value_alignment); 10590eae32dcSDimitry Andric } else if (isa<llvm::Function>(llvm_value_ptr)) { 10609dba64beSDimitry Andric LLDB_LOG(log, "Function pointers aren't handled right now"); 10610b57cec5SDimitry Andric 10620b57cec5SDimitry Andric return false; 10630b57cec5SDimitry Andric } 10640b57cec5SDimitry Andric 10650b57cec5SDimitry Andric return true; 10660b57cec5SDimitry Andric } 10670b57cec5SDimitry Andric 10680b57cec5SDimitry Andric // This function does not report errors; its callers are responsible. 10690b57cec5SDimitry Andric bool IRForTarget::HandleSymbol(Value *symbol) { 107081ad6265SDimitry Andric lldb_private::Log *log(GetLog(LLDBLog::Expressions)); 10710b57cec5SDimitry Andric 10720b57cec5SDimitry Andric lldb_private::ConstString name(symbol->getName().str().c_str()); 10730b57cec5SDimitry Andric 10740b57cec5SDimitry Andric lldb::addr_t symbol_addr = 10750b57cec5SDimitry Andric m_decl_map->GetSymbolAddress(name, lldb::eSymbolTypeAny); 10760b57cec5SDimitry Andric 10770b57cec5SDimitry Andric if (symbol_addr == LLDB_INVALID_ADDRESS) { 10789dba64beSDimitry Andric LLDB_LOG(log, "Symbol \"{0}\" had no address", name); 10790b57cec5SDimitry Andric 10800b57cec5SDimitry Andric return false; 10810b57cec5SDimitry Andric } 10820b57cec5SDimitry Andric 10839dba64beSDimitry Andric LLDB_LOG(log, "Found \"{0}\" at {1}", name, symbol_addr); 10840b57cec5SDimitry Andric 10850b57cec5SDimitry Andric Type *symbol_type = symbol->getType(); 10860b57cec5SDimitry Andric 10870b57cec5SDimitry Andric Constant *symbol_addr_int = ConstantInt::get(m_intptr_ty, symbol_addr, false); 10880b57cec5SDimitry Andric 10890b57cec5SDimitry Andric Value *symbol_addr_ptr = 10900b57cec5SDimitry Andric ConstantExpr::getIntToPtr(symbol_addr_int, symbol_type); 10910b57cec5SDimitry Andric 10929dba64beSDimitry Andric LLDB_LOG(log, "Replacing {0} with {1}", PrintValue(symbol), 10939dba64beSDimitry Andric PrintValue(symbol_addr_ptr)); 10940b57cec5SDimitry Andric 10950b57cec5SDimitry Andric symbol->replaceAllUsesWith(symbol_addr_ptr); 10960b57cec5SDimitry Andric 10970b57cec5SDimitry Andric return true; 10980b57cec5SDimitry Andric } 10990b57cec5SDimitry Andric 11000b57cec5SDimitry Andric bool IRForTarget::MaybeHandleCallArguments(CallInst *Old) { 110181ad6265SDimitry Andric lldb_private::Log *log(GetLog(LLDBLog::Expressions)); 11020b57cec5SDimitry Andric 11039dba64beSDimitry Andric LLDB_LOG(log, "MaybeHandleCallArguments({0})", PrintValue(Old)); 11040b57cec5SDimitry Andric 1105349cc55cSDimitry Andric for (unsigned op_index = 0, num_ops = Old->arg_size(); 11060b57cec5SDimitry Andric op_index < num_ops; ++op_index) 11079dba64beSDimitry Andric // conservatively believe that this is a store 11089dba64beSDimitry Andric if (!MaybeHandleVariable(Old->getArgOperand(op_index))) { 11090b57cec5SDimitry Andric m_error_stream.Printf("Internal error [IRForTarget]: Couldn't rewrite " 11100b57cec5SDimitry Andric "one of the arguments of a function call.\n"); 11110b57cec5SDimitry Andric 11120b57cec5SDimitry Andric return false; 11130b57cec5SDimitry Andric } 11140b57cec5SDimitry Andric 11150b57cec5SDimitry Andric return true; 11160b57cec5SDimitry Andric } 11170b57cec5SDimitry Andric 11180b57cec5SDimitry Andric bool IRForTarget::HandleObjCClass(Value *classlist_reference) { 111981ad6265SDimitry Andric lldb_private::Log *log(GetLog(LLDBLog::Expressions)); 11200b57cec5SDimitry Andric 11210b57cec5SDimitry Andric GlobalVariable *global_variable = 11220b57cec5SDimitry Andric dyn_cast<GlobalVariable>(classlist_reference); 11230b57cec5SDimitry Andric 11240b57cec5SDimitry Andric if (!global_variable) 11250b57cec5SDimitry Andric return false; 11260b57cec5SDimitry Andric 11270b57cec5SDimitry Andric Constant *initializer = global_variable->getInitializer(); 11280b57cec5SDimitry Andric 11290b57cec5SDimitry Andric if (!initializer) 11300b57cec5SDimitry Andric return false; 11310b57cec5SDimitry Andric 11320b57cec5SDimitry Andric if (!initializer->hasName()) 11330b57cec5SDimitry Andric return false; 11340b57cec5SDimitry Andric 11350b57cec5SDimitry Andric StringRef name(initializer->getName()); 11360b57cec5SDimitry Andric lldb_private::ConstString name_cstr(name.str().c_str()); 11370b57cec5SDimitry Andric lldb::addr_t class_ptr = 11380b57cec5SDimitry Andric m_decl_map->GetSymbolAddress(name_cstr, lldb::eSymbolTypeObjCClass); 11390b57cec5SDimitry Andric 11409dba64beSDimitry Andric LLDB_LOG(log, "Found reference to Objective-C class {0} ({1})", name, 11419dba64beSDimitry Andric (unsigned long long)class_ptr); 11420b57cec5SDimitry Andric 11430b57cec5SDimitry Andric if (class_ptr == LLDB_INVALID_ADDRESS) 11440b57cec5SDimitry Andric return false; 11450b57cec5SDimitry Andric 11460b57cec5SDimitry Andric if (global_variable->use_empty()) 11470b57cec5SDimitry Andric return false; 11480b57cec5SDimitry Andric 11490b57cec5SDimitry Andric SmallVector<LoadInst *, 2> load_instructions; 11500b57cec5SDimitry Andric 11510b57cec5SDimitry Andric for (llvm::User *u : global_variable->users()) { 11520b57cec5SDimitry Andric if (LoadInst *load_instruction = dyn_cast<LoadInst>(u)) 11530b57cec5SDimitry Andric load_instructions.push_back(load_instruction); 11540b57cec5SDimitry Andric } 11550b57cec5SDimitry Andric 11560b57cec5SDimitry Andric if (load_instructions.empty()) 11570b57cec5SDimitry Andric return false; 11580b57cec5SDimitry Andric 11590b57cec5SDimitry Andric Constant *class_addr = ConstantInt::get(m_intptr_ty, (uint64_t)class_ptr); 11600b57cec5SDimitry Andric 11610b57cec5SDimitry Andric for (LoadInst *load_instruction : load_instructions) { 11620b57cec5SDimitry Andric Constant *class_bitcast = 11630b57cec5SDimitry Andric ConstantExpr::getIntToPtr(class_addr, load_instruction->getType()); 11640b57cec5SDimitry Andric 11650b57cec5SDimitry Andric load_instruction->replaceAllUsesWith(class_bitcast); 11660b57cec5SDimitry Andric 11670b57cec5SDimitry Andric load_instruction->eraseFromParent(); 11680b57cec5SDimitry Andric } 11690b57cec5SDimitry Andric 11700b57cec5SDimitry Andric return true; 11710b57cec5SDimitry Andric } 11720b57cec5SDimitry Andric 11730b57cec5SDimitry Andric bool IRForTarget::RemoveCXAAtExit(BasicBlock &basic_block) { 11740b57cec5SDimitry Andric std::vector<CallInst *> calls_to_remove; 11750b57cec5SDimitry Andric 11769dba64beSDimitry Andric for (Instruction &inst : basic_block) { 11770b57cec5SDimitry Andric CallInst *call = dyn_cast<CallInst>(&inst); 11780b57cec5SDimitry Andric 11790b57cec5SDimitry Andric // MaybeHandleCallArguments handles error reporting; we are silent here 11800b57cec5SDimitry Andric if (!call) 11810b57cec5SDimitry Andric continue; 11820b57cec5SDimitry Andric 11830b57cec5SDimitry Andric bool remove = false; 11840b57cec5SDimitry Andric 11850b57cec5SDimitry Andric llvm::Function *func = call->getCalledFunction(); 11860b57cec5SDimitry Andric 11870b57cec5SDimitry Andric if (func && func->getName() == "__cxa_atexit") 11880b57cec5SDimitry Andric remove = true; 11890b57cec5SDimitry Andric 11905ffd83dbSDimitry Andric llvm::Value *val = call->getCalledOperand(); 11910b57cec5SDimitry Andric 11920b57cec5SDimitry Andric if (val && val->getName() == "__cxa_atexit") 11930b57cec5SDimitry Andric remove = true; 11940b57cec5SDimitry Andric 11950b57cec5SDimitry Andric if (remove) 11960b57cec5SDimitry Andric calls_to_remove.push_back(call); 11970b57cec5SDimitry Andric } 11980b57cec5SDimitry Andric 11999dba64beSDimitry Andric for (CallInst *ci : calls_to_remove) 12009dba64beSDimitry Andric ci->eraseFromParent(); 12010b57cec5SDimitry Andric 12020b57cec5SDimitry Andric return true; 12030b57cec5SDimitry Andric } 12040b57cec5SDimitry Andric 12050b57cec5SDimitry Andric bool IRForTarget::ResolveCalls(BasicBlock &basic_block) { 12060b57cec5SDimitry Andric // Prepare the current basic block for execution in the remote process 12070b57cec5SDimitry Andric 12089dba64beSDimitry Andric for (Instruction &inst : basic_block) { 12090b57cec5SDimitry Andric CallInst *call = dyn_cast<CallInst>(&inst); 12100b57cec5SDimitry Andric 12110b57cec5SDimitry Andric // MaybeHandleCallArguments handles error reporting; we are silent here 12120b57cec5SDimitry Andric if (call && !MaybeHandleCallArguments(call)) 12130b57cec5SDimitry Andric return false; 12140b57cec5SDimitry Andric } 12150b57cec5SDimitry Andric 12160b57cec5SDimitry Andric return true; 12170b57cec5SDimitry Andric } 12180b57cec5SDimitry Andric 12190b57cec5SDimitry Andric bool IRForTarget::ResolveExternals(Function &llvm_function) { 122081ad6265SDimitry Andric lldb_private::Log *log(GetLog(LLDBLog::Expressions)); 12210b57cec5SDimitry Andric 12220b57cec5SDimitry Andric for (GlobalVariable &global_var : m_module->globals()) { 12239dba64beSDimitry Andric llvm::StringRef global_name = global_var.getName(); 12240b57cec5SDimitry Andric 12259dba64beSDimitry Andric LLDB_LOG(log, "Examining {0}, DeclForGlobalValue returns {1}", global_name, 12260b57cec5SDimitry Andric static_cast<void *>(DeclForGlobal(&global_var))); 12270b57cec5SDimitry Andric 12285f757f3fSDimitry Andric if (global_name.starts_with("OBJC_IVAR")) { 12290b57cec5SDimitry Andric if (!HandleSymbol(&global_var)) { 12309dba64beSDimitry Andric m_error_stream.Format("Error [IRForTarget]: Couldn't find Objective-C " 12319dba64beSDimitry Andric "indirect ivar symbol {0}\n", 12329dba64beSDimitry Andric global_name); 12330b57cec5SDimitry Andric 12340b57cec5SDimitry Andric return false; 12350b57cec5SDimitry Andric } 12369dba64beSDimitry Andric } else if (global_name.contains("OBJC_CLASSLIST_REFERENCES_$")) { 12370b57cec5SDimitry Andric if (!HandleObjCClass(&global_var)) { 12380b57cec5SDimitry Andric m_error_stream.Printf("Error [IRForTarget]: Couldn't resolve the class " 12390b57cec5SDimitry Andric "for an Objective-C static method call\n"); 12400b57cec5SDimitry Andric 12410b57cec5SDimitry Andric return false; 12420b57cec5SDimitry Andric } 12439dba64beSDimitry Andric } else if (global_name.contains("OBJC_CLASSLIST_SUP_REFS_$")) { 12440b57cec5SDimitry Andric if (!HandleObjCClass(&global_var)) { 12450b57cec5SDimitry Andric m_error_stream.Printf("Error [IRForTarget]: Couldn't resolve the class " 12460b57cec5SDimitry Andric "for an Objective-C static method call\n"); 12470b57cec5SDimitry Andric 12480b57cec5SDimitry Andric return false; 12490b57cec5SDimitry Andric } 12500b57cec5SDimitry Andric } else if (DeclForGlobal(&global_var)) { 12510b57cec5SDimitry Andric if (!MaybeHandleVariable(&global_var)) { 12529dba64beSDimitry Andric m_error_stream.Format("Internal error [IRForTarget]: Couldn't rewrite " 12539dba64beSDimitry Andric "external variable {0}\n", 12549dba64beSDimitry Andric global_name); 12550b57cec5SDimitry Andric 12560b57cec5SDimitry Andric return false; 12570b57cec5SDimitry Andric } 12580b57cec5SDimitry Andric } 12590b57cec5SDimitry Andric } 12600b57cec5SDimitry Andric 12610b57cec5SDimitry Andric return true; 12620b57cec5SDimitry Andric } 12630b57cec5SDimitry Andric 12640b57cec5SDimitry Andric static bool isGuardVariableRef(Value *V) { 126506c3fb27SDimitry Andric GlobalVariable *GV = dyn_cast<GlobalVariable>(V); 12660b57cec5SDimitry Andric 12679dba64beSDimitry Andric if (!GV || !GV->hasName() || !isGuardVariableSymbol(GV->getName())) 12680b57cec5SDimitry Andric return false; 12690b57cec5SDimitry Andric 12700b57cec5SDimitry Andric return true; 12710b57cec5SDimitry Andric } 12720b57cec5SDimitry Andric 12730b57cec5SDimitry Andric void IRForTarget::TurnGuardLoadIntoZero(llvm::Instruction *guard_load) { 12740b57cec5SDimitry Andric Constant *zero(Constant::getNullValue(guard_load->getType())); 12750b57cec5SDimitry Andric guard_load->replaceAllUsesWith(zero); 12760b57cec5SDimitry Andric guard_load->eraseFromParent(); 12770b57cec5SDimitry Andric } 12780b57cec5SDimitry Andric 12790b57cec5SDimitry Andric static void ExciseGuardStore(Instruction *guard_store) { 12800b57cec5SDimitry Andric guard_store->eraseFromParent(); 12810b57cec5SDimitry Andric } 12820b57cec5SDimitry Andric 12830b57cec5SDimitry Andric bool IRForTarget::RemoveGuards(BasicBlock &basic_block) { 12840b57cec5SDimitry Andric // Eliminate any reference to guard variables found. 12850b57cec5SDimitry Andric 12860b57cec5SDimitry Andric InstrList guard_loads; 12870b57cec5SDimitry Andric InstrList guard_stores; 12880b57cec5SDimitry Andric 12899dba64beSDimitry Andric for (Instruction &inst : basic_block) { 12900b57cec5SDimitry Andric 12910b57cec5SDimitry Andric if (LoadInst *load = dyn_cast<LoadInst>(&inst)) 12920b57cec5SDimitry Andric if (isGuardVariableRef(load->getPointerOperand())) 12930b57cec5SDimitry Andric guard_loads.push_back(&inst); 12940b57cec5SDimitry Andric 12950b57cec5SDimitry Andric if (StoreInst *store = dyn_cast<StoreInst>(&inst)) 12960b57cec5SDimitry Andric if (isGuardVariableRef(store->getPointerOperand())) 12970b57cec5SDimitry Andric guard_stores.push_back(&inst); 12980b57cec5SDimitry Andric } 12990b57cec5SDimitry Andric 13009dba64beSDimitry Andric for (Instruction *inst : guard_loads) 13019dba64beSDimitry Andric TurnGuardLoadIntoZero(inst); 13020b57cec5SDimitry Andric 13039dba64beSDimitry Andric for (Instruction *inst : guard_stores) 13049dba64beSDimitry Andric ExciseGuardStore(inst); 13050b57cec5SDimitry Andric 13060b57cec5SDimitry Andric return true; 13070b57cec5SDimitry Andric } 13080b57cec5SDimitry Andric 13090b57cec5SDimitry Andric // This function does not report errors; its callers are responsible. 13100b57cec5SDimitry Andric bool IRForTarget::UnfoldConstant(Constant *old_constant, 13110b57cec5SDimitry Andric llvm::Function *llvm_function, 13120b57cec5SDimitry Andric FunctionValueCache &value_maker, 13130b57cec5SDimitry Andric FunctionValueCache &entry_instruction_finder, 13140b57cec5SDimitry Andric lldb_private::Stream &error_stream) { 13150b57cec5SDimitry Andric SmallVector<User *, 16> users; 13160b57cec5SDimitry Andric 13170b57cec5SDimitry Andric // We do this because the use list might change, invalidating our iterator. 13180b57cec5SDimitry Andric // Much better to keep a work list ourselves. 13190b57cec5SDimitry Andric for (llvm::User *u : old_constant->users()) 13200b57cec5SDimitry Andric users.push_back(u); 13210b57cec5SDimitry Andric 13220b57cec5SDimitry Andric for (size_t i = 0; i < users.size(); ++i) { 13230b57cec5SDimitry Andric User *user = users[i]; 13240b57cec5SDimitry Andric 13250b57cec5SDimitry Andric if (Constant *constant = dyn_cast<Constant>(user)) { 13260b57cec5SDimitry Andric // synthesize a new non-constant equivalent of the constant 13270b57cec5SDimitry Andric 13280b57cec5SDimitry Andric if (ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(constant)) { 13290b57cec5SDimitry Andric switch (constant_expr->getOpcode()) { 13300b57cec5SDimitry Andric default: 13310b57cec5SDimitry Andric error_stream.Printf("error [IRForTarget internal]: Unhandled " 13320b57cec5SDimitry Andric "constant expression type: \"%s\"", 13330b57cec5SDimitry Andric PrintValue(constant_expr).c_str()); 13340b57cec5SDimitry Andric return false; 13350b57cec5SDimitry Andric case Instruction::BitCast: { 13360b57cec5SDimitry Andric FunctionValueCache bit_cast_maker( 13370b57cec5SDimitry Andric [&value_maker, &entry_instruction_finder, old_constant, 13380b57cec5SDimitry Andric constant_expr](llvm::Function *function) -> llvm::Value * { 13390b57cec5SDimitry Andric // UnaryExpr 13400b57cec5SDimitry Andric // OperandList[0] is value 13410b57cec5SDimitry Andric 13420b57cec5SDimitry Andric if (constant_expr->getOperand(0) != old_constant) 13430b57cec5SDimitry Andric return constant_expr; 13440b57cec5SDimitry Andric 13450b57cec5SDimitry Andric return new BitCastInst( 13460b57cec5SDimitry Andric value_maker.GetValue(function), constant_expr->getType(), 13470b57cec5SDimitry Andric "", llvm::cast<Instruction>( 13480b57cec5SDimitry Andric entry_instruction_finder.GetValue(function))); 13490b57cec5SDimitry Andric }); 13500b57cec5SDimitry Andric 13510b57cec5SDimitry Andric if (!UnfoldConstant(constant_expr, llvm_function, bit_cast_maker, 13520b57cec5SDimitry Andric entry_instruction_finder, error_stream)) 13530b57cec5SDimitry Andric return false; 13540b57cec5SDimitry Andric } break; 13550b57cec5SDimitry Andric case Instruction::GetElementPtr: { 13560b57cec5SDimitry Andric // GetElementPtrConstantExpr 13570b57cec5SDimitry Andric // OperandList[0] is base 13580b57cec5SDimitry Andric // OperandList[1]... are indices 13590b57cec5SDimitry Andric 13600b57cec5SDimitry Andric FunctionValueCache get_element_pointer_maker( 13610b57cec5SDimitry Andric [&value_maker, &entry_instruction_finder, old_constant, 13620b57cec5SDimitry Andric constant_expr](llvm::Function *function) -> llvm::Value * { 1363fe6060f1SDimitry Andric auto *gep = cast<llvm::GEPOperator>(constant_expr); 1364fe6060f1SDimitry Andric Value *ptr = gep->getPointerOperand(); 13650b57cec5SDimitry Andric 13660b57cec5SDimitry Andric if (ptr == old_constant) 13670b57cec5SDimitry Andric ptr = value_maker.GetValue(function); 13680b57cec5SDimitry Andric 13690b57cec5SDimitry Andric std::vector<Value *> index_vector; 1370fe6060f1SDimitry Andric for (Value *operand : gep->indices()) { 13710b57cec5SDimitry Andric if (operand == old_constant) 13720b57cec5SDimitry Andric operand = value_maker.GetValue(function); 13730b57cec5SDimitry Andric 13740b57cec5SDimitry Andric index_vector.push_back(operand); 13750b57cec5SDimitry Andric } 13760b57cec5SDimitry Andric 13770b57cec5SDimitry Andric ArrayRef<Value *> indices(index_vector); 13780b57cec5SDimitry Andric 13790b57cec5SDimitry Andric return GetElementPtrInst::Create( 1380fe6060f1SDimitry Andric gep->getSourceElementType(), ptr, indices, "", 13810b57cec5SDimitry Andric llvm::cast<Instruction>( 13820b57cec5SDimitry Andric entry_instruction_finder.GetValue(function))); 13830b57cec5SDimitry Andric }); 13840b57cec5SDimitry Andric 13850b57cec5SDimitry Andric if (!UnfoldConstant(constant_expr, llvm_function, 13860b57cec5SDimitry Andric get_element_pointer_maker, 13870b57cec5SDimitry Andric entry_instruction_finder, error_stream)) 13880b57cec5SDimitry Andric return false; 13890b57cec5SDimitry Andric } break; 13900b57cec5SDimitry Andric } 13910b57cec5SDimitry Andric } else { 13920b57cec5SDimitry Andric error_stream.Printf( 13930b57cec5SDimitry Andric "error [IRForTarget internal]: Unhandled constant type: \"%s\"", 13940b57cec5SDimitry Andric PrintValue(constant).c_str()); 13950b57cec5SDimitry Andric return false; 13960b57cec5SDimitry Andric } 13970b57cec5SDimitry Andric } else { 13980b57cec5SDimitry Andric if (Instruction *inst = llvm::dyn_cast<Instruction>(user)) { 13990b57cec5SDimitry Andric if (llvm_function && inst->getParent()->getParent() != llvm_function) { 14000b57cec5SDimitry Andric error_stream.PutCString("error: Capturing non-local variables in " 14010b57cec5SDimitry Andric "expressions is unsupported.\n"); 14020b57cec5SDimitry Andric return false; 14030b57cec5SDimitry Andric } 14040b57cec5SDimitry Andric inst->replaceUsesOfWith( 14050b57cec5SDimitry Andric old_constant, value_maker.GetValue(inst->getParent()->getParent())); 14060b57cec5SDimitry Andric } else { 14070b57cec5SDimitry Andric error_stream.Printf( 14080b57cec5SDimitry Andric "error [IRForTarget internal]: Unhandled non-constant type: \"%s\"", 14090b57cec5SDimitry Andric PrintValue(user).c_str()); 14100b57cec5SDimitry Andric return false; 14110b57cec5SDimitry Andric } 14120b57cec5SDimitry Andric } 14130b57cec5SDimitry Andric } 14140b57cec5SDimitry Andric 14150b57cec5SDimitry Andric if (!isa<GlobalValue>(old_constant)) { 14160b57cec5SDimitry Andric old_constant->destroyConstant(); 14170b57cec5SDimitry Andric } 14180b57cec5SDimitry Andric 14190b57cec5SDimitry Andric return true; 14200b57cec5SDimitry Andric } 14210b57cec5SDimitry Andric 14220b57cec5SDimitry Andric bool IRForTarget::ReplaceVariables(Function &llvm_function) { 14230b57cec5SDimitry Andric if (!m_resolve_vars) 14240b57cec5SDimitry Andric return true; 14250b57cec5SDimitry Andric 142681ad6265SDimitry Andric lldb_private::Log *log(GetLog(LLDBLog::Expressions)); 14270b57cec5SDimitry Andric 14280b57cec5SDimitry Andric m_decl_map->DoStructLayout(); 14290b57cec5SDimitry Andric 14309dba64beSDimitry Andric LLDB_LOG(log, "Element arrangement:"); 14310b57cec5SDimitry Andric 14320b57cec5SDimitry Andric uint32_t num_elements; 14330b57cec5SDimitry Andric uint32_t element_index; 14340b57cec5SDimitry Andric 14350b57cec5SDimitry Andric size_t size; 14360b57cec5SDimitry Andric lldb::offset_t alignment; 14370b57cec5SDimitry Andric 14380b57cec5SDimitry Andric if (!m_decl_map->GetStructInfo(num_elements, size, alignment)) 14390b57cec5SDimitry Andric return false; 14400b57cec5SDimitry Andric 14410b57cec5SDimitry Andric Function::arg_iterator iter(llvm_function.arg_begin()); 14420b57cec5SDimitry Andric 14430b57cec5SDimitry Andric if (iter == llvm_function.arg_end()) { 14440b57cec5SDimitry Andric m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes no " 14450b57cec5SDimitry Andric "arguments (should take at least a struct pointer)"); 14460b57cec5SDimitry Andric 14470b57cec5SDimitry Andric return false; 14480b57cec5SDimitry Andric } 14490b57cec5SDimitry Andric 14500b57cec5SDimitry Andric Argument *argument = &*iter; 14510b57cec5SDimitry Andric 1452*0fca6ea1SDimitry Andric if (argument->getName() == "this") { 14530b57cec5SDimitry Andric ++iter; 14540b57cec5SDimitry Andric 14550b57cec5SDimitry Andric if (iter == llvm_function.arg_end()) { 14560b57cec5SDimitry Andric m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes only " 14570b57cec5SDimitry Andric "'this' argument (should take a struct pointer " 14580b57cec5SDimitry Andric "too)"); 14590b57cec5SDimitry Andric 14600b57cec5SDimitry Andric return false; 14610b57cec5SDimitry Andric } 14620b57cec5SDimitry Andric 14630b57cec5SDimitry Andric argument = &*iter; 1464*0fca6ea1SDimitry Andric } else if (argument->getName() == "self") { 14650b57cec5SDimitry Andric ++iter; 14660b57cec5SDimitry Andric 14670b57cec5SDimitry Andric if (iter == llvm_function.arg_end()) { 14680b57cec5SDimitry Andric m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes only " 14690b57cec5SDimitry Andric "'self' argument (should take '_cmd' and a struct " 14700b57cec5SDimitry Andric "pointer too)"); 14710b57cec5SDimitry Andric 14720b57cec5SDimitry Andric return false; 14730b57cec5SDimitry Andric } 14740b57cec5SDimitry Andric 1475*0fca6ea1SDimitry Andric if (iter->getName() != "_cmd") { 14769dba64beSDimitry Andric m_error_stream.Format("Internal error [IRForTarget]: Wrapper takes '{0}' " 14770b57cec5SDimitry Andric "after 'self' argument (should take '_cmd')", 14789dba64beSDimitry Andric iter->getName()); 14790b57cec5SDimitry Andric 14800b57cec5SDimitry Andric return false; 14810b57cec5SDimitry Andric } 14820b57cec5SDimitry Andric 14830b57cec5SDimitry Andric ++iter; 14840b57cec5SDimitry Andric 14850b57cec5SDimitry Andric if (iter == llvm_function.arg_end()) { 14860b57cec5SDimitry Andric m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes only " 14870b57cec5SDimitry Andric "'self' and '_cmd' arguments (should take a struct " 14880b57cec5SDimitry Andric "pointer too)"); 14890b57cec5SDimitry Andric 14900b57cec5SDimitry Andric return false; 14910b57cec5SDimitry Andric } 14920b57cec5SDimitry Andric 14930b57cec5SDimitry Andric argument = &*iter; 14940b57cec5SDimitry Andric } 14950b57cec5SDimitry Andric 1496*0fca6ea1SDimitry Andric if (argument->getName() != "$__lldb_arg") { 14979dba64beSDimitry Andric m_error_stream.Format("Internal error [IRForTarget]: Wrapper takes an " 14989dba64beSDimitry Andric "argument named '{0}' instead of the struct pointer", 14999dba64beSDimitry Andric argument->getName()); 15000b57cec5SDimitry Andric 15010b57cec5SDimitry Andric return false; 15020b57cec5SDimitry Andric } 15030b57cec5SDimitry Andric 15049dba64beSDimitry Andric LLDB_LOG(log, "Arg: \"{0}\"", PrintValue(argument)); 15050b57cec5SDimitry Andric 15060b57cec5SDimitry Andric BasicBlock &entry_block(llvm_function.getEntryBlock()); 15070b57cec5SDimitry Andric Instruction *FirstEntryInstruction(entry_block.getFirstNonPHIOrDbg()); 15080b57cec5SDimitry Andric 15090b57cec5SDimitry Andric if (!FirstEntryInstruction) { 15100b57cec5SDimitry Andric m_error_stream.Printf("Internal error [IRForTarget]: Couldn't find the " 15110b57cec5SDimitry Andric "first instruction in the wrapper for use in " 15120b57cec5SDimitry Andric "rewriting"); 15130b57cec5SDimitry Andric 15140b57cec5SDimitry Andric return false; 15150b57cec5SDimitry Andric } 15160b57cec5SDimitry Andric 15170b57cec5SDimitry Andric LLVMContext &context(m_module->getContext()); 15180b57cec5SDimitry Andric IntegerType *offset_type(Type::getInt32Ty(context)); 15190b57cec5SDimitry Andric 15200b57cec5SDimitry Andric if (!offset_type) { 15210b57cec5SDimitry Andric m_error_stream.Printf( 15220b57cec5SDimitry Andric "Internal error [IRForTarget]: Couldn't produce an offset type"); 15230b57cec5SDimitry Andric 15240b57cec5SDimitry Andric return false; 15250b57cec5SDimitry Andric } 15260b57cec5SDimitry Andric 15270b57cec5SDimitry Andric for (element_index = 0; element_index < num_elements; ++element_index) { 15280b57cec5SDimitry Andric const clang::NamedDecl *decl = nullptr; 15290b57cec5SDimitry Andric Value *value = nullptr; 15300b57cec5SDimitry Andric lldb::offset_t offset; 15310b57cec5SDimitry Andric lldb_private::ConstString name; 15320b57cec5SDimitry Andric 15330b57cec5SDimitry Andric if (!m_decl_map->GetStructElement(decl, value, offset, name, 15340b57cec5SDimitry Andric element_index)) { 15350b57cec5SDimitry Andric m_error_stream.Printf( 15360b57cec5SDimitry Andric "Internal error [IRForTarget]: Structure information is incomplete"); 15370b57cec5SDimitry Andric 15380b57cec5SDimitry Andric return false; 15390b57cec5SDimitry Andric } 15400b57cec5SDimitry Andric 15419dba64beSDimitry Andric LLDB_LOG(log, " \"{0}\" (\"{1}\") placed at {2}", name, 15429dba64beSDimitry Andric decl->getNameAsString(), offset); 15430b57cec5SDimitry Andric 15440b57cec5SDimitry Andric if (value) { 15459dba64beSDimitry Andric LLDB_LOG(log, " Replacing [{0}]", PrintValue(value)); 15460b57cec5SDimitry Andric 15470b57cec5SDimitry Andric FunctionValueCache body_result_maker( 15480b57cec5SDimitry Andric [this, name, offset_type, offset, argument, 15490b57cec5SDimitry Andric value](llvm::Function *function) -> llvm::Value * { 15500b57cec5SDimitry Andric // Per the comment at ASTResultSynthesizer::SynthesizeBodyResult, 15510b57cec5SDimitry Andric // in cases where the result variable is an rvalue, we have to 15520b57cec5SDimitry Andric // synthesize a dereference of the appropriate structure entry in 15530b57cec5SDimitry Andric // order to produce the static variable that the AST thinks it is 15540b57cec5SDimitry Andric // accessing. 15550b57cec5SDimitry Andric 15560b57cec5SDimitry Andric llvm::Instruction *entry_instruction = llvm::cast<Instruction>( 15570b57cec5SDimitry Andric m_entry_instruction_finder.GetValue(function)); 15580b57cec5SDimitry Andric 155981ad6265SDimitry Andric Type *int8Ty = Type::getInt8Ty(function->getContext()); 15600b57cec5SDimitry Andric ConstantInt *offset_int( 15610b57cec5SDimitry Andric ConstantInt::get(offset_type, offset, true)); 15620b57cec5SDimitry Andric GetElementPtrInst *get_element_ptr = GetElementPtrInst::Create( 156381ad6265SDimitry Andric int8Ty, argument, offset_int, "", entry_instruction); 15640b57cec5SDimitry Andric 15650b57cec5SDimitry Andric if (name == m_result_name && !m_result_is_pointer) { 156606c3fb27SDimitry Andric LoadInst *load = new LoadInst(value->getType(), get_element_ptr, 156706c3fb27SDimitry Andric "", entry_instruction); 15680b57cec5SDimitry Andric 15690b57cec5SDimitry Andric return load; 15700b57cec5SDimitry Andric } else { 157106c3fb27SDimitry Andric return get_element_ptr; 15720b57cec5SDimitry Andric } 15730b57cec5SDimitry Andric }); 15740b57cec5SDimitry Andric 15750b57cec5SDimitry Andric if (Constant *constant = dyn_cast<Constant>(value)) { 15760b57cec5SDimitry Andric if (!UnfoldConstant(constant, &llvm_function, body_result_maker, 15770b57cec5SDimitry Andric m_entry_instruction_finder, m_error_stream)) { 15780b57cec5SDimitry Andric return false; 15790b57cec5SDimitry Andric } 15800b57cec5SDimitry Andric } else if (Instruction *instruction = dyn_cast<Instruction>(value)) { 15810b57cec5SDimitry Andric if (instruction->getParent()->getParent() != &llvm_function) { 15820b57cec5SDimitry Andric m_error_stream.PutCString("error: Capturing non-local variables in " 15830b57cec5SDimitry Andric "expressions is unsupported.\n"); 15840b57cec5SDimitry Andric return false; 15850b57cec5SDimitry Andric } 15860b57cec5SDimitry Andric value->replaceAllUsesWith( 15870b57cec5SDimitry Andric body_result_maker.GetValue(instruction->getParent()->getParent())); 15880b57cec5SDimitry Andric } else { 15899dba64beSDimitry Andric LLDB_LOG(log, "Unhandled non-constant type: \"{0}\"", 15909dba64beSDimitry Andric PrintValue(value)); 15910b57cec5SDimitry Andric return false; 15920b57cec5SDimitry Andric } 15930b57cec5SDimitry Andric 15940b57cec5SDimitry Andric if (GlobalVariable *var = dyn_cast<GlobalVariable>(value)) 15950b57cec5SDimitry Andric var->eraseFromParent(); 15960b57cec5SDimitry Andric } 15970b57cec5SDimitry Andric } 15980b57cec5SDimitry Andric 15999dba64beSDimitry Andric LLDB_LOG(log, "Total structure [align {0}, size {1}]", (int64_t)alignment, 16009dba64beSDimitry Andric (uint64_t)size); 16010b57cec5SDimitry Andric 16020b57cec5SDimitry Andric return true; 16030b57cec5SDimitry Andric } 16040b57cec5SDimitry Andric 16050b57cec5SDimitry Andric bool IRForTarget::runOnModule(Module &llvm_module) { 160681ad6265SDimitry Andric lldb_private::Log *log(GetLog(LLDBLog::Expressions)); 16070b57cec5SDimitry Andric 16080b57cec5SDimitry Andric m_module = &llvm_module; 16095ffd83dbSDimitry Andric m_target_data = std::make_unique<DataLayout>(m_module); 16100b57cec5SDimitry Andric m_intptr_ty = llvm::Type::getIntNTy(m_module->getContext(), 16110b57cec5SDimitry Andric m_target_data->getPointerSizeInBits()); 16120b57cec5SDimitry Andric 16130b57cec5SDimitry Andric if (log) { 16140b57cec5SDimitry Andric std::string s; 16150b57cec5SDimitry Andric raw_string_ostream oss(s); 16160b57cec5SDimitry Andric 16170b57cec5SDimitry Andric m_module->print(oss, nullptr); 16180b57cec5SDimitry Andric 16190b57cec5SDimitry Andric oss.flush(); 16200b57cec5SDimitry Andric 16219dba64beSDimitry Andric LLDB_LOG(log, "Module as passed in to IRForTarget: \n\"{0}\"", s); 16220b57cec5SDimitry Andric } 16230b57cec5SDimitry Andric 16240b57cec5SDimitry Andric Function *const main_function = 16250b57cec5SDimitry Andric m_func_name.IsEmpty() ? nullptr 16260b57cec5SDimitry Andric : m_module->getFunction(m_func_name.GetStringRef()); 16270b57cec5SDimitry Andric 16280b57cec5SDimitry Andric if (!m_func_name.IsEmpty() && !main_function) { 16299dba64beSDimitry Andric LLDB_LOG(log, "Couldn't find \"{0}()\" in the module", m_func_name); 16300b57cec5SDimitry Andric 16319dba64beSDimitry Andric m_error_stream.Format("Internal error [IRForTarget]: Couldn't find wrapper " 16329dba64beSDimitry Andric "'{0}' in the module", 16339dba64beSDimitry Andric m_func_name); 16340b57cec5SDimitry Andric 16350b57cec5SDimitry Andric return false; 16360b57cec5SDimitry Andric } 16370b57cec5SDimitry Andric 16380b57cec5SDimitry Andric if (main_function) { 16390b57cec5SDimitry Andric if (!FixFunctionLinkage(*main_function)) { 16409dba64beSDimitry Andric LLDB_LOG(log, "Couldn't fix the linkage for the function"); 16410b57cec5SDimitry Andric 16420b57cec5SDimitry Andric return false; 16430b57cec5SDimitry Andric } 16440b57cec5SDimitry Andric } 16450b57cec5SDimitry Andric 16460b57cec5SDimitry Andric //////////////////////////////////////////////////////////// 16470b57cec5SDimitry Andric // Replace $__lldb_expr_result with a persistent variable 16480b57cec5SDimitry Andric // 16490b57cec5SDimitry Andric 16500b57cec5SDimitry Andric if (main_function) { 16510b57cec5SDimitry Andric if (!CreateResultVariable(*main_function)) { 16529dba64beSDimitry Andric LLDB_LOG(log, "CreateResultVariable() failed"); 16530b57cec5SDimitry Andric 16540b57cec5SDimitry Andric // CreateResultVariable() reports its own errors, so we don't do so here 16550b57cec5SDimitry Andric 16560b57cec5SDimitry Andric return false; 16570b57cec5SDimitry Andric } 16580b57cec5SDimitry Andric } 16590b57cec5SDimitry Andric 16600b57cec5SDimitry Andric if (log && log->GetVerbose()) { 16610b57cec5SDimitry Andric std::string s; 16620b57cec5SDimitry Andric raw_string_ostream oss(s); 16630b57cec5SDimitry Andric 16640b57cec5SDimitry Andric m_module->print(oss, nullptr); 16650b57cec5SDimitry Andric 16660b57cec5SDimitry Andric oss.flush(); 16670b57cec5SDimitry Andric 16689dba64beSDimitry Andric LLDB_LOG(log, "Module after creating the result variable: \n\"{0}\"", s); 16690b57cec5SDimitry Andric } 16700b57cec5SDimitry Andric 16719dba64beSDimitry Andric for (llvm::Function &function : *m_module) { 16729dba64beSDimitry Andric for (BasicBlock &bb : function) { 16739dba64beSDimitry Andric if (!RemoveGuards(bb)) { 16749dba64beSDimitry Andric LLDB_LOG(log, "RemoveGuards() failed"); 16750b57cec5SDimitry Andric 16760b57cec5SDimitry Andric // RemoveGuards() reports its own errors, so we don't do so here 16770b57cec5SDimitry Andric 16780b57cec5SDimitry Andric return false; 16790b57cec5SDimitry Andric } 16800b57cec5SDimitry Andric 16819dba64beSDimitry Andric if (!RewritePersistentAllocs(bb)) { 16829dba64beSDimitry Andric LLDB_LOG(log, "RewritePersistentAllocs() failed"); 16830b57cec5SDimitry Andric 16840b57cec5SDimitry Andric // RewritePersistentAllocs() reports its own errors, so we don't do so 16850b57cec5SDimitry Andric // here 16860b57cec5SDimitry Andric 16870b57cec5SDimitry Andric return false; 16880b57cec5SDimitry Andric } 16890b57cec5SDimitry Andric 16909dba64beSDimitry Andric if (!RemoveCXAAtExit(bb)) { 16919dba64beSDimitry Andric LLDB_LOG(log, "RemoveCXAAtExit() failed"); 16920b57cec5SDimitry Andric 16930b57cec5SDimitry Andric // RemoveCXAAtExit() reports its own errors, so we don't do so here 16940b57cec5SDimitry Andric 16950b57cec5SDimitry Andric return false; 16960b57cec5SDimitry Andric } 16970b57cec5SDimitry Andric } 16980b57cec5SDimitry Andric } 16990b57cec5SDimitry Andric 17000b57cec5SDimitry Andric /////////////////////////////////////////////////////////////////////////////// 17010b57cec5SDimitry Andric // Fix all Objective-C constant strings to use NSStringWithCString:encoding: 17020b57cec5SDimitry Andric // 17030b57cec5SDimitry Andric 17040b57cec5SDimitry Andric if (!RewriteObjCConstStrings()) { 17059dba64beSDimitry Andric LLDB_LOG(log, "RewriteObjCConstStrings() failed"); 17060b57cec5SDimitry Andric 17070b57cec5SDimitry Andric // RewriteObjCConstStrings() reports its own errors, so we don't do so here 17080b57cec5SDimitry Andric 17090b57cec5SDimitry Andric return false; 17100b57cec5SDimitry Andric } 17110b57cec5SDimitry Andric 17129dba64beSDimitry Andric for (llvm::Function &function : *m_module) { 17139dba64beSDimitry Andric for (llvm::BasicBlock &bb : function) { 17149dba64beSDimitry Andric if (!RewriteObjCSelectors(bb)) { 17159dba64beSDimitry Andric LLDB_LOG(log, "RewriteObjCSelectors() failed"); 17160b57cec5SDimitry Andric 17170b57cec5SDimitry Andric // RewriteObjCSelectors() reports its own errors, so we don't do so 17180b57cec5SDimitry Andric // here 17190b57cec5SDimitry Andric 17200b57cec5SDimitry Andric return false; 17210b57cec5SDimitry Andric } 17220b57cec5SDimitry Andric } 17230b57cec5SDimitry Andric } 17240b57cec5SDimitry Andric 17259dba64beSDimitry Andric for (llvm::Function &function : *m_module) { 17269dba64beSDimitry Andric for (BasicBlock &bb : function) { 17279dba64beSDimitry Andric if (!ResolveCalls(bb)) { 17289dba64beSDimitry Andric LLDB_LOG(log, "ResolveCalls() failed"); 17290b57cec5SDimitry Andric 17300b57cec5SDimitry Andric // ResolveCalls() reports its own errors, so we don't do so here 17310b57cec5SDimitry Andric 17320b57cec5SDimitry Andric return false; 17330b57cec5SDimitry Andric } 17340b57cec5SDimitry Andric } 17350b57cec5SDimitry Andric } 17360b57cec5SDimitry Andric 17370b57cec5SDimitry Andric //////////////////////////////////////////////////////////////////////// 17380b57cec5SDimitry Andric // Run function-level passes that only make sense on the main function 17390b57cec5SDimitry Andric // 17400b57cec5SDimitry Andric 17410b57cec5SDimitry Andric if (main_function) { 17420b57cec5SDimitry Andric if (!ResolveExternals(*main_function)) { 17439dba64beSDimitry Andric LLDB_LOG(log, "ResolveExternals() failed"); 17440b57cec5SDimitry Andric 17450b57cec5SDimitry Andric // ResolveExternals() reports its own errors, so we don't do so here 17460b57cec5SDimitry Andric 17470b57cec5SDimitry Andric return false; 17480b57cec5SDimitry Andric } 17490b57cec5SDimitry Andric 17500b57cec5SDimitry Andric if (!ReplaceVariables(*main_function)) { 17519dba64beSDimitry Andric LLDB_LOG(log, "ReplaceVariables() failed"); 17520b57cec5SDimitry Andric 17530b57cec5SDimitry Andric // ReplaceVariables() reports its own errors, so we don't do so here 17540b57cec5SDimitry Andric 17550b57cec5SDimitry Andric return false; 17560b57cec5SDimitry Andric } 17570b57cec5SDimitry Andric } 17580b57cec5SDimitry Andric 17590b57cec5SDimitry Andric if (log && log->GetVerbose()) { 17600b57cec5SDimitry Andric std::string s; 17610b57cec5SDimitry Andric raw_string_ostream oss(s); 17620b57cec5SDimitry Andric 17630b57cec5SDimitry Andric m_module->print(oss, nullptr); 17640b57cec5SDimitry Andric 17650b57cec5SDimitry Andric oss.flush(); 17660b57cec5SDimitry Andric 17679dba64beSDimitry Andric LLDB_LOG(log, "Module after preparing for execution: \n\"{0}\"", s); 17680b57cec5SDimitry Andric } 17690b57cec5SDimitry Andric 17700b57cec5SDimitry Andric return true; 17710b57cec5SDimitry Andric } 1772