xref: /freebsd-src/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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