Path: blob/main/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
39648 views
//===-- IRForTarget.cpp ---------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "IRForTarget.h"910#include "ClangExpressionDeclMap.h"11#include "ClangUtil.h"1213#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"14#include "llvm/IR/Constants.h"15#include "llvm/IR/DataLayout.h"16#include "llvm/IR/Operator.h"17#include "llvm/IR/InstrTypes.h"18#include "llvm/IR/Instructions.h"19#include "llvm/IR/Intrinsics.h"20#include "llvm/IR/LegacyPassManager.h"21#include "llvm/IR/Metadata.h"22#include "llvm/IR/Module.h"23#include "llvm/IR/ValueSymbolTable.h"24#include "llvm/Support/raw_ostream.h"25#include "llvm/Transforms/IPO.h"2627#include "clang/AST/ASTContext.h"2829#include "lldb/Core/dwarf.h"30#include "lldb/Expression/IRExecutionUnit.h"31#include "lldb/Expression/IRInterpreter.h"32#include "lldb/Symbol/CompilerType.h"33#include "lldb/Utility/ConstString.h"34#include "lldb/Utility/DataBufferHeap.h"35#include "lldb/Utility/Endian.h"36#include "lldb/Utility/LLDBLog.h"37#include "lldb/Utility/Log.h"38#include "lldb/Utility/Scalar.h"39#include "lldb/Utility/StreamString.h"4041#include <map>42#include <optional>4344using namespace llvm;45using lldb_private::LLDBLog;4647typedef SmallVector<Instruction *, 2> InstrList;4849IRForTarget::FunctionValueCache::FunctionValueCache(Maker const &maker)50: m_maker(maker), m_values() {}5152IRForTarget::FunctionValueCache::~FunctionValueCache() = default;5354llvm::Value *55IRForTarget::FunctionValueCache::GetValue(llvm::Function *function) {56if (!m_values.count(function)) {57llvm::Value *ret = m_maker(function);58m_values[function] = ret;59return ret;60}61return m_values[function];62}6364static llvm::Value *FindEntryInstruction(llvm::Function *function) {65if (function->empty())66return nullptr;6768return function->getEntryBlock().getFirstNonPHIOrDbg();69}7071IRForTarget::IRForTarget(lldb_private::ClangExpressionDeclMap *decl_map,72bool resolve_vars,73lldb_private::IRExecutionUnit &execution_unit,74lldb_private::Stream &error_stream,75const char *func_name)76: m_resolve_vars(resolve_vars), m_func_name(func_name),77m_decl_map(decl_map), m_error_stream(error_stream),78m_execution_unit(execution_unit),79m_entry_instruction_finder(FindEntryInstruction) {}8081/* Handy utility functions used at several places in the code */8283static std::string PrintValue(const Value *value, bool truncate = false) {84std::string s;85if (value) {86raw_string_ostream rso(s);87value->print(rso);88rso.flush();89if (truncate)90s.resize(s.length() - 1);91}92return s;93}9495static std::string PrintType(const llvm::Type *type, bool truncate = false) {96std::string s;97raw_string_ostream rso(s);98type->print(rso);99rso.flush();100if (truncate)101s.resize(s.length() - 1);102return s;103}104105bool IRForTarget::FixFunctionLinkage(llvm::Function &llvm_function) {106llvm_function.setLinkage(GlobalValue::ExternalLinkage);107108return true;109}110111clang::NamedDecl *IRForTarget::DeclForGlobal(const GlobalValue *global_val,112Module *module) {113NamedMDNode *named_metadata =114module->getNamedMetadata("clang.global.decl.ptrs");115116if (!named_metadata)117return nullptr;118119unsigned num_nodes = named_metadata->getNumOperands();120unsigned node_index;121122for (node_index = 0; node_index < num_nodes; ++node_index) {123llvm::MDNode *metadata_node =124dyn_cast<llvm::MDNode>(named_metadata->getOperand(node_index));125if (!metadata_node)126return nullptr;127128if (metadata_node->getNumOperands() != 2)129continue;130131if (mdconst::dyn_extract_or_null<GlobalValue>(132metadata_node->getOperand(0)) != global_val)133continue;134135ConstantInt *constant_int =136mdconst::dyn_extract<ConstantInt>(metadata_node->getOperand(1));137138if (!constant_int)139return nullptr;140141uintptr_t ptr = constant_int->getZExtValue();142143return reinterpret_cast<clang::NamedDecl *>(ptr);144}145146return nullptr;147}148149clang::NamedDecl *IRForTarget::DeclForGlobal(GlobalValue *global_val) {150return DeclForGlobal(global_val, m_module);151}152153/// Returns true iff the mangled symbol is for a static guard variable.154static bool isGuardVariableSymbol(llvm::StringRef mangled_symbol,155bool check_ms_abi = true) {156bool result =157mangled_symbol.starts_with("_ZGV"); // Itanium ABI guard variable158if (check_ms_abi)159result |= mangled_symbol.ends_with("@4IA"); // Microsoft ABI160return result;161}162163bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) {164lldb_private::Log *log(GetLog(LLDBLog::Expressions));165166if (!m_resolve_vars)167return true;168169// Find the result variable. If it doesn't exist, we can give up right here.170171ValueSymbolTable &value_symbol_table = m_module->getValueSymbolTable();172173llvm::StringRef result_name;174bool found_result = false;175176for (StringMapEntry<llvm::Value *> &value_symbol : value_symbol_table) {177result_name = value_symbol.first();178179// Check if this is a guard variable. It seems this causes some hiccups180// on Windows, so let's only check for Itanium guard variables.181bool is_guard_var = isGuardVariableSymbol(result_name, /*MS ABI*/ false);182183if (result_name.contains("$__lldb_expr_result_ptr") && !is_guard_var) {184found_result = true;185m_result_is_pointer = true;186break;187}188189if (result_name.contains("$__lldb_expr_result") && !is_guard_var) {190found_result = true;191m_result_is_pointer = false;192break;193}194}195196if (!found_result) {197LLDB_LOG(log, "Couldn't find result variable");198199return true;200}201202LLDB_LOG(log, "Result name: \"{0}\"", result_name);203204Value *result_value = m_module->getNamedValue(result_name);205206if (!result_value) {207LLDB_LOG(log, "Result variable had no data");208209m_error_stream.Format("Internal error [IRForTarget]: Result variable's "210"name ({0}) exists, but not its definition\n",211result_name);212213return false;214}215216LLDB_LOG(log, "Found result in the IR: \"{0}\"",217PrintValue(result_value, false));218219GlobalVariable *result_global = dyn_cast<GlobalVariable>(result_value);220221if (!result_global) {222LLDB_LOG(log, "Result variable isn't a GlobalVariable");223224m_error_stream.Format("Internal error [IRForTarget]: Result variable ({0}) "225"is defined, but is not a global variable\n",226result_name);227228return false;229}230231clang::NamedDecl *result_decl = DeclForGlobal(result_global);232if (!result_decl) {233LLDB_LOG(log, "Result variable doesn't have a corresponding Decl");234235m_error_stream.Format("Internal error [IRForTarget]: Result variable ({0}) "236"does not have a corresponding Clang entity\n",237result_name);238239return false;240}241242if (log) {243std::string decl_desc_str;244raw_string_ostream decl_desc_stream(decl_desc_str);245result_decl->print(decl_desc_stream);246decl_desc_stream.flush();247248LLDB_LOG(log, "Found result decl: \"{0}\"", decl_desc_str);249}250251clang::VarDecl *result_var = dyn_cast<clang::VarDecl>(result_decl);252if (!result_var) {253LLDB_LOG(log, "Result variable Decl isn't a VarDecl");254255m_error_stream.Format("Internal error [IRForTarget]: Result variable "256"({0})'s corresponding Clang entity isn't a "257"variable\n",258result_name);259260return false;261}262263// Get the next available result name from m_decl_map and create the264// persistent variable for it265266// If the result is an Lvalue, it is emitted as a pointer; see267// ASTResultSynthesizer::SynthesizeBodyResult.268if (m_result_is_pointer) {269clang::QualType pointer_qual_type = result_var->getType();270const clang::Type *pointer_type = pointer_qual_type.getTypePtr();271272const clang::PointerType *pointer_pointertype =273pointer_type->getAs<clang::PointerType>();274const clang::ObjCObjectPointerType *pointer_objcobjpointertype =275pointer_type->getAs<clang::ObjCObjectPointerType>();276277if (pointer_pointertype) {278clang::QualType element_qual_type = pointer_pointertype->getPointeeType();279280m_result_type = lldb_private::TypeFromParser(281m_decl_map->GetTypeSystem()->GetType(element_qual_type));282} else if (pointer_objcobjpointertype) {283clang::QualType element_qual_type =284clang::QualType(pointer_objcobjpointertype->getObjectType(), 0);285286m_result_type = lldb_private::TypeFromParser(287m_decl_map->GetTypeSystem()->GetType(element_qual_type));288} else {289LLDB_LOG(log, "Expected result to have pointer type, but it did not");290291m_error_stream.Format("Internal error [IRForTarget]: Lvalue result ({0}) "292"is not a pointer variable\n",293result_name);294295return false;296}297} else {298m_result_type = lldb_private::TypeFromParser(299m_decl_map->GetTypeSystem()->GetType(result_var->getType()));300}301302lldb::TargetSP target_sp(m_execution_unit.GetTarget());303std::optional<uint64_t> bit_size = m_result_type.GetBitSize(target_sp.get());304if (!bit_size) {305lldb_private::StreamString type_desc_stream;306m_result_type.DumpTypeDescription(&type_desc_stream);307308LLDB_LOG(log, "Result type has unknown size");309310m_error_stream.Printf("Error [IRForTarget]: Size of result type '%s' "311"couldn't be determined\n",312type_desc_stream.GetData());313return false;314}315316if (log) {317lldb_private::StreamString type_desc_stream;318m_result_type.DumpTypeDescription(&type_desc_stream);319320LLDB_LOG(log, "Result decl type: \"{0}\"", type_desc_stream.GetData());321}322323m_result_name = lldb_private::ConstString("$RESULT_NAME");324325LLDB_LOG(log, "Creating a new result global: \"{0}\" with size {1}",326m_result_name,327m_result_type.GetByteSize(target_sp.get()).value_or(0));328329// Construct a new result global and set up its metadata330331GlobalVariable *new_result_global = new GlobalVariable(332(*m_module), result_global->getValueType(), false, /* not constant */333GlobalValue::ExternalLinkage, nullptr, /* no initializer */334m_result_name.GetCString());335336// It's too late in compilation to create a new VarDecl for this, but we337// don't need to. We point the metadata at the old VarDecl. This creates an338// odd anomaly: a variable with a Value whose name is something like $0 and a339// Decl whose name is $__lldb_expr_result. This condition is handled in340// ClangExpressionDeclMap::DoMaterialize, and the name of the variable is341// fixed up.342343ConstantInt *new_constant_int =344ConstantInt::get(llvm::Type::getInt64Ty(m_module->getContext()),345reinterpret_cast<uintptr_t>(result_decl), false);346347llvm::Metadata *values[2];348values[0] = ConstantAsMetadata::get(new_result_global);349values[1] = ConstantAsMetadata::get(new_constant_int);350351ArrayRef<Metadata *> value_ref(values, 2);352353MDNode *persistent_global_md = MDNode::get(m_module->getContext(), value_ref);354NamedMDNode *named_metadata =355m_module->getNamedMetadata("clang.global.decl.ptrs");356named_metadata->addOperand(persistent_global_md);357358LLDB_LOG(log, "Replacing \"{0}\" with \"{1}\"", PrintValue(result_global),359PrintValue(new_result_global));360361if (result_global->use_empty()) {362// We need to synthesize a store for this variable, because otherwise363// there's nothing to put into its equivalent persistent variable.364365BasicBlock &entry_block(llvm_function.getEntryBlock());366Instruction *first_entry_instruction(entry_block.getFirstNonPHIOrDbg());367368if (!first_entry_instruction)369return false;370371if (!result_global->hasInitializer()) {372LLDB_LOG(log, "Couldn't find initializer for unused variable");373374m_error_stream.Format("Internal error [IRForTarget]: Result variable "375"({0}) has no writes and no initializer\n",376result_name);377378return false;379}380381Constant *initializer = result_global->getInitializer();382383StoreInst *synthesized_store =384new StoreInst(initializer, new_result_global, first_entry_instruction);385386LLDB_LOG(log, "Synthesized result store \"{0}\"\n",387PrintValue(synthesized_store));388} else {389result_global->replaceAllUsesWith(new_result_global);390}391392if (!m_decl_map->AddPersistentVariable(393result_decl, m_result_name, m_result_type, true, m_result_is_pointer))394return false;395396result_global->eraseFromParent();397398return true;399}400401bool IRForTarget::RewriteObjCConstString(llvm::GlobalVariable *ns_str,402llvm::GlobalVariable *cstr) {403lldb_private::Log *log(GetLog(LLDBLog::Expressions));404405Type *ns_str_ty = ns_str->getType();406407Type *i8_ptr_ty = PointerType::getUnqual(m_module->getContext());408Type *i32_ty = Type::getInt32Ty(m_module->getContext());409Type *i8_ty = Type::getInt8Ty(m_module->getContext());410411if (!m_CFStringCreateWithBytes) {412lldb::addr_t CFStringCreateWithBytes_addr;413414static lldb_private::ConstString g_CFStringCreateWithBytes_str(415"CFStringCreateWithBytes");416417bool missing_weak = false;418CFStringCreateWithBytes_addr =419m_execution_unit.FindSymbol(g_CFStringCreateWithBytes_str,420missing_weak);421if (CFStringCreateWithBytes_addr == LLDB_INVALID_ADDRESS || missing_weak) {422LLDB_LOG(log, "Couldn't find CFStringCreateWithBytes in the target");423424m_error_stream.Printf("Error [IRForTarget]: Rewriting an Objective-C "425"constant string requires "426"CFStringCreateWithBytes\n");427428return false;429}430431LLDB_LOG(log, "Found CFStringCreateWithBytes at {0}",432CFStringCreateWithBytes_addr);433434// Build the function type:435//436// CFStringRef CFStringCreateWithBytes (437// CFAllocatorRef alloc,438// const UInt8 *bytes,439// CFIndex numBytes,440// CFStringEncoding encoding,441// Boolean isExternalRepresentation442// );443//444// We make the following substitutions:445//446// CFStringRef -> i8*447// CFAllocatorRef -> i8*448// UInt8 * -> i8*449// CFIndex -> long (i32 or i64, as appropriate; we ask the module for its450// pointer size for now) CFStringEncoding -> i32 Boolean -> i8451452Type *arg_type_array[5];453454arg_type_array[0] = i8_ptr_ty;455arg_type_array[1] = i8_ptr_ty;456arg_type_array[2] = m_intptr_ty;457arg_type_array[3] = i32_ty;458arg_type_array[4] = i8_ty;459460ArrayRef<Type *> CFSCWB_arg_types(arg_type_array, 5);461462llvm::FunctionType *CFSCWB_ty =463FunctionType::get(ns_str_ty, CFSCWB_arg_types, false);464465// Build the constant containing the pointer to the function466PointerType *CFSCWB_ptr_ty = PointerType::getUnqual(CFSCWB_ty);467Constant *CFSCWB_addr_int =468ConstantInt::get(m_intptr_ty, CFStringCreateWithBytes_addr, false);469m_CFStringCreateWithBytes = {470CFSCWB_ty, ConstantExpr::getIntToPtr(CFSCWB_addr_int, CFSCWB_ptr_ty)};471}472473ConstantDataSequential *string_array = nullptr;474475if (cstr)476string_array = dyn_cast<ConstantDataSequential>(cstr->getInitializer());477478Constant *alloc_arg = Constant::getNullValue(i8_ptr_ty);479Constant *bytes_arg = cstr ? cstr : Constant::getNullValue(i8_ptr_ty);480Constant *numBytes_arg = ConstantInt::get(481m_intptr_ty, cstr ? (string_array->getNumElements() - 1) * string_array->getElementByteSize() : 0, false);482int encoding_flags = 0;483switch (cstr ? string_array->getElementByteSize() : 1) {484case 1:485encoding_flags = 0x08000100; /* 0x08000100 is kCFStringEncodingUTF8 */486break;487case 2:488encoding_flags = 0x0100; /* 0x0100 is kCFStringEncodingUTF16 */489break;490case 4:491encoding_flags = 0x0c000100; /* 0x0c000100 is kCFStringEncodingUTF32 */492break;493default:494encoding_flags = 0x0600; /* fall back to 0x0600, kCFStringEncodingASCII */495LLDB_LOG(log, "Encountered an Objective-C constant string with unusual "496"element size {0}",497string_array->getElementByteSize());498}499Constant *encoding_arg = ConstantInt::get(i32_ty, encoding_flags, false);500Constant *isExternal_arg =501ConstantInt::get(i8_ty, 0x0, false); /* 0x0 is false */502503Value *argument_array[5];504505argument_array[0] = alloc_arg;506argument_array[1] = bytes_arg;507argument_array[2] = numBytes_arg;508argument_array[3] = encoding_arg;509argument_array[4] = isExternal_arg;510511ArrayRef<Value *> CFSCWB_arguments(argument_array, 5);512513FunctionValueCache CFSCWB_Caller(514[this, &CFSCWB_arguments](llvm::Function *function) -> llvm::Value * {515return CallInst::Create(516m_CFStringCreateWithBytes, CFSCWB_arguments,517"CFStringCreateWithBytes",518llvm::cast<Instruction>(519m_entry_instruction_finder.GetValue(function)));520});521522if (!UnfoldConstant(ns_str, nullptr, CFSCWB_Caller, m_entry_instruction_finder,523m_error_stream)) {524LLDB_LOG(log, "Couldn't replace the NSString with the result of the call");525526m_error_stream.Printf("error [IRForTarget internal]: Couldn't replace an "527"Objective-C constant string with a dynamic "528"string\n");529530return false;531}532533ns_str->eraseFromParent();534535return true;536}537538bool IRForTarget::RewriteObjCConstStrings() {539lldb_private::Log *log(GetLog(LLDBLog::Expressions));540541ValueSymbolTable &value_symbol_table = m_module->getValueSymbolTable();542543for (StringMapEntry<llvm::Value *> &value_symbol : value_symbol_table) {544llvm::StringRef value_name = value_symbol.first();545546if (value_name.contains("_unnamed_cfstring_")) {547Value *nsstring_value = value_symbol.second;548549GlobalVariable *nsstring_global =550dyn_cast<GlobalVariable>(nsstring_value);551552if (!nsstring_global) {553LLDB_LOG(log, "NSString variable is not a GlobalVariable");554555m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C "556"constant string is not a global variable\n");557558return false;559}560561if (!nsstring_global->hasInitializer()) {562LLDB_LOG(log, "NSString variable does not have an initializer");563564m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C "565"constant string does not have an initializer\n");566567return false;568}569570ConstantStruct *nsstring_struct =571dyn_cast<ConstantStruct>(nsstring_global->getInitializer());572573if (!nsstring_struct) {574LLDB_LOG(log,575"NSString variable's initializer is not a ConstantStruct");576577m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C "578"constant string is not a structure constant\n");579580return false;581}582583// We expect the following structure:584//585// struct {586// int *isa;587// int flags;588// char *str;589// long length;590// };591592if (nsstring_struct->getNumOperands() != 4) {593594LLDB_LOG(log,595"NSString variable's initializer structure has an "596"unexpected number of members. Should be 4, is {0}",597nsstring_struct->getNumOperands());598599m_error_stream.Printf("Internal error [IRForTarget]: The struct for an "600"Objective-C constant string is not as "601"expected\n");602603return false;604}605606Constant *nsstring_member = nsstring_struct->getOperand(2);607608if (!nsstring_member) {609LLDB_LOG(log, "NSString initializer's str element was empty");610611m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C "612"constant string does not have a string "613"initializer\n");614615return false;616}617618auto *cstr_global = dyn_cast<GlobalVariable>(nsstring_member);619if (!cstr_global) {620LLDB_LOG(log,621"NSString initializer's str element is not a GlobalVariable");622623m_error_stream.Printf("Internal error [IRForTarget]: Unhandled"624"constant string initializer\n");625626return false;627}628629if (!cstr_global->hasInitializer()) {630LLDB_LOG(log, "NSString initializer's str element does not have an "631"initializer");632633m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C "634"constant string's string initializer doesn't "635"point to initialized data\n");636637return false;638}639640/*641if (!cstr_array)642{643if (log)644log->PutCString("NSString initializer's str element is not a645ConstantArray");646647if (m_error_stream)648m_error_stream.Printf("Internal error [IRForTarget]: An649Objective-C constant string's string initializer doesn't point to an650array\n");651652return false;653}654655if (!cstr_array->isCString())656{657if (log)658log->PutCString("NSString initializer's str element is not a C659string array");660661if (m_error_stream)662m_error_stream.Printf("Internal error [IRForTarget]: An663Objective-C constant string's string initializer doesn't point to a C664string\n");665666return false;667}668*/669670ConstantDataArray *cstr_array =671dyn_cast<ConstantDataArray>(cstr_global->getInitializer());672673if (cstr_array)674LLDB_LOG(log, "Found NSString constant {0}, which contains \"{1}\"",675value_name, cstr_array->getAsString());676else677LLDB_LOG(log, "Found NSString constant {0}, which contains \"\"",678value_name);679680if (!cstr_array)681cstr_global = nullptr;682683if (!RewriteObjCConstString(nsstring_global, cstr_global)) {684LLDB_LOG(log, "Error rewriting the constant string");685686// We don't print an error message here because RewriteObjCConstString687// has done so for us.688689return false;690}691}692}693694for (StringMapEntry<llvm::Value *> &value_symbol : value_symbol_table) {695llvm::StringRef value_name = value_symbol.first();696697if (value_name == "__CFConstantStringClassReference") {698GlobalVariable *gv = dyn_cast<GlobalVariable>(value_symbol.second);699700if (!gv) {701LLDB_LOG(log,702"__CFConstantStringClassReference is not a global variable");703704m_error_stream.Printf("Internal error [IRForTarget]: Found a "705"CFConstantStringClassReference, but it is not a "706"global object\n");707708return false;709}710711gv->eraseFromParent();712713break;714}715}716717return true;718}719720static bool IsObjCSelectorRef(Value *value) {721GlobalVariable *global_variable = dyn_cast<GlobalVariable>(value);722723return !(724!global_variable || !global_variable->hasName() ||725!global_variable->getName().starts_with("OBJC_SELECTOR_REFERENCES_"));726}727728// This function does not report errors; its callers are responsible.729bool IRForTarget::RewriteObjCSelector(Instruction *selector_load) {730lldb_private::Log *log(GetLog(LLDBLog::Expressions));731732LoadInst *load = dyn_cast<LoadInst>(selector_load);733734if (!load)735return false;736737// Unpack the message name from the selector. In LLVM IR, an objc_msgSend738// gets represented as739//740// %sel = load ptr, ptr @OBJC_SELECTOR_REFERENCES_, align 8741// call i8 @objc_msgSend(ptr %obj, ptr %sel, ...)742//743// where %obj is the object pointer and %sel is the selector.744//745// @"OBJC_SELECTOR_REFERENCES_" is a pointer to a character array called746// @"\01L_OBJC_METH_VAR_NAME_".747// @"\01L_OBJC_METH_VAR_NAME_" contains the string.748749// Find the pointer's initializer and get the string from its target.750751GlobalVariable *_objc_selector_references_ =752dyn_cast<GlobalVariable>(load->getPointerOperand());753754if (!_objc_selector_references_ ||755!_objc_selector_references_->hasInitializer())756return false;757758Constant *osr_initializer = _objc_selector_references_->getInitializer();759if (!osr_initializer)760return false;761762// Find the string's initializer (a ConstantArray) and get the string from it763764GlobalVariable *_objc_meth_var_name_ =765dyn_cast<GlobalVariable>(osr_initializer);766767if (!_objc_meth_var_name_ || !_objc_meth_var_name_->hasInitializer())768return false;769770Constant *omvn_initializer = _objc_meth_var_name_->getInitializer();771772ConstantDataArray *omvn_initializer_array =773dyn_cast<ConstantDataArray>(omvn_initializer);774775if (!omvn_initializer_array->isString())776return false;777778std::string omvn_initializer_string =779std::string(omvn_initializer_array->getAsString());780781LLDB_LOG(log, "Found Objective-C selector reference \"{0}\"",782omvn_initializer_string);783784// Construct a call to sel_registerName785786if (!m_sel_registerName) {787lldb::addr_t sel_registerName_addr;788789bool missing_weak = false;790static lldb_private::ConstString g_sel_registerName_str("sel_registerName");791sel_registerName_addr = m_execution_unit.FindSymbol(g_sel_registerName_str,792missing_weak);793if (sel_registerName_addr == LLDB_INVALID_ADDRESS || missing_weak)794return false;795796LLDB_LOG(log, "Found sel_registerName at {0}", sel_registerName_addr);797798// Build the function type: struct objc_selector799// *sel_registerName(uint8_t*)800801// The below code would be "more correct," but in actuality what's required802// is uint8_t*803// Type *sel_type = StructType::get(m_module->getContext());804// Type *sel_ptr_type = PointerType::getUnqual(sel_type);805Type *sel_ptr_type = PointerType::getUnqual(m_module->getContext());806807Type *type_array[1];808809type_array[0] = llvm::PointerType::getUnqual(m_module->getContext());810811ArrayRef<Type *> srN_arg_types(type_array, 1);812813llvm::FunctionType *srN_type =814FunctionType::get(sel_ptr_type, srN_arg_types, false);815816// Build the constant containing the pointer to the function817PointerType *srN_ptr_ty = PointerType::getUnqual(srN_type);818Constant *srN_addr_int =819ConstantInt::get(m_intptr_ty, sel_registerName_addr, false);820m_sel_registerName = {srN_type,821ConstantExpr::getIntToPtr(srN_addr_int, srN_ptr_ty)};822}823824CallInst *srN_call =825CallInst::Create(m_sel_registerName, _objc_meth_var_name_,826"sel_registerName", selector_load);827828// Replace the load with the call in all users829830selector_load->replaceAllUsesWith(srN_call);831832selector_load->eraseFromParent();833834return true;835}836837bool IRForTarget::RewriteObjCSelectors(BasicBlock &basic_block) {838lldb_private::Log *log(GetLog(LLDBLog::Expressions));839840InstrList selector_loads;841842for (Instruction &inst : basic_block) {843if (LoadInst *load = dyn_cast<LoadInst>(&inst))844if (IsObjCSelectorRef(load->getPointerOperand()))845selector_loads.push_back(&inst);846}847848for (Instruction *inst : selector_loads) {849if (!RewriteObjCSelector(inst)) {850m_error_stream.Printf("Internal error [IRForTarget]: Couldn't change a "851"static reference to an Objective-C selector to a "852"dynamic reference\n");853854LLDB_LOG(log, "Couldn't rewrite a reference to an Objective-C selector");855856return false;857}858}859860return true;861}862863// This function does not report errors; its callers are responsible.864bool IRForTarget::RewritePersistentAlloc(llvm::Instruction *persistent_alloc) {865lldb_private::Log *log(GetLog(LLDBLog::Expressions));866867AllocaInst *alloc = dyn_cast<AllocaInst>(persistent_alloc);868869MDNode *alloc_md = alloc->getMetadata("clang.decl.ptr");870871if (!alloc_md || !alloc_md->getNumOperands())872return false;873874ConstantInt *constant_int =875mdconst::dyn_extract<ConstantInt>(alloc_md->getOperand(0));876877if (!constant_int)878return false;879880// We attempt to register this as a new persistent variable with the DeclMap.881882uintptr_t ptr = constant_int->getZExtValue();883884clang::VarDecl *decl = reinterpret_cast<clang::VarDecl *>(ptr);885886lldb_private::TypeFromParser result_decl_type(887m_decl_map->GetTypeSystem()->GetType(decl->getType()));888889StringRef decl_name(decl->getName());890lldb_private::ConstString persistent_variable_name(decl_name.data(),891decl_name.size());892if (!m_decl_map->AddPersistentVariable(decl, persistent_variable_name,893result_decl_type, false, false))894return false;895896GlobalVariable *persistent_global = new GlobalVariable(897(*m_module), alloc->getType(), false, /* not constant */898GlobalValue::ExternalLinkage, nullptr, /* no initializer */899alloc->getName().str());900901// What we're going to do here is make believe this was a regular old902// external variable. That means we need to make the metadata valid.903904NamedMDNode *named_metadata =905m_module->getOrInsertNamedMetadata("clang.global.decl.ptrs");906907llvm::Metadata *values[2];908values[0] = ConstantAsMetadata::get(persistent_global);909values[1] = ConstantAsMetadata::get(constant_int);910911ArrayRef<llvm::Metadata *> value_ref(values, 2);912913MDNode *persistent_global_md = MDNode::get(m_module->getContext(), value_ref);914named_metadata->addOperand(persistent_global_md);915916// Now, since the variable is a pointer variable, we will drop in a load of917// that pointer variable.918919LoadInst *persistent_load = new LoadInst(persistent_global->getValueType(),920persistent_global, "", alloc);921922LLDB_LOG(log, "Replacing \"{0}\" with \"{1}\"", PrintValue(alloc),923PrintValue(persistent_load));924925alloc->replaceAllUsesWith(persistent_load);926alloc->eraseFromParent();927928return true;929}930931bool IRForTarget::RewritePersistentAllocs(llvm::BasicBlock &basic_block) {932if (!m_resolve_vars)933return true;934935lldb_private::Log *log(GetLog(LLDBLog::Expressions));936937InstrList pvar_allocs;938939for (Instruction &inst : basic_block) {940941if (AllocaInst *alloc = dyn_cast<AllocaInst>(&inst)) {942llvm::StringRef alloc_name = alloc->getName();943944if (alloc_name.starts_with("$") && !alloc_name.starts_with("$__lldb")) {945if (alloc_name.find_first_of("0123456789") == 1) {946LLDB_LOG(log, "Rejecting a numeric persistent variable.");947948m_error_stream.Printf("Error [IRForTarget]: Names starting with $0, "949"$1, ... are reserved for use as result "950"names\n");951952return false;953}954955pvar_allocs.push_back(alloc);956}957}958}959960for (Instruction *inst : pvar_allocs) {961if (!RewritePersistentAlloc(inst)) {962m_error_stream.Printf("Internal error [IRForTarget]: Couldn't rewrite "963"the creation of a persistent variable\n");964965LLDB_LOG(log, "Couldn't rewrite the creation of a persistent variable");966967return false;968}969}970971return true;972}973974// This function does not report errors; its callers are responsible.975bool IRForTarget::MaybeHandleVariable(Value *llvm_value_ptr) {976lldb_private::Log *log(GetLog(LLDBLog::Expressions));977978LLDB_LOG(log, "MaybeHandleVariable ({0})", PrintValue(llvm_value_ptr));979980if (ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(llvm_value_ptr)) {981switch (constant_expr->getOpcode()) {982default:983break;984case Instruction::GetElementPtr:985case Instruction::BitCast:986Value *s = constant_expr->getOperand(0);987if (!MaybeHandleVariable(s))988return false;989}990} else if (GlobalVariable *global_variable =991dyn_cast<GlobalVariable>(llvm_value_ptr)) {992if (!GlobalValue::isExternalLinkage(global_variable->getLinkage()))993return true;994995clang::NamedDecl *named_decl = DeclForGlobal(global_variable);996997if (!named_decl) {998if (IsObjCSelectorRef(llvm_value_ptr))999return true;10001001if (!global_variable->hasExternalLinkage())1002return true;10031004LLDB_LOG(log, "Found global variable \"{0}\" without metadata",1005global_variable->getName());10061007return false;1008}10091010llvm::StringRef name(named_decl->getName());10111012clang::ValueDecl *value_decl = dyn_cast<clang::ValueDecl>(named_decl);1013if (value_decl == nullptr)1014return false;10151016lldb_private::CompilerType compiler_type =1017m_decl_map->GetTypeSystem()->GetType(value_decl->getType());10181019const Type *value_type = nullptr;10201021if (name.starts_with("$")) {1022// The $__lldb_expr_result name indicates the return value has allocated1023// as a static variable. Per the comment at1024// ASTResultSynthesizer::SynthesizeBodyResult, accesses to this static1025// variable need to be redirected to the result of dereferencing a1026// pointer that is passed in as one of the arguments.1027//1028// Consequently, when reporting the size of the type, we report a pointer1029// type pointing to the type of $__lldb_expr_result, not the type itself.1030//1031// We also do this for any user-declared persistent variables.1032compiler_type = compiler_type.GetPointerType();1033value_type = PointerType::get(global_variable->getType(), 0);1034} else {1035value_type = global_variable->getType();1036}10371038auto *target = m_execution_unit.GetTarget().get();1039std::optional<uint64_t> value_size = compiler_type.GetByteSize(target);1040if (!value_size)1041return false;1042std::optional<size_t> opt_alignment = compiler_type.GetTypeBitAlign(target);1043if (!opt_alignment)1044return false;1045lldb::offset_t value_alignment = (*opt_alignment + 7ull) / 8ull;10461047LLDB_LOG(log,1048"Type of \"{0}\" is [clang \"{1}\", llvm \"{2}\"] [size {3}, "1049"align {4}]",1050name,1051lldb_private::ClangUtil::GetQualType(compiler_type).getAsString(),1052PrintType(value_type), *value_size, value_alignment);10531054if (named_decl)1055m_decl_map->AddValueToStruct(named_decl, lldb_private::ConstString(name),1056llvm_value_ptr, *value_size,1057value_alignment);1058} else if (isa<llvm::Function>(llvm_value_ptr)) {1059LLDB_LOG(log, "Function pointers aren't handled right now");10601061return false;1062}10631064return true;1065}10661067// This function does not report errors; its callers are responsible.1068bool IRForTarget::HandleSymbol(Value *symbol) {1069lldb_private::Log *log(GetLog(LLDBLog::Expressions));10701071lldb_private::ConstString name(symbol->getName().str().c_str());10721073lldb::addr_t symbol_addr =1074m_decl_map->GetSymbolAddress(name, lldb::eSymbolTypeAny);10751076if (symbol_addr == LLDB_INVALID_ADDRESS) {1077LLDB_LOG(log, "Symbol \"{0}\" had no address", name);10781079return false;1080}10811082LLDB_LOG(log, "Found \"{0}\" at {1}", name, symbol_addr);10831084Type *symbol_type = symbol->getType();10851086Constant *symbol_addr_int = ConstantInt::get(m_intptr_ty, symbol_addr, false);10871088Value *symbol_addr_ptr =1089ConstantExpr::getIntToPtr(symbol_addr_int, symbol_type);10901091LLDB_LOG(log, "Replacing {0} with {1}", PrintValue(symbol),1092PrintValue(symbol_addr_ptr));10931094symbol->replaceAllUsesWith(symbol_addr_ptr);10951096return true;1097}10981099bool IRForTarget::MaybeHandleCallArguments(CallInst *Old) {1100lldb_private::Log *log(GetLog(LLDBLog::Expressions));11011102LLDB_LOG(log, "MaybeHandleCallArguments({0})", PrintValue(Old));11031104for (unsigned op_index = 0, num_ops = Old->arg_size();1105op_index < num_ops; ++op_index)1106// conservatively believe that this is a store1107if (!MaybeHandleVariable(Old->getArgOperand(op_index))) {1108m_error_stream.Printf("Internal error [IRForTarget]: Couldn't rewrite "1109"one of the arguments of a function call.\n");11101111return false;1112}11131114return true;1115}11161117bool IRForTarget::HandleObjCClass(Value *classlist_reference) {1118lldb_private::Log *log(GetLog(LLDBLog::Expressions));11191120GlobalVariable *global_variable =1121dyn_cast<GlobalVariable>(classlist_reference);11221123if (!global_variable)1124return false;11251126Constant *initializer = global_variable->getInitializer();11271128if (!initializer)1129return false;11301131if (!initializer->hasName())1132return false;11331134StringRef name(initializer->getName());1135lldb_private::ConstString name_cstr(name.str().c_str());1136lldb::addr_t class_ptr =1137m_decl_map->GetSymbolAddress(name_cstr, lldb::eSymbolTypeObjCClass);11381139LLDB_LOG(log, "Found reference to Objective-C class {0} ({1})", name,1140(unsigned long long)class_ptr);11411142if (class_ptr == LLDB_INVALID_ADDRESS)1143return false;11441145if (global_variable->use_empty())1146return false;11471148SmallVector<LoadInst *, 2> load_instructions;11491150for (llvm::User *u : global_variable->users()) {1151if (LoadInst *load_instruction = dyn_cast<LoadInst>(u))1152load_instructions.push_back(load_instruction);1153}11541155if (load_instructions.empty())1156return false;11571158Constant *class_addr = ConstantInt::get(m_intptr_ty, (uint64_t)class_ptr);11591160for (LoadInst *load_instruction : load_instructions) {1161Constant *class_bitcast =1162ConstantExpr::getIntToPtr(class_addr, load_instruction->getType());11631164load_instruction->replaceAllUsesWith(class_bitcast);11651166load_instruction->eraseFromParent();1167}11681169return true;1170}11711172bool IRForTarget::RemoveCXAAtExit(BasicBlock &basic_block) {1173std::vector<CallInst *> calls_to_remove;11741175for (Instruction &inst : basic_block) {1176CallInst *call = dyn_cast<CallInst>(&inst);11771178// MaybeHandleCallArguments handles error reporting; we are silent here1179if (!call)1180continue;11811182bool remove = false;11831184llvm::Function *func = call->getCalledFunction();11851186if (func && func->getName() == "__cxa_atexit")1187remove = true;11881189llvm::Value *val = call->getCalledOperand();11901191if (val && val->getName() == "__cxa_atexit")1192remove = true;11931194if (remove)1195calls_to_remove.push_back(call);1196}11971198for (CallInst *ci : calls_to_remove)1199ci->eraseFromParent();12001201return true;1202}12031204bool IRForTarget::ResolveCalls(BasicBlock &basic_block) {1205// Prepare the current basic block for execution in the remote process12061207for (Instruction &inst : basic_block) {1208CallInst *call = dyn_cast<CallInst>(&inst);12091210// MaybeHandleCallArguments handles error reporting; we are silent here1211if (call && !MaybeHandleCallArguments(call))1212return false;1213}12141215return true;1216}12171218bool IRForTarget::ResolveExternals(Function &llvm_function) {1219lldb_private::Log *log(GetLog(LLDBLog::Expressions));12201221for (GlobalVariable &global_var : m_module->globals()) {1222llvm::StringRef global_name = global_var.getName();12231224LLDB_LOG(log, "Examining {0}, DeclForGlobalValue returns {1}", global_name,1225static_cast<void *>(DeclForGlobal(&global_var)));12261227if (global_name.starts_with("OBJC_IVAR")) {1228if (!HandleSymbol(&global_var)) {1229m_error_stream.Format("Error [IRForTarget]: Couldn't find Objective-C "1230"indirect ivar symbol {0}\n",1231global_name);12321233return false;1234}1235} else if (global_name.contains("OBJC_CLASSLIST_REFERENCES_$")) {1236if (!HandleObjCClass(&global_var)) {1237m_error_stream.Printf("Error [IRForTarget]: Couldn't resolve the class "1238"for an Objective-C static method call\n");12391240return false;1241}1242} else if (global_name.contains("OBJC_CLASSLIST_SUP_REFS_$")) {1243if (!HandleObjCClass(&global_var)) {1244m_error_stream.Printf("Error [IRForTarget]: Couldn't resolve the class "1245"for an Objective-C static method call\n");12461247return false;1248}1249} else if (DeclForGlobal(&global_var)) {1250if (!MaybeHandleVariable(&global_var)) {1251m_error_stream.Format("Internal error [IRForTarget]: Couldn't rewrite "1252"external variable {0}\n",1253global_name);12541255return false;1256}1257}1258}12591260return true;1261}12621263static bool isGuardVariableRef(Value *V) {1264GlobalVariable *GV = dyn_cast<GlobalVariable>(V);12651266if (!GV || !GV->hasName() || !isGuardVariableSymbol(GV->getName()))1267return false;12681269return true;1270}12711272void IRForTarget::TurnGuardLoadIntoZero(llvm::Instruction *guard_load) {1273Constant *zero(Constant::getNullValue(guard_load->getType()));1274guard_load->replaceAllUsesWith(zero);1275guard_load->eraseFromParent();1276}12771278static void ExciseGuardStore(Instruction *guard_store) {1279guard_store->eraseFromParent();1280}12811282bool IRForTarget::RemoveGuards(BasicBlock &basic_block) {1283// Eliminate any reference to guard variables found.12841285InstrList guard_loads;1286InstrList guard_stores;12871288for (Instruction &inst : basic_block) {12891290if (LoadInst *load = dyn_cast<LoadInst>(&inst))1291if (isGuardVariableRef(load->getPointerOperand()))1292guard_loads.push_back(&inst);12931294if (StoreInst *store = dyn_cast<StoreInst>(&inst))1295if (isGuardVariableRef(store->getPointerOperand()))1296guard_stores.push_back(&inst);1297}12981299for (Instruction *inst : guard_loads)1300TurnGuardLoadIntoZero(inst);13011302for (Instruction *inst : guard_stores)1303ExciseGuardStore(inst);13041305return true;1306}13071308// This function does not report errors; its callers are responsible.1309bool IRForTarget::UnfoldConstant(Constant *old_constant,1310llvm::Function *llvm_function,1311FunctionValueCache &value_maker,1312FunctionValueCache &entry_instruction_finder,1313lldb_private::Stream &error_stream) {1314SmallVector<User *, 16> users;13151316// We do this because the use list might change, invalidating our iterator.1317// Much better to keep a work list ourselves.1318for (llvm::User *u : old_constant->users())1319users.push_back(u);13201321for (size_t i = 0; i < users.size(); ++i) {1322User *user = users[i];13231324if (Constant *constant = dyn_cast<Constant>(user)) {1325// synthesize a new non-constant equivalent of the constant13261327if (ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(constant)) {1328switch (constant_expr->getOpcode()) {1329default:1330error_stream.Printf("error [IRForTarget internal]: Unhandled "1331"constant expression type: \"%s\"",1332PrintValue(constant_expr).c_str());1333return false;1334case Instruction::BitCast: {1335FunctionValueCache bit_cast_maker(1336[&value_maker, &entry_instruction_finder, old_constant,1337constant_expr](llvm::Function *function) -> llvm::Value * {1338// UnaryExpr1339// OperandList[0] is value13401341if (constant_expr->getOperand(0) != old_constant)1342return constant_expr;13431344return new BitCastInst(1345value_maker.GetValue(function), constant_expr->getType(),1346"", llvm::cast<Instruction>(1347entry_instruction_finder.GetValue(function)));1348});13491350if (!UnfoldConstant(constant_expr, llvm_function, bit_cast_maker,1351entry_instruction_finder, error_stream))1352return false;1353} break;1354case Instruction::GetElementPtr: {1355// GetElementPtrConstantExpr1356// OperandList[0] is base1357// OperandList[1]... are indices13581359FunctionValueCache get_element_pointer_maker(1360[&value_maker, &entry_instruction_finder, old_constant,1361constant_expr](llvm::Function *function) -> llvm::Value * {1362auto *gep = cast<llvm::GEPOperator>(constant_expr);1363Value *ptr = gep->getPointerOperand();13641365if (ptr == old_constant)1366ptr = value_maker.GetValue(function);13671368std::vector<Value *> index_vector;1369for (Value *operand : gep->indices()) {1370if (operand == old_constant)1371operand = value_maker.GetValue(function);13721373index_vector.push_back(operand);1374}13751376ArrayRef<Value *> indices(index_vector);13771378return GetElementPtrInst::Create(1379gep->getSourceElementType(), ptr, indices, "",1380llvm::cast<Instruction>(1381entry_instruction_finder.GetValue(function)));1382});13831384if (!UnfoldConstant(constant_expr, llvm_function,1385get_element_pointer_maker,1386entry_instruction_finder, error_stream))1387return false;1388} break;1389}1390} else {1391error_stream.Printf(1392"error [IRForTarget internal]: Unhandled constant type: \"%s\"",1393PrintValue(constant).c_str());1394return false;1395}1396} else {1397if (Instruction *inst = llvm::dyn_cast<Instruction>(user)) {1398if (llvm_function && inst->getParent()->getParent() != llvm_function) {1399error_stream.PutCString("error: Capturing non-local variables in "1400"expressions is unsupported.\n");1401return false;1402}1403inst->replaceUsesOfWith(1404old_constant, value_maker.GetValue(inst->getParent()->getParent()));1405} else {1406error_stream.Printf(1407"error [IRForTarget internal]: Unhandled non-constant type: \"%s\"",1408PrintValue(user).c_str());1409return false;1410}1411}1412}14131414if (!isa<GlobalValue>(old_constant)) {1415old_constant->destroyConstant();1416}14171418return true;1419}14201421bool IRForTarget::ReplaceVariables(Function &llvm_function) {1422if (!m_resolve_vars)1423return true;14241425lldb_private::Log *log(GetLog(LLDBLog::Expressions));14261427m_decl_map->DoStructLayout();14281429LLDB_LOG(log, "Element arrangement:");14301431uint32_t num_elements;1432uint32_t element_index;14331434size_t size;1435lldb::offset_t alignment;14361437if (!m_decl_map->GetStructInfo(num_elements, size, alignment))1438return false;14391440Function::arg_iterator iter(llvm_function.arg_begin());14411442if (iter == llvm_function.arg_end()) {1443m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes no "1444"arguments (should take at least a struct pointer)");14451446return false;1447}14481449Argument *argument = &*iter;14501451if (argument->getName() == "this") {1452++iter;14531454if (iter == llvm_function.arg_end()) {1455m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes only "1456"'this' argument (should take a struct pointer "1457"too)");14581459return false;1460}14611462argument = &*iter;1463} else if (argument->getName() == "self") {1464++iter;14651466if (iter == llvm_function.arg_end()) {1467m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes only "1468"'self' argument (should take '_cmd' and a struct "1469"pointer too)");14701471return false;1472}14731474if (iter->getName() != "_cmd") {1475m_error_stream.Format("Internal error [IRForTarget]: Wrapper takes '{0}' "1476"after 'self' argument (should take '_cmd')",1477iter->getName());14781479return false;1480}14811482++iter;14831484if (iter == llvm_function.arg_end()) {1485m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes only "1486"'self' and '_cmd' arguments (should take a struct "1487"pointer too)");14881489return false;1490}14911492argument = &*iter;1493}14941495if (argument->getName() != "$__lldb_arg") {1496m_error_stream.Format("Internal error [IRForTarget]: Wrapper takes an "1497"argument named '{0}' instead of the struct pointer",1498argument->getName());14991500return false;1501}15021503LLDB_LOG(log, "Arg: \"{0}\"", PrintValue(argument));15041505BasicBlock &entry_block(llvm_function.getEntryBlock());1506Instruction *FirstEntryInstruction(entry_block.getFirstNonPHIOrDbg());15071508if (!FirstEntryInstruction) {1509m_error_stream.Printf("Internal error [IRForTarget]: Couldn't find the "1510"first instruction in the wrapper for use in "1511"rewriting");15121513return false;1514}15151516LLVMContext &context(m_module->getContext());1517IntegerType *offset_type(Type::getInt32Ty(context));15181519if (!offset_type) {1520m_error_stream.Printf(1521"Internal error [IRForTarget]: Couldn't produce an offset type");15221523return false;1524}15251526for (element_index = 0; element_index < num_elements; ++element_index) {1527const clang::NamedDecl *decl = nullptr;1528Value *value = nullptr;1529lldb::offset_t offset;1530lldb_private::ConstString name;15311532if (!m_decl_map->GetStructElement(decl, value, offset, name,1533element_index)) {1534m_error_stream.Printf(1535"Internal error [IRForTarget]: Structure information is incomplete");15361537return false;1538}15391540LLDB_LOG(log, " \"{0}\" (\"{1}\") placed at {2}", name,1541decl->getNameAsString(), offset);15421543if (value) {1544LLDB_LOG(log, " Replacing [{0}]", PrintValue(value));15451546FunctionValueCache body_result_maker(1547[this, name, offset_type, offset, argument,1548value](llvm::Function *function) -> llvm::Value * {1549// Per the comment at ASTResultSynthesizer::SynthesizeBodyResult,1550// in cases where the result variable is an rvalue, we have to1551// synthesize a dereference of the appropriate structure entry in1552// order to produce the static variable that the AST thinks it is1553// accessing.15541555llvm::Instruction *entry_instruction = llvm::cast<Instruction>(1556m_entry_instruction_finder.GetValue(function));15571558Type *int8Ty = Type::getInt8Ty(function->getContext());1559ConstantInt *offset_int(1560ConstantInt::get(offset_type, offset, true));1561GetElementPtrInst *get_element_ptr = GetElementPtrInst::Create(1562int8Ty, argument, offset_int, "", entry_instruction);15631564if (name == m_result_name && !m_result_is_pointer) {1565LoadInst *load = new LoadInst(value->getType(), get_element_ptr,1566"", entry_instruction);15671568return load;1569} else {1570return get_element_ptr;1571}1572});15731574if (Constant *constant = dyn_cast<Constant>(value)) {1575if (!UnfoldConstant(constant, &llvm_function, body_result_maker,1576m_entry_instruction_finder, m_error_stream)) {1577return false;1578}1579} else if (Instruction *instruction = dyn_cast<Instruction>(value)) {1580if (instruction->getParent()->getParent() != &llvm_function) {1581m_error_stream.PutCString("error: Capturing non-local variables in "1582"expressions is unsupported.\n");1583return false;1584}1585value->replaceAllUsesWith(1586body_result_maker.GetValue(instruction->getParent()->getParent()));1587} else {1588LLDB_LOG(log, "Unhandled non-constant type: \"{0}\"",1589PrintValue(value));1590return false;1591}15921593if (GlobalVariable *var = dyn_cast<GlobalVariable>(value))1594var->eraseFromParent();1595}1596}15971598LLDB_LOG(log, "Total structure [align {0}, size {1}]", (int64_t)alignment,1599(uint64_t)size);16001601return true;1602}16031604bool IRForTarget::runOnModule(Module &llvm_module) {1605lldb_private::Log *log(GetLog(LLDBLog::Expressions));16061607m_module = &llvm_module;1608m_target_data = std::make_unique<DataLayout>(m_module);1609m_intptr_ty = llvm::Type::getIntNTy(m_module->getContext(),1610m_target_data->getPointerSizeInBits());16111612if (log) {1613std::string s;1614raw_string_ostream oss(s);16151616m_module->print(oss, nullptr);16171618oss.flush();16191620LLDB_LOG(log, "Module as passed in to IRForTarget: \n\"{0}\"", s);1621}16221623Function *const main_function =1624m_func_name.IsEmpty() ? nullptr1625: m_module->getFunction(m_func_name.GetStringRef());16261627if (!m_func_name.IsEmpty() && !main_function) {1628LLDB_LOG(log, "Couldn't find \"{0}()\" in the module", m_func_name);16291630m_error_stream.Format("Internal error [IRForTarget]: Couldn't find wrapper "1631"'{0}' in the module",1632m_func_name);16331634return false;1635}16361637if (main_function) {1638if (!FixFunctionLinkage(*main_function)) {1639LLDB_LOG(log, "Couldn't fix the linkage for the function");16401641return false;1642}1643}16441645////////////////////////////////////////////////////////////1646// Replace $__lldb_expr_result with a persistent variable1647//16481649if (main_function) {1650if (!CreateResultVariable(*main_function)) {1651LLDB_LOG(log, "CreateResultVariable() failed");16521653// CreateResultVariable() reports its own errors, so we don't do so here16541655return false;1656}1657}16581659if (log && log->GetVerbose()) {1660std::string s;1661raw_string_ostream oss(s);16621663m_module->print(oss, nullptr);16641665oss.flush();16661667LLDB_LOG(log, "Module after creating the result variable: \n\"{0}\"", s);1668}16691670for (llvm::Function &function : *m_module) {1671for (BasicBlock &bb : function) {1672if (!RemoveGuards(bb)) {1673LLDB_LOG(log, "RemoveGuards() failed");16741675// RemoveGuards() reports its own errors, so we don't do so here16761677return false;1678}16791680if (!RewritePersistentAllocs(bb)) {1681LLDB_LOG(log, "RewritePersistentAllocs() failed");16821683// RewritePersistentAllocs() reports its own errors, so we don't do so1684// here16851686return false;1687}16881689if (!RemoveCXAAtExit(bb)) {1690LLDB_LOG(log, "RemoveCXAAtExit() failed");16911692// RemoveCXAAtExit() reports its own errors, so we don't do so here16931694return false;1695}1696}1697}16981699///////////////////////////////////////////////////////////////////////////////1700// Fix all Objective-C constant strings to use NSStringWithCString:encoding:1701//17021703if (!RewriteObjCConstStrings()) {1704LLDB_LOG(log, "RewriteObjCConstStrings() failed");17051706// RewriteObjCConstStrings() reports its own errors, so we don't do so here17071708return false;1709}17101711for (llvm::Function &function : *m_module) {1712for (llvm::BasicBlock &bb : function) {1713if (!RewriteObjCSelectors(bb)) {1714LLDB_LOG(log, "RewriteObjCSelectors() failed");17151716// RewriteObjCSelectors() reports its own errors, so we don't do so1717// here17181719return false;1720}1721}1722}17231724for (llvm::Function &function : *m_module) {1725for (BasicBlock &bb : function) {1726if (!ResolveCalls(bb)) {1727LLDB_LOG(log, "ResolveCalls() failed");17281729// ResolveCalls() reports its own errors, so we don't do so here17301731return false;1732}1733}1734}17351736////////////////////////////////////////////////////////////////////////1737// Run function-level passes that only make sense on the main function1738//17391740if (main_function) {1741if (!ResolveExternals(*main_function)) {1742LLDB_LOG(log, "ResolveExternals() failed");17431744// ResolveExternals() reports its own errors, so we don't do so here17451746return false;1747}17481749if (!ReplaceVariables(*main_function)) {1750LLDB_LOG(log, "ReplaceVariables() failed");17511752// ReplaceVariables() reports its own errors, so we don't do so here17531754return false;1755}1756}17571758if (log && log->GetVerbose()) {1759std::string s;1760raw_string_ostream oss(s);17611762m_module->print(oss, nullptr);17631764oss.flush();17651766LLDB_LOG(log, "Module after preparing for execution: \n\"{0}\"", s);1767}17681769return true;1770}177117721773