180814287SRaphael Isemann //===-- IRForTarget.cpp ---------------------------------------------------===//
24dbb271fSSean Callanan //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
64dbb271fSSean Callanan //
74dbb271fSSean Callanan //===----------------------------------------------------------------------===//
84dbb271fSSean Callanan 
94dbb271fSSean Callanan #include "IRForTarget.h"
104dbb271fSSean Callanan 
114dbb271fSSean Callanan #include "ClangExpressionDeclMap.h"
128be30215SAlex Langford #include "ClangUtil.h"
134dbb271fSSean Callanan 
148be30215SAlex Langford #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
154dbb271fSSean Callanan #include "llvm/IR/Constants.h"
164dbb271fSSean Callanan #include "llvm/IR/DataLayout.h"
17c476566bSNikita Popov #include "llvm/IR/Operator.h"
184dbb271fSSean Callanan #include "llvm/IR/InstrTypes.h"
194dbb271fSSean Callanan #include "llvm/IR/Instructions.h"
204dbb271fSSean Callanan #include "llvm/IR/Intrinsics.h"
214dbb271fSSean Callanan #include "llvm/IR/LegacyPassManager.h"
224dbb271fSSean Callanan #include "llvm/IR/Metadata.h"
23b9c1b51eSKate Stone #include "llvm/IR/Module.h"
244dbb271fSSean Callanan #include "llvm/IR/ValueSymbolTable.h"
25b9c1b51eSKate Stone #include "llvm/Support/raw_ostream.h"
26b9c1b51eSKate Stone #include "llvm/Transforms/IPO.h"
274dbb271fSSean Callanan 
284dbb271fSSean Callanan #include "clang/AST/ASTContext.h"
294dbb271fSSean Callanan 
30d133f6acSZachary Turner #include "lldb/Core/dwarf.h"
314dbb271fSSean Callanan #include "lldb/Expression/IRExecutionUnit.h"
324dbb271fSSean Callanan #include "lldb/Expression/IRInterpreter.h"
334dbb271fSSean Callanan #include "lldb/Symbol/CompilerType.h"
34bf9a7730SZachary Turner #include "lldb/Utility/ConstString.h"
35666cc0b2SZachary Turner #include "lldb/Utility/DataBufferHeap.h"
3601c3243fSZachary Turner #include "lldb/Utility/Endian.h"
37c34698a8SPavel Labath #include "lldb/Utility/LLDBLog.h"
386f9e6901SZachary Turner #include "lldb/Utility/Log.h"
39d821c997SPavel Labath #include "lldb/Utility/Scalar.h"
40bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h"
414dbb271fSSean Callanan 
424dbb271fSSean Callanan #include <map>
434dbb271fSSean Callanan 
444dbb271fSSean Callanan using namespace llvm;
45a007a6d8SPavel Labath using lldb_private::LLDBLog;
464dbb271fSSean Callanan 
47ac42e741SRaphael Isemann typedef SmallVector<Instruction *, 2> InstrList;
48ac42e741SRaphael Isemann 
FunctionValueCache(Maker const & maker)49b9c1b51eSKate Stone IRForTarget::FunctionValueCache::FunctionValueCache(Maker const &maker)
50b9c1b51eSKate Stone     : m_maker(maker), m_values() {}
514dbb271fSSean Callanan 
52fd2433e1SJonas Devlieghere IRForTarget::FunctionValueCache::~FunctionValueCache() = default;
534dbb271fSSean Callanan 
544dbb271fSSean Callanan llvm::Value *
GetValue(llvm::Function * function)55b9c1b51eSKate Stone IRForTarget::FunctionValueCache::GetValue(llvm::Function *function) {
56b9c1b51eSKate Stone   if (!m_values.count(function)) {
574dbb271fSSean Callanan     llvm::Value *ret = m_maker(function);
584dbb271fSSean Callanan     m_values[function] = ret;
594dbb271fSSean Callanan     return ret;
604dbb271fSSean Callanan   }
614dbb271fSSean Callanan   return m_values[function];
624dbb271fSSean Callanan }
634dbb271fSSean Callanan 
FindEntryInstruction(llvm::Function * function)64b9c1b51eSKate Stone static llvm::Value *FindEntryInstruction(llvm::Function *function) {
654dbb271fSSean Callanan   if (function->empty())
66248a1305SKonrad Kleine     return nullptr;
674dbb271fSSean Callanan 
684dbb271fSSean Callanan   return function->getEntryBlock().getFirstNonPHIOrDbg();
694dbb271fSSean Callanan }
704dbb271fSSean Callanan 
IRForTarget(lldb_private::ClangExpressionDeclMap * decl_map,bool resolve_vars,lldb_private::IRExecutionUnit & execution_unit,lldb_private::Stream & error_stream,const char * func_name)714dbb271fSSean Callanan IRForTarget::IRForTarget(lldb_private::ClangExpressionDeclMap *decl_map,
724dbb271fSSean Callanan                          bool resolve_vars,
734dbb271fSSean Callanan                          lldb_private::IRExecutionUnit &execution_unit,
748a33f612SSean Callanan                          lldb_private::Stream &error_stream,
75b9c1b51eSKate Stone                          const char *func_name)
761dee479fSRaphael Isemann     : m_resolve_vars(resolve_vars), m_func_name(func_name),
77d017d12fSRaphael Isemann       m_decl_map(decl_map), m_error_stream(error_stream),
78d017d12fSRaphael Isemann       m_execution_unit(execution_unit),
79b9c1b51eSKate Stone       m_entry_instruction_finder(FindEntryInstruction) {}
804dbb271fSSean Callanan 
814dbb271fSSean Callanan /* Handy utility functions used at several places in the code */
824dbb271fSSean Callanan 
PrintValue(const Value * value,bool truncate=false)83b9c1b51eSKate Stone static std::string PrintValue(const Value *value, bool truncate = false) {
844dbb271fSSean Callanan   std::string s;
85b9c1b51eSKate Stone   if (value) {
864dbb271fSSean Callanan     raw_string_ostream rso(s);
874dbb271fSSean Callanan     value->print(rso);
884dbb271fSSean Callanan     rso.flush();
894dbb271fSSean Callanan     if (truncate)
904dbb271fSSean Callanan       s.resize(s.length() - 1);
914dbb271fSSean Callanan   }
924dbb271fSSean Callanan   return s;
934dbb271fSSean Callanan }
944dbb271fSSean Callanan 
PrintType(const llvm::Type * type,bool truncate=false)95b9c1b51eSKate Stone static std::string PrintType(const llvm::Type *type, bool truncate = false) {
964dbb271fSSean Callanan   std::string s;
974dbb271fSSean Callanan   raw_string_ostream rso(s);
984dbb271fSSean Callanan   type->print(rso);
994dbb271fSSean Callanan   rso.flush();
1004dbb271fSSean Callanan   if (truncate)
1014dbb271fSSean Callanan     s.resize(s.length() - 1);
1024dbb271fSSean Callanan   return s;
1034dbb271fSSean Callanan }
1044dbb271fSSean Callanan 
FixFunctionLinkage(llvm::Function & llvm_function)105b9c1b51eSKate Stone bool IRForTarget::FixFunctionLinkage(llvm::Function &llvm_function) {
1064dbb271fSSean Callanan   llvm_function.setLinkage(GlobalValue::ExternalLinkage);
1074dbb271fSSean Callanan 
1084dbb271fSSean Callanan   return true;
1094dbb271fSSean Callanan }
1104dbb271fSSean Callanan 
DeclForGlobal(const GlobalValue * global_val,Module * module)111b9c1b51eSKate Stone clang::NamedDecl *IRForTarget::DeclForGlobal(const GlobalValue *global_val,
112b9c1b51eSKate Stone                                              Module *module) {
113b9c1b51eSKate Stone   NamedMDNode *named_metadata =
114b9c1b51eSKate Stone       module->getNamedMetadata("clang.global.decl.ptrs");
1154dbb271fSSean Callanan 
1164dbb271fSSean Callanan   if (!named_metadata)
117248a1305SKonrad Kleine     return nullptr;
1184dbb271fSSean Callanan 
1194dbb271fSSean Callanan   unsigned num_nodes = named_metadata->getNumOperands();
1204dbb271fSSean Callanan   unsigned node_index;
1214dbb271fSSean Callanan 
122b9c1b51eSKate Stone   for (node_index = 0; node_index < num_nodes; ++node_index) {
123b9c1b51eSKate Stone     llvm::MDNode *metadata_node =
124b9c1b51eSKate Stone         dyn_cast<llvm::MDNode>(named_metadata->getOperand(node_index));
1254dbb271fSSean Callanan     if (!metadata_node)
126248a1305SKonrad Kleine       return nullptr;
1274dbb271fSSean Callanan 
1284dbb271fSSean Callanan     if (metadata_node->getNumOperands() != 2)
1294dbb271fSSean Callanan       continue;
1304dbb271fSSean Callanan 
131b9c1b51eSKate Stone     if (mdconst::dyn_extract_or_null<GlobalValue>(
132b9c1b51eSKate Stone             metadata_node->getOperand(0)) != global_val)
1334dbb271fSSean Callanan       continue;
1344dbb271fSSean Callanan 
135b9c1b51eSKate Stone     ConstantInt *constant_int =
136b9c1b51eSKate Stone         mdconst::dyn_extract<ConstantInt>(metadata_node->getOperand(1));
1374dbb271fSSean Callanan 
1384dbb271fSSean Callanan     if (!constant_int)
139248a1305SKonrad Kleine       return nullptr;
1404dbb271fSSean Callanan 
1414dbb271fSSean Callanan     uintptr_t ptr = constant_int->getZExtValue();
1424dbb271fSSean Callanan 
1434dbb271fSSean Callanan     return reinterpret_cast<clang::NamedDecl *>(ptr);
1444dbb271fSSean Callanan   }
1454dbb271fSSean Callanan 
146248a1305SKonrad Kleine   return nullptr;
1474dbb271fSSean Callanan }
1484dbb271fSSean Callanan 
DeclForGlobal(GlobalValue * global_val)149b9c1b51eSKate Stone clang::NamedDecl *IRForTarget::DeclForGlobal(GlobalValue *global_val) {
1504dbb271fSSean Callanan   return DeclForGlobal(global_val, m_module);
1514dbb271fSSean Callanan }
1524dbb271fSSean Callanan 
1537f7b2966SRaphael Isemann /// Returns true iff the mangled symbol is for a static guard variable.
isGuardVariableSymbol(llvm::StringRef mangled_symbol,bool check_ms_abi=true)15466214b58SRaphael Isemann static bool isGuardVariableSymbol(llvm::StringRef mangled_symbol,
15566214b58SRaphael Isemann                                   bool check_ms_abi = true) {
15666214b58SRaphael Isemann   bool result = mangled_symbol.startswith("_ZGV"); // Itanium ABI guard variable
15766214b58SRaphael Isemann   if (check_ms_abi)
15866214b58SRaphael Isemann     result |= mangled_symbol.endswith("@4IA"); // Microsoft ABI
15966214b58SRaphael Isemann   return result;
1607f7b2966SRaphael Isemann }
1617f7b2966SRaphael Isemann 
CreateResultVariable(llvm::Function & llvm_function)162b9c1b51eSKate Stone bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) {
163a007a6d8SPavel Labath   lldb_private::Log *log(GetLog(LLDBLog::Expressions));
1644dbb271fSSean Callanan 
1654dbb271fSSean Callanan   if (!m_resolve_vars)
1664dbb271fSSean Callanan     return true;
1674dbb271fSSean Callanan 
1684dbb271fSSean Callanan   // Find the result variable.  If it doesn't exist, we can give up right here.
1694dbb271fSSean Callanan 
1704dbb271fSSean Callanan   ValueSymbolTable &value_symbol_table = m_module->getValueSymbolTable();
1714dbb271fSSean Callanan 
17250f7e945SRaphael Isemann   llvm::StringRef result_name;
17350f7e945SRaphael Isemann   bool found_result = false;
1744dbb271fSSean Callanan 
175dced445bSRaphael Isemann   for (StringMapEntry<llvm::Value *> &value_symbol : value_symbol_table) {
176dced445bSRaphael Isemann     result_name = value_symbol.first();
1774dbb271fSSean Callanan 
17866214b58SRaphael Isemann     // Check if this is a guard variable. It seems this causes some hiccups
17966214b58SRaphael Isemann     // on Windows, so let's only check for Itanium guard variables.
18066214b58SRaphael Isemann     bool is_guard_var = isGuardVariableSymbol(result_name, /*MS ABI*/ false);
1817f7b2966SRaphael Isemann 
1827f7b2966SRaphael Isemann     if (result_name.contains("$__lldb_expr_result_ptr") && !is_guard_var) {
18350f7e945SRaphael Isemann       found_result = true;
1844dbb271fSSean Callanan       m_result_is_pointer = true;
1854dbb271fSSean Callanan       break;
1864dbb271fSSean Callanan     }
1874dbb271fSSean Callanan 
1887f7b2966SRaphael Isemann     if (result_name.contains("$__lldb_expr_result") && !is_guard_var) {
18950f7e945SRaphael Isemann       found_result = true;
1904dbb271fSSean Callanan       m_result_is_pointer = false;
1914dbb271fSSean Callanan       break;
1924dbb271fSSean Callanan     }
1934dbb271fSSean Callanan   }
1944dbb271fSSean Callanan 
19550f7e945SRaphael Isemann   if (!found_result) {
1964ef50a33SRaphael Isemann     LLDB_LOG(log, "Couldn't find result variable");
1974dbb271fSSean Callanan 
1984dbb271fSSean Callanan     return true;
1994dbb271fSSean Callanan   }
2004dbb271fSSean Callanan 
20150f7e945SRaphael Isemann   LLDB_LOG(log, "Result name: \"{0}\"", result_name);
2024dbb271fSSean Callanan 
2034dbb271fSSean Callanan   Value *result_value = m_module->getNamedValue(result_name);
2044dbb271fSSean Callanan 
205b9c1b51eSKate Stone   if (!result_value) {
2064ef50a33SRaphael Isemann     LLDB_LOG(log, "Result variable had no data");
2074dbb271fSSean Callanan 
20850f7e945SRaphael Isemann     m_error_stream.Format("Internal error [IRForTarget]: Result variable's "
20950f7e945SRaphael Isemann                           "name ({0}) exists, but not its definition\n",
210b9c1b51eSKate Stone                           result_name);
2114dbb271fSSean Callanan 
2124dbb271fSSean Callanan     return false;
2134dbb271fSSean Callanan   }
2144dbb271fSSean Callanan 
2154ef50a33SRaphael Isemann   LLDB_LOG(log, "Found result in the IR: \"{0}\"",
2164ef50a33SRaphael Isemann            PrintValue(result_value, false));
2174dbb271fSSean Callanan 
2184dbb271fSSean Callanan   GlobalVariable *result_global = dyn_cast<GlobalVariable>(result_value);
2194dbb271fSSean Callanan 
220b9c1b51eSKate Stone   if (!result_global) {
2214ef50a33SRaphael Isemann     LLDB_LOG(log, "Result variable isn't a GlobalVariable");
2224dbb271fSSean Callanan 
22350f7e945SRaphael Isemann     m_error_stream.Format("Internal error [IRForTarget]: Result variable ({0}) "
224b9c1b51eSKate Stone                           "is defined, but is not a global variable\n",
225b9c1b51eSKate Stone                           result_name);
2264dbb271fSSean Callanan 
2274dbb271fSSean Callanan     return false;
2284dbb271fSSean Callanan   }
2294dbb271fSSean Callanan 
2304dbb271fSSean Callanan   clang::NamedDecl *result_decl = DeclForGlobal(result_global);
231b9c1b51eSKate Stone   if (!result_decl) {
2324ef50a33SRaphael Isemann     LLDB_LOG(log, "Result variable doesn't have a corresponding Decl");
2334dbb271fSSean Callanan 
23450f7e945SRaphael Isemann     m_error_stream.Format("Internal error [IRForTarget]: Result variable ({0}) "
235b9c1b51eSKate Stone                           "does not have a corresponding Clang entity\n",
236b9c1b51eSKate Stone                           result_name);
2374dbb271fSSean Callanan 
2384dbb271fSSean Callanan     return false;
2394dbb271fSSean Callanan   }
2404dbb271fSSean Callanan 
241b9c1b51eSKate Stone   if (log) {
2424dbb271fSSean Callanan     std::string decl_desc_str;
2434dbb271fSSean Callanan     raw_string_ostream decl_desc_stream(decl_desc_str);
2444dbb271fSSean Callanan     result_decl->print(decl_desc_stream);
2454dbb271fSSean Callanan     decl_desc_stream.flush();
2464dbb271fSSean Callanan 
2474ef50a33SRaphael Isemann     LLDB_LOG(log, "Found result decl: \"{0}\"", decl_desc_str);
2484dbb271fSSean Callanan   }
2494dbb271fSSean Callanan 
2504dbb271fSSean Callanan   clang::VarDecl *result_var = dyn_cast<clang::VarDecl>(result_decl);
251b9c1b51eSKate Stone   if (!result_var) {
2524ef50a33SRaphael Isemann     LLDB_LOG(log, "Result variable Decl isn't a VarDecl");
2534dbb271fSSean Callanan 
25450f7e945SRaphael Isemann     m_error_stream.Format("Internal error [IRForTarget]: Result variable "
25550f7e945SRaphael Isemann                           "({0})'s corresponding Clang entity isn't a "
256b9c1b51eSKate Stone                           "variable\n",
257b9c1b51eSKate Stone                           result_name);
2584dbb271fSSean Callanan 
2594dbb271fSSean Callanan     return false;
2604dbb271fSSean Callanan   }
2614dbb271fSSean Callanan 
262b9c1b51eSKate Stone   // Get the next available result name from m_decl_map and create the
26305097246SAdrian Prantl   // persistent variable for it
2644dbb271fSSean Callanan 
2654dbb271fSSean Callanan   // If the result is an Lvalue, it is emitted as a pointer; see
2664dbb271fSSean Callanan   // ASTResultSynthesizer::SynthesizeBodyResult.
267b9c1b51eSKate Stone   if (m_result_is_pointer) {
2684dbb271fSSean Callanan     clang::QualType pointer_qual_type = result_var->getType();
2694dbb271fSSean Callanan     const clang::Type *pointer_type = pointer_qual_type.getTypePtr();
2704dbb271fSSean Callanan 
271b9c1b51eSKate Stone     const clang::PointerType *pointer_pointertype =
272b9c1b51eSKate Stone         pointer_type->getAs<clang::PointerType>();
273b9c1b51eSKate Stone     const clang::ObjCObjectPointerType *pointer_objcobjpointertype =
274b9c1b51eSKate Stone         pointer_type->getAs<clang::ObjCObjectPointerType>();
2754dbb271fSSean Callanan 
276b9c1b51eSKate Stone     if (pointer_pointertype) {
2774dbb271fSSean Callanan       clang::QualType element_qual_type = pointer_pointertype->getPointeeType();
2784dbb271fSSean Callanan 
279b9c1b51eSKate Stone       m_result_type = lldb_private::TypeFromParser(
280df8a986fSRaphael Isemann           m_decl_map->GetTypeSystem()->GetType(element_qual_type));
281b9c1b51eSKate Stone     } else if (pointer_objcobjpointertype) {
282b9c1b51eSKate Stone       clang::QualType element_qual_type =
283b9c1b51eSKate Stone           clang::QualType(pointer_objcobjpointertype->getObjectType(), 0);
2844dbb271fSSean Callanan 
285b9c1b51eSKate Stone       m_result_type = lldb_private::TypeFromParser(
286df8a986fSRaphael Isemann           m_decl_map->GetTypeSystem()->GetType(element_qual_type));
287b9c1b51eSKate Stone     } else {
2884ef50a33SRaphael Isemann       LLDB_LOG(log, "Expected result to have pointer type, but it did not");
2894dbb271fSSean Callanan 
29050f7e945SRaphael Isemann       m_error_stream.Format("Internal error [IRForTarget]: Lvalue result ({0}) "
291b9c1b51eSKate Stone                             "is not a pointer variable\n",
292b9c1b51eSKate Stone                             result_name);
2934dbb271fSSean Callanan 
2944dbb271fSSean Callanan       return false;
2954dbb271fSSean Callanan     }
296b9c1b51eSKate Stone   } else {
297b9c1b51eSKate Stone     m_result_type = lldb_private::TypeFromParser(
298df8a986fSRaphael Isemann         m_decl_map->GetTypeSystem()->GetType(result_var->getType()));
2994dbb271fSSean Callanan   }
3004dbb271fSSean Callanan 
3012a8fa2a8SSean Callanan   lldb::TargetSP target_sp(m_execution_unit.GetTarget());
30202f58373SAdrian Prantl   llvm::Optional<uint64_t> bit_size = m_result_type.GetBitSize(target_sp.get());
303d963a7c3SAdrian Prantl   if (!bit_size) {
3044dbb271fSSean Callanan     lldb_private::StreamString type_desc_stream;
3054dbb271fSSean Callanan     m_result_type.DumpTypeDescription(&type_desc_stream);
3064dbb271fSSean Callanan 
3074ef50a33SRaphael Isemann     LLDB_LOG(log, "Result type has unknown size");
3084dbb271fSSean Callanan 
309b9c1b51eSKate Stone     m_error_stream.Printf("Error [IRForTarget]: Size of result type '%s' "
310b9c1b51eSKate Stone                           "couldn't be determined\n",
3114dbb271fSSean Callanan                           type_desc_stream.GetData());
3124dbb271fSSean Callanan     return false;
3134dbb271fSSean Callanan   }
3144dbb271fSSean Callanan 
315b9c1b51eSKate Stone   if (log) {
3164dbb271fSSean Callanan     lldb_private::StreamString type_desc_stream;
3174dbb271fSSean Callanan     m_result_type.DumpTypeDescription(&type_desc_stream);
3184dbb271fSSean Callanan 
3194ef50a33SRaphael Isemann     LLDB_LOG(log, "Result decl type: \"{0}\"", type_desc_stream.GetData());
3204dbb271fSSean Callanan   }
3214dbb271fSSean Callanan 
3224dbb271fSSean Callanan   m_result_name = lldb_private::ConstString("$RESULT_NAME");
3234dbb271fSSean Callanan 
3244ef50a33SRaphael Isemann   LLDB_LOG(log, "Creating a new result global: \"{0}\" with size {1}",
32502f58373SAdrian Prantl            m_result_name,
326*aa88161bSKazu Hirata            m_result_type.GetByteSize(target_sp.get()).value_or(0));
3274dbb271fSSean Callanan 
3284dbb271fSSean Callanan   // Construct a new result global and set up its metadata
3294dbb271fSSean Callanan 
330b9c1b51eSKate Stone   GlobalVariable *new_result_global = new GlobalVariable(
331ad1feef7SNikita Popov       (*m_module), result_global->getValueType(), false, /* not constant */
332248a1305SKonrad Kleine       GlobalValue::ExternalLinkage, nullptr,             /* no initializer */
3334dbb271fSSean Callanan       m_result_name.GetCString());
3344dbb271fSSean Callanan 
33505097246SAdrian Prantl   // It's too late in compilation to create a new VarDecl for this, but we
33605097246SAdrian Prantl   // don't need to.  We point the metadata at the old VarDecl.  This creates an
33705097246SAdrian Prantl   // odd anomaly: a variable with a Value whose name is something like $0 and a
3384dbb271fSSean Callanan   // Decl whose name is $__lldb_expr_result.  This condition is handled in
3394dbb271fSSean Callanan   // ClangExpressionDeclMap::DoMaterialize, and the name of the variable is
3404dbb271fSSean Callanan   // fixed up.
3414dbb271fSSean Callanan 
342b9c1b51eSKate Stone   ConstantInt *new_constant_int =
343b9c1b51eSKate Stone       ConstantInt::get(llvm::Type::getInt64Ty(m_module->getContext()),
344df6879ecSJan Kratochvil                        reinterpret_cast<uintptr_t>(result_decl), false);
3454dbb271fSSean Callanan 
3464dbb271fSSean Callanan   llvm::Metadata *values[2];
3474dbb271fSSean Callanan   values[0] = ConstantAsMetadata::get(new_result_global);
3484dbb271fSSean Callanan   values[1] = ConstantAsMetadata::get(new_constant_int);
3494dbb271fSSean Callanan 
3504dbb271fSSean Callanan   ArrayRef<Metadata *> value_ref(values, 2);
3514dbb271fSSean Callanan 
3524dbb271fSSean Callanan   MDNode *persistent_global_md = MDNode::get(m_module->getContext(), value_ref);
353b9c1b51eSKate Stone   NamedMDNode *named_metadata =
354b9c1b51eSKate Stone       m_module->getNamedMetadata("clang.global.decl.ptrs");
3554dbb271fSSean Callanan   named_metadata->addOperand(persistent_global_md);
3564dbb271fSSean Callanan 
3574ef50a33SRaphael Isemann   LLDB_LOG(log, "Replacing \"{0}\" with \"{1}\"", PrintValue(result_global),
3584ef50a33SRaphael Isemann            PrintValue(new_result_global));
3594dbb271fSSean Callanan 
360b9c1b51eSKate Stone   if (result_global->use_empty()) {
3614dbb271fSSean Callanan     // We need to synthesize a store for this variable, because otherwise
3624dbb271fSSean Callanan     // there's nothing to put into its equivalent persistent variable.
3634dbb271fSSean Callanan 
3644dbb271fSSean Callanan     BasicBlock &entry_block(llvm_function.getEntryBlock());
3654dbb271fSSean Callanan     Instruction *first_entry_instruction(entry_block.getFirstNonPHIOrDbg());
3664dbb271fSSean Callanan 
3674dbb271fSSean Callanan     if (!first_entry_instruction)
3684dbb271fSSean Callanan       return false;
3694dbb271fSSean Callanan 
370b9c1b51eSKate Stone     if (!result_global->hasInitializer()) {
3714ef50a33SRaphael Isemann       LLDB_LOG(log, "Couldn't find initializer for unused variable");
3724dbb271fSSean Callanan 
37350f7e945SRaphael Isemann       m_error_stream.Format("Internal error [IRForTarget]: Result variable "
37450f7e945SRaphael Isemann                             "({0}) has no writes and no initializer\n",
375b9c1b51eSKate Stone                             result_name);
3764dbb271fSSean Callanan 
3774dbb271fSSean Callanan       return false;
3784dbb271fSSean Callanan     }
3794dbb271fSSean Callanan 
3804dbb271fSSean Callanan     Constant *initializer = result_global->getInitializer();
3814dbb271fSSean Callanan 
382b9c1b51eSKate Stone     StoreInst *synthesized_store =
383b9c1b51eSKate Stone         new StoreInst(initializer, new_result_global, first_entry_instruction);
3844dbb271fSSean Callanan 
3854ef50a33SRaphael Isemann     LLDB_LOG(log, "Synthesized result store \"{0}\"\n",
3864ef50a33SRaphael Isemann              PrintValue(synthesized_store));
387b9c1b51eSKate Stone   } else {
3884dbb271fSSean Callanan     result_global->replaceAllUsesWith(new_result_global);
3894dbb271fSSean Callanan   }
3904dbb271fSSean Callanan 
391b9c1b51eSKate Stone   if (!m_decl_map->AddPersistentVariable(
392b9c1b51eSKate Stone           result_decl, m_result_name, m_result_type, true, m_result_is_pointer))
3934dbb271fSSean Callanan     return false;
3944dbb271fSSean Callanan 
3954dbb271fSSean Callanan   result_global->eraseFromParent();
3964dbb271fSSean Callanan 
3974dbb271fSSean Callanan   return true;
3984dbb271fSSean Callanan }
3994dbb271fSSean Callanan 
RewriteObjCConstString(llvm::GlobalVariable * ns_str,llvm::GlobalVariable * cstr)400b9c1b51eSKate Stone bool IRForTarget::RewriteObjCConstString(llvm::GlobalVariable *ns_str,
401b9c1b51eSKate Stone                                          llvm::GlobalVariable *cstr) {
402a007a6d8SPavel Labath   lldb_private::Log *log(GetLog(LLDBLog::Expressions));
4034dbb271fSSean Callanan 
4044dbb271fSSean Callanan   Type *ns_str_ty = ns_str->getType();
4054dbb271fSSean Callanan 
4064dbb271fSSean Callanan   Type *i8_ptr_ty = Type::getInt8PtrTy(m_module->getContext());
4074dbb271fSSean Callanan   Type *i32_ty = Type::getInt32Ty(m_module->getContext());
4084dbb271fSSean Callanan   Type *i8_ty = Type::getInt8Ty(m_module->getContext());
4094dbb271fSSean Callanan 
410b9c1b51eSKate Stone   if (!m_CFStringCreateWithBytes) {
4114dbb271fSSean Callanan     lldb::addr_t CFStringCreateWithBytes_addr;
4124dbb271fSSean Callanan 
413b9c1b51eSKate Stone     static lldb_private::ConstString g_CFStringCreateWithBytes_str(
414b9c1b51eSKate Stone         "CFStringCreateWithBytes");
4154dbb271fSSean Callanan 
416f2128b28SJim Ingham     bool missing_weak = false;
417b9c1b51eSKate Stone     CFStringCreateWithBytes_addr =
418f2128b28SJim Ingham         m_execution_unit.FindSymbol(g_CFStringCreateWithBytes_str,
419f2128b28SJim Ingham                                     missing_weak);
420f2128b28SJim Ingham     if (CFStringCreateWithBytes_addr == LLDB_INVALID_ADDRESS || missing_weak) {
421e2d8aa6bSRaphael Isemann       LLDB_LOG(log, "Couldn't find CFStringCreateWithBytes in the target");
4224dbb271fSSean Callanan 
423b9c1b51eSKate Stone       m_error_stream.Printf("Error [IRForTarget]: Rewriting an Objective-C "
424b9c1b51eSKate Stone                             "constant string requires "
425b9c1b51eSKate Stone                             "CFStringCreateWithBytes\n");
4264dbb271fSSean Callanan 
4274dbb271fSSean Callanan       return false;
4284dbb271fSSean Callanan     }
4294dbb271fSSean Callanan 
4304ef50a33SRaphael Isemann     LLDB_LOG(log, "Found CFStringCreateWithBytes at {0}",
431b9c1b51eSKate Stone              CFStringCreateWithBytes_addr);
4324dbb271fSSean Callanan 
4334dbb271fSSean Callanan     // Build the function type:
4344dbb271fSSean Callanan     //
4354dbb271fSSean Callanan     // CFStringRef CFStringCreateWithBytes (
4364dbb271fSSean Callanan     //   CFAllocatorRef alloc,
4374dbb271fSSean Callanan     //   const UInt8 *bytes,
4384dbb271fSSean Callanan     //   CFIndex numBytes,
4394dbb271fSSean Callanan     //   CFStringEncoding encoding,
4404dbb271fSSean Callanan     //   Boolean isExternalRepresentation
4414dbb271fSSean Callanan     // );
4424dbb271fSSean Callanan     //
4434dbb271fSSean Callanan     // We make the following substitutions:
4444dbb271fSSean Callanan     //
4454dbb271fSSean Callanan     // CFStringRef -> i8*
4464dbb271fSSean Callanan     // CFAllocatorRef -> i8*
4474dbb271fSSean Callanan     // UInt8 * -> i8*
448b9c1b51eSKate Stone     // CFIndex -> long (i32 or i64, as appropriate; we ask the module for its
44905097246SAdrian Prantl     // pointer size for now) CFStringEncoding -> i32 Boolean -> i8
4504dbb271fSSean Callanan 
4514dbb271fSSean Callanan     Type *arg_type_array[5];
4524dbb271fSSean Callanan 
4534dbb271fSSean Callanan     arg_type_array[0] = i8_ptr_ty;
4544dbb271fSSean Callanan     arg_type_array[1] = i8_ptr_ty;
4554dbb271fSSean Callanan     arg_type_array[2] = m_intptr_ty;
4564dbb271fSSean Callanan     arg_type_array[3] = i32_ty;
4574dbb271fSSean Callanan     arg_type_array[4] = i8_ty;
4584dbb271fSSean Callanan 
4594dbb271fSSean Callanan     ArrayRef<Type *> CFSCWB_arg_types(arg_type_array, 5);
4604dbb271fSSean Callanan 
461ae2f9512SJames Y Knight     llvm::FunctionType *CFSCWB_ty =
462b9c1b51eSKate Stone         FunctionType::get(ns_str_ty, CFSCWB_arg_types, false);
4634dbb271fSSean Callanan 
4644dbb271fSSean Callanan     // Build the constant containing the pointer to the function
4654dbb271fSSean Callanan     PointerType *CFSCWB_ptr_ty = PointerType::getUnqual(CFSCWB_ty);
466b9c1b51eSKate Stone     Constant *CFSCWB_addr_int =
467b9c1b51eSKate Stone         ConstantInt::get(m_intptr_ty, CFStringCreateWithBytes_addr, false);
468ae2f9512SJames Y Knight     m_CFStringCreateWithBytes = {
469ae2f9512SJames Y Knight         CFSCWB_ty, ConstantExpr::getIntToPtr(CFSCWB_addr_int, CFSCWB_ptr_ty)};
4704dbb271fSSean Callanan   }
4714dbb271fSSean Callanan 
472248a1305SKonrad Kleine   ConstantDataSequential *string_array = nullptr;
4734dbb271fSSean Callanan 
4744dbb271fSSean Callanan   if (cstr)
4754dbb271fSSean Callanan     string_array = dyn_cast<ConstantDataSequential>(cstr->getInitializer());
4764dbb271fSSean Callanan 
4774dbb271fSSean Callanan   Constant *alloc_arg = Constant::getNullValue(i8_ptr_ty);
478b9c1b51eSKate Stone   Constant *bytes_arg = cstr ? ConstantExpr::getBitCast(cstr, i8_ptr_ty)
479b9c1b51eSKate Stone                              : Constant::getNullValue(i8_ptr_ty);
480b9c1b51eSKate Stone   Constant *numBytes_arg = ConstantInt::get(
481cd1eb72bSSean Callanan       m_intptr_ty, cstr ? (string_array->getNumElements() - 1) * string_array->getElementByteSize() : 0, false);
482cd1eb72bSSean Callanan  int encoding_flags = 0;
4830134152cSSean Callanan  switch (cstr ? string_array->getElementByteSize() : 1) {
484cd1eb72bSSean Callanan  case 1:
485cd1eb72bSSean Callanan    encoding_flags = 0x08000100; /* 0x08000100 is kCFStringEncodingUTF8 */
486cd1eb72bSSean Callanan    break;
487cd1eb72bSSean Callanan  case 2:
488cd1eb72bSSean Callanan    encoding_flags = 0x0100; /* 0x0100 is kCFStringEncodingUTF16 */
489cd1eb72bSSean Callanan    break;
490cd1eb72bSSean Callanan  case 4:
491cd1eb72bSSean Callanan    encoding_flags = 0x0c000100; /* 0x0c000100 is kCFStringEncodingUTF32 */
492cd1eb72bSSean Callanan    break;
493cd1eb72bSSean Callanan  default:
494cd1eb72bSSean Callanan    encoding_flags = 0x0600; /* fall back to 0x0600, kCFStringEncodingASCII */
495107d9bbdSPavel Labath    LLDB_LOG(log, "Encountered an Objective-C constant string with unusual "
49663dea591SLuke Drummond                  "element size {0}",
497cd1eb72bSSean Callanan             string_array->getElementByteSize());
498cd1eb72bSSean Callanan  }
499cd1eb72bSSean Callanan  Constant *encoding_arg = ConstantInt::get(i32_ty, encoding_flags, false);
500b9c1b51eSKate Stone  Constant *isExternal_arg =
501b9c1b51eSKate Stone      ConstantInt::get(i8_ty, 0x0, false); /* 0x0 is false */
5024dbb271fSSean Callanan 
5034dbb271fSSean Callanan  Value *argument_array[5];
5044dbb271fSSean Callanan 
5054dbb271fSSean Callanan  argument_array[0] = alloc_arg;
5064dbb271fSSean Callanan  argument_array[1] = bytes_arg;
5074dbb271fSSean Callanan  argument_array[2] = numBytes_arg;
5084dbb271fSSean Callanan  argument_array[3] = encoding_arg;
5094dbb271fSSean Callanan  argument_array[4] = isExternal_arg;
5104dbb271fSSean Callanan 
5114dbb271fSSean Callanan  ArrayRef<Value *> CFSCWB_arguments(argument_array, 5);
5124dbb271fSSean Callanan 
513b9c1b51eSKate Stone  FunctionValueCache CFSCWB_Caller(
514b9c1b51eSKate Stone      [this, &CFSCWB_arguments](llvm::Function *function) -> llvm::Value * {
515b9c1b51eSKate Stone        return CallInst::Create(
516b9c1b51eSKate Stone            m_CFStringCreateWithBytes, CFSCWB_arguments,
5174dbb271fSSean Callanan            "CFStringCreateWithBytes",
518b9c1b51eSKate Stone            llvm::cast<Instruction>(
519b9c1b51eSKate Stone                m_entry_instruction_finder.GetValue(function)));
5204dbb271fSSean Callanan      });
5214dbb271fSSean Callanan 
522cd1eb72bSSean Callanan  if (!UnfoldConstant(ns_str, nullptr, CFSCWB_Caller, m_entry_instruction_finder,
523cd1eb72bSSean Callanan                      m_error_stream)) {
5244ef50a33SRaphael Isemann    LLDB_LOG(log, "Couldn't replace the NSString with the result of the call");
5254dbb271fSSean Callanan 
526b9c1b51eSKate Stone    m_error_stream.Printf("error [IRForTarget internal]: Couldn't replace an "
527b9c1b51eSKate Stone                          "Objective-C constant string with a dynamic "
528b9c1b51eSKate Stone                          "string\n");
5294dbb271fSSean Callanan 
5304dbb271fSSean Callanan    return false;
5314dbb271fSSean Callanan   }
5324dbb271fSSean Callanan 
5334dbb271fSSean Callanan   ns_str->eraseFromParent();
5344dbb271fSSean Callanan 
5354dbb271fSSean Callanan   return true;
5364dbb271fSSean Callanan }
5374dbb271fSSean Callanan 
RewriteObjCConstStrings()538b9c1b51eSKate Stone bool IRForTarget::RewriteObjCConstStrings() {
539a007a6d8SPavel Labath   lldb_private::Log *log(GetLog(LLDBLog::Expressions));
5404dbb271fSSean Callanan 
5414dbb271fSSean Callanan   ValueSymbolTable &value_symbol_table = m_module->getValueSymbolTable();
5424dbb271fSSean Callanan 
543dced445bSRaphael Isemann   for (StringMapEntry<llvm::Value *> &value_symbol : value_symbol_table) {
544474d70b2SRaphael Isemann     llvm::StringRef value_name = value_symbol.first();
5454dbb271fSSean Callanan 
546474d70b2SRaphael Isemann     if (value_name.contains("_unnamed_cfstring_")) {
547dced445bSRaphael Isemann       Value *nsstring_value = value_symbol.second;
5484dbb271fSSean Callanan 
549b9c1b51eSKate Stone       GlobalVariable *nsstring_global =
550b9c1b51eSKate Stone           dyn_cast<GlobalVariable>(nsstring_value);
5514dbb271fSSean Callanan 
552b9c1b51eSKate Stone       if (!nsstring_global) {
5534ef50a33SRaphael Isemann         LLDB_LOG(log, "NSString variable is not a GlobalVariable");
5544dbb271fSSean Callanan 
555b9c1b51eSKate Stone         m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C "
556b9c1b51eSKate Stone                               "constant string is not a global variable\n");
5574dbb271fSSean Callanan 
5584dbb271fSSean Callanan         return false;
5594dbb271fSSean Callanan       }
5604dbb271fSSean Callanan 
561b9c1b51eSKate Stone       if (!nsstring_global->hasInitializer()) {
5624ef50a33SRaphael Isemann         LLDB_LOG(log, "NSString variable does not have an initializer");
5634dbb271fSSean Callanan 
564b9c1b51eSKate Stone         m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C "
565b9c1b51eSKate Stone                               "constant string does not have an initializer\n");
5664dbb271fSSean Callanan 
5674dbb271fSSean Callanan         return false;
5684dbb271fSSean Callanan       }
5694dbb271fSSean Callanan 
570b9c1b51eSKate Stone       ConstantStruct *nsstring_struct =
571b9c1b51eSKate Stone           dyn_cast<ConstantStruct>(nsstring_global->getInitializer());
5724dbb271fSSean Callanan 
573b9c1b51eSKate Stone       if (!nsstring_struct) {
5744ef50a33SRaphael Isemann         LLDB_LOG(log,
575b9c1b51eSKate Stone                  "NSString variable's initializer is not a ConstantStruct");
5764dbb271fSSean Callanan 
577b9c1b51eSKate Stone         m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C "
578b9c1b51eSKate Stone                               "constant string is not a structure constant\n");
5794dbb271fSSean Callanan 
5804dbb271fSSean Callanan         return false;
5814dbb271fSSean Callanan       }
5824dbb271fSSean Callanan 
5834dbb271fSSean Callanan       // We expect the following structure:
5844dbb271fSSean Callanan       //
5854dbb271fSSean Callanan       // struct {
5864dbb271fSSean Callanan       //   int *isa;
5874dbb271fSSean Callanan       //   int flags;
5884dbb271fSSean Callanan       //   char *str;
5894dbb271fSSean Callanan       //   long length;
5904dbb271fSSean Callanan       // };
5914dbb271fSSean Callanan 
592b9c1b51eSKate Stone       if (nsstring_struct->getNumOperands() != 4) {
5934ef50a33SRaphael Isemann 
5944ef50a33SRaphael Isemann         LLDB_LOG(log,
59563e5fb76SJonas Devlieghere                  "NSString variable's initializer structure has an "
5964ef50a33SRaphael Isemann                  "unexpected number of members.  Should be 4, is {0}",
597b9c1b51eSKate Stone                  nsstring_struct->getNumOperands());
5984dbb271fSSean Callanan 
599b9c1b51eSKate Stone         m_error_stream.Printf("Internal error [IRForTarget]: The struct for an "
600b9c1b51eSKate Stone                               "Objective-C constant string is not as "
601b9c1b51eSKate Stone                               "expected\n");
6024dbb271fSSean Callanan 
6034dbb271fSSean Callanan         return false;
6044dbb271fSSean Callanan       }
6054dbb271fSSean Callanan 
6064dbb271fSSean Callanan       Constant *nsstring_member = nsstring_struct->getOperand(2);
6074dbb271fSSean Callanan 
608b9c1b51eSKate Stone       if (!nsstring_member) {
6094ef50a33SRaphael Isemann         LLDB_LOG(log, "NSString initializer's str element was empty");
6104dbb271fSSean Callanan 
611b9c1b51eSKate Stone         m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C "
612b9c1b51eSKate Stone                               "constant string does not have a string "
613b9c1b51eSKate Stone                               "initializer\n");
6144dbb271fSSean Callanan 
6154dbb271fSSean Callanan         return false;
6164dbb271fSSean Callanan       }
6174dbb271fSSean Callanan 
618e7b929d7SAdrian Prantl       auto *cstr_global = dyn_cast<GlobalVariable>(nsstring_member);
619b9c1b51eSKate Stone       if (!cstr_global) {
6204ef50a33SRaphael Isemann         LLDB_LOG(log,
621b9c1b51eSKate Stone                  "NSString initializer's str element is not a GlobalVariable");
6224dbb271fSSean Callanan 
623cd1eb72bSSean Callanan         m_error_stream.Printf("Internal error [IRForTarget]: Unhandled"
624cd1eb72bSSean Callanan                               "constant string initializer\n");
6254dbb271fSSean Callanan 
6264dbb271fSSean Callanan         return false;
6274dbb271fSSean Callanan       }
6284dbb271fSSean Callanan 
629b9c1b51eSKate Stone       if (!cstr_global->hasInitializer()) {
6304ef50a33SRaphael Isemann         LLDB_LOG(log, "NSString initializer's str element does not have an "
631b9c1b51eSKate Stone                       "initializer");
6324dbb271fSSean Callanan 
633b9c1b51eSKate Stone         m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C "
634b9c1b51eSKate Stone                               "constant string's string initializer doesn't "
635b9c1b51eSKate Stone                               "point to initialized data\n");
6364dbb271fSSean Callanan 
6374dbb271fSSean Callanan         return false;
6384dbb271fSSean Callanan       }
6394dbb271fSSean Callanan 
6404dbb271fSSean Callanan       /*
6414dbb271fSSean Callanan       if (!cstr_array)
6424dbb271fSSean Callanan       {
6434dbb271fSSean Callanan           if (log)
644b9c1b51eSKate Stone               log->PutCString("NSString initializer's str element is not a
645b9c1b51eSKate Stone       ConstantArray");
6464dbb271fSSean Callanan 
6474dbb271fSSean Callanan           if (m_error_stream)
648b9c1b51eSKate Stone               m_error_stream.Printf("Internal error [IRForTarget]: An
649b9c1b51eSKate Stone       Objective-C constant string's string initializer doesn't point to an
650b9c1b51eSKate Stone       array\n");
6514dbb271fSSean Callanan 
6524dbb271fSSean Callanan           return false;
6534dbb271fSSean Callanan       }
6544dbb271fSSean Callanan 
6554dbb271fSSean Callanan       if (!cstr_array->isCString())
6564dbb271fSSean Callanan       {
6574dbb271fSSean Callanan           if (log)
658b9c1b51eSKate Stone               log->PutCString("NSString initializer's str element is not a C
659b9c1b51eSKate Stone       string array");
6604dbb271fSSean Callanan 
6614dbb271fSSean Callanan           if (m_error_stream)
662b9c1b51eSKate Stone               m_error_stream.Printf("Internal error [IRForTarget]: An
663b9c1b51eSKate Stone       Objective-C constant string's string initializer doesn't point to a C
664b9c1b51eSKate Stone       string\n");
6654dbb271fSSean Callanan 
6664dbb271fSSean Callanan           return false;
6674dbb271fSSean Callanan       }
6684dbb271fSSean Callanan       */
6694dbb271fSSean Callanan 
670b9c1b51eSKate Stone       ConstantDataArray *cstr_array =
671b9c1b51eSKate Stone           dyn_cast<ConstantDataArray>(cstr_global->getInitializer());
6724dbb271fSSean Callanan 
6734dbb271fSSean Callanan       if (cstr_array)
674474d70b2SRaphael Isemann         LLDB_LOG(log, "Found NSString constant {0}, which contains \"{1}\"",
675474d70b2SRaphael Isemann                  value_name, cstr_array->getAsString());
6764dbb271fSSean Callanan       else
677474d70b2SRaphael Isemann         LLDB_LOG(log, "Found NSString constant {0}, which contains \"\"",
678474d70b2SRaphael Isemann                  value_name);
6794dbb271fSSean Callanan 
6804dbb271fSSean Callanan       if (!cstr_array)
681248a1305SKonrad Kleine         cstr_global = nullptr;
6824dbb271fSSean Callanan 
683b9c1b51eSKate Stone       if (!RewriteObjCConstString(nsstring_global, cstr_global)) {
6844ef50a33SRaphael Isemann         LLDB_LOG(log, "Error rewriting the constant string");
6854dbb271fSSean Callanan 
686b9c1b51eSKate Stone         // We don't print an error message here because RewriteObjCConstString
687b9c1b51eSKate Stone         // has done so for us.
6884dbb271fSSean Callanan 
6894dbb271fSSean Callanan         return false;
6904dbb271fSSean Callanan       }
6914dbb271fSSean Callanan     }
6924dbb271fSSean Callanan   }
6934dbb271fSSean Callanan 
694dced445bSRaphael Isemann   for (StringMapEntry<llvm::Value *> &value_symbol : value_symbol_table) {
695474d70b2SRaphael Isemann     llvm::StringRef value_name = value_symbol.first();
6964dbb271fSSean Callanan 
697474d70b2SRaphael Isemann     if (value_name == "__CFConstantStringClassReference") {
698dced445bSRaphael Isemann       GlobalVariable *gv = dyn_cast<GlobalVariable>(value_symbol.second);
6994dbb271fSSean Callanan 
700b9c1b51eSKate Stone       if (!gv) {
7014ef50a33SRaphael Isemann         LLDB_LOG(log,
702b9c1b51eSKate Stone                  "__CFConstantStringClassReference is not a global variable");
7034dbb271fSSean Callanan 
704b9c1b51eSKate Stone         m_error_stream.Printf("Internal error [IRForTarget]: Found a "
705b9c1b51eSKate Stone                               "CFConstantStringClassReference, but it is not a "
706b9c1b51eSKate Stone                               "global object\n");
7074dbb271fSSean Callanan 
7084dbb271fSSean Callanan         return false;
7094dbb271fSSean Callanan       }
7104dbb271fSSean Callanan 
7114dbb271fSSean Callanan       gv->eraseFromParent();
7124dbb271fSSean Callanan 
7134dbb271fSSean Callanan       break;
7144dbb271fSSean Callanan     }
7154dbb271fSSean Callanan   }
7164dbb271fSSean Callanan 
7174dbb271fSSean Callanan   return true;
7184dbb271fSSean Callanan }
7194dbb271fSSean Callanan 
IsObjCSelectorRef(Value * value)720b9c1b51eSKate Stone static bool IsObjCSelectorRef(Value *value) {
7214dbb271fSSean Callanan   GlobalVariable *global_variable = dyn_cast<GlobalVariable>(value);
7224dbb271fSSean Callanan 
723a6682a41SJonas Devlieghere   return !(!global_variable || !global_variable->hasName() ||
724a6682a41SJonas Devlieghere            !global_variable->getName().startswith("OBJC_SELECTOR_REFERENCES_"));
7254dbb271fSSean Callanan }
7264dbb271fSSean Callanan 
7274dbb271fSSean Callanan // This function does not report errors; its callers are responsible.
RewriteObjCSelector(Instruction * selector_load)728b9c1b51eSKate Stone bool IRForTarget::RewriteObjCSelector(Instruction *selector_load) {
729a007a6d8SPavel Labath   lldb_private::Log *log(GetLog(LLDBLog::Expressions));
7304dbb271fSSean Callanan 
7314dbb271fSSean Callanan   LoadInst *load = dyn_cast<LoadInst>(selector_load);
7324dbb271fSSean Callanan 
7334dbb271fSSean Callanan   if (!load)
7344dbb271fSSean Callanan     return false;
7354dbb271fSSean Callanan 
736b9c1b51eSKate Stone   // Unpack the message name from the selector.  In LLVM IR, an objc_msgSend
737b9c1b51eSKate Stone   // gets represented as
7384dbb271fSSean Callanan   //
7398eed95c8SAdrian Prantl   //   %sel = load ptr, ptr @OBJC_SELECTOR_REFERENCES_, align 8
7408eed95c8SAdrian Prantl   //   call i8 @objc_msgSend(ptr %obj, ptr %sel, ...)
7414dbb271fSSean Callanan   //
7428eed95c8SAdrian Prantl   // where %obj is the object pointer and %sel is the selector.
7434dbb271fSSean Callanan   //
744b9c1b51eSKate Stone   // @"OBJC_SELECTOR_REFERENCES_" is a pointer to a character array called
745b9c1b51eSKate Stone   // @"\01L_OBJC_llvm_moduleETH_VAR_NAllvm_moduleE_".
7464dbb271fSSean Callanan   // @"\01L_OBJC_llvm_moduleETH_VAR_NAllvm_moduleE_" contains the string.
7474dbb271fSSean Callanan 
7488eed95c8SAdrian Prantl   // Find the pointer's initializer and get the string from its target.
7494dbb271fSSean Callanan 
750b9c1b51eSKate Stone   GlobalVariable *_objc_selector_references_ =
751b9c1b51eSKate Stone       dyn_cast<GlobalVariable>(load->getPointerOperand());
7524dbb271fSSean Callanan 
753b9c1b51eSKate Stone   if (!_objc_selector_references_ ||
754b9c1b51eSKate Stone       !_objc_selector_references_->hasInitializer())
7554dbb271fSSean Callanan     return false;
7564dbb271fSSean Callanan 
7574dbb271fSSean Callanan   Constant *osr_initializer = _objc_selector_references_->getInitializer();
7588eed95c8SAdrian Prantl   if (!osr_initializer)
7594dbb271fSSean Callanan     return false;
7604dbb271fSSean Callanan 
7614dbb271fSSean Callanan   // Find the string's initializer (a ConstantArray) and get the string from it
7624dbb271fSSean Callanan 
763b9c1b51eSKate Stone   GlobalVariable *_objc_meth_var_name_ =
7648eed95c8SAdrian Prantl       dyn_cast<GlobalVariable>(osr_initializer);
7654dbb271fSSean Callanan 
7664dbb271fSSean Callanan   if (!_objc_meth_var_name_ || !_objc_meth_var_name_->hasInitializer())
7674dbb271fSSean Callanan     return false;
7684dbb271fSSean Callanan 
7694dbb271fSSean Callanan   Constant *omvn_initializer = _objc_meth_var_name_->getInitializer();
7704dbb271fSSean Callanan 
771b9c1b51eSKate Stone   ConstantDataArray *omvn_initializer_array =
772b9c1b51eSKate Stone       dyn_cast<ConstantDataArray>(omvn_initializer);
7734dbb271fSSean Callanan 
7744dbb271fSSean Callanan   if (!omvn_initializer_array->isString())
7754dbb271fSSean Callanan     return false;
7764dbb271fSSean Callanan 
777adcd0268SBenjamin Kramer   std::string omvn_initializer_string =
778adcd0268SBenjamin Kramer       std::string(omvn_initializer_array->getAsString());
7794dbb271fSSean Callanan 
7804ef50a33SRaphael Isemann   LLDB_LOG(log, "Found Objective-C selector reference \"{0}\"",
7814ef50a33SRaphael Isemann            omvn_initializer_string);
7824dbb271fSSean Callanan 
7834dbb271fSSean Callanan   // Construct a call to sel_registerName
7844dbb271fSSean Callanan 
785b9c1b51eSKate Stone   if (!m_sel_registerName) {
7864dbb271fSSean Callanan     lldb::addr_t sel_registerName_addr;
7874dbb271fSSean Callanan 
788f2128b28SJim Ingham     bool missing_weak = false;
7894dbb271fSSean Callanan     static lldb_private::ConstString g_sel_registerName_str("sel_registerName");
790f2128b28SJim Ingham     sel_registerName_addr = m_execution_unit.FindSymbol(g_sel_registerName_str,
791f2128b28SJim Ingham                                                         missing_weak);
792f2128b28SJim Ingham     if (sel_registerName_addr == LLDB_INVALID_ADDRESS || missing_weak)
7934dbb271fSSean Callanan       return false;
7944dbb271fSSean Callanan 
7954ef50a33SRaphael Isemann     LLDB_LOG(log, "Found sel_registerName at {0}", sel_registerName_addr);
7964dbb271fSSean Callanan 
79705097246SAdrian Prantl     // Build the function type: struct objc_selector
79805097246SAdrian Prantl     // *sel_registerName(uint8_t*)
7994dbb271fSSean Callanan 
800b9c1b51eSKate Stone     // The below code would be "more correct," but in actuality what's required
801b9c1b51eSKate Stone     // is uint8_t*
8024dbb271fSSean Callanan     // Type *sel_type = StructType::get(m_module->getContext());
8034dbb271fSSean Callanan     // Type *sel_ptr_type = PointerType::getUnqual(sel_type);
8044dbb271fSSean Callanan     Type *sel_ptr_type = Type::getInt8PtrTy(m_module->getContext());
8054dbb271fSSean Callanan 
8064dbb271fSSean Callanan     Type *type_array[1];
8074dbb271fSSean Callanan 
8084dbb271fSSean Callanan     type_array[0] = llvm::Type::getInt8PtrTy(m_module->getContext());
8094dbb271fSSean Callanan 
8104dbb271fSSean Callanan     ArrayRef<Type *> srN_arg_types(type_array, 1);
8114dbb271fSSean Callanan 
812ae2f9512SJames Y Knight     llvm::FunctionType *srN_type =
813b9c1b51eSKate Stone         FunctionType::get(sel_ptr_type, srN_arg_types, false);
8144dbb271fSSean Callanan 
8154dbb271fSSean Callanan     // Build the constant containing the pointer to the function
8164dbb271fSSean Callanan     PointerType *srN_ptr_ty = PointerType::getUnqual(srN_type);
817b9c1b51eSKate Stone     Constant *srN_addr_int =
818b9c1b51eSKate Stone         ConstantInt::get(m_intptr_ty, sel_registerName_addr, false);
819ae2f9512SJames Y Knight     m_sel_registerName = {srN_type,
820ae2f9512SJames Y Knight                           ConstantExpr::getIntToPtr(srN_addr_int, srN_ptr_ty)};
8214dbb271fSSean Callanan   }
8224dbb271fSSean Callanan 
8234dbb271fSSean Callanan   Value *argument_array[1];
8244dbb271fSSean Callanan 
825b9c1b51eSKate Stone   Constant *omvn_pointer = ConstantExpr::getBitCast(
826b9c1b51eSKate Stone       _objc_meth_var_name_, Type::getInt8PtrTy(m_module->getContext()));
8274dbb271fSSean Callanan 
8284dbb271fSSean Callanan   argument_array[0] = omvn_pointer;
8294dbb271fSSean Callanan 
8304dbb271fSSean Callanan   ArrayRef<Value *> srN_arguments(argument_array, 1);
8314dbb271fSSean Callanan 
832b9c1b51eSKate Stone   CallInst *srN_call = CallInst::Create(m_sel_registerName, srN_arguments,
833b9c1b51eSKate Stone                                         "sel_registerName", selector_load);
8344dbb271fSSean Callanan 
8354dbb271fSSean Callanan   // Replace the load with the call in all users
8364dbb271fSSean Callanan 
8374dbb271fSSean Callanan   selector_load->replaceAllUsesWith(srN_call);
8384dbb271fSSean Callanan 
8394dbb271fSSean Callanan   selector_load->eraseFromParent();
8404dbb271fSSean Callanan 
8414dbb271fSSean Callanan   return true;
8424dbb271fSSean Callanan }
8434dbb271fSSean Callanan 
RewriteObjCSelectors(BasicBlock & basic_block)844b9c1b51eSKate Stone bool IRForTarget::RewriteObjCSelectors(BasicBlock &basic_block) {
845a007a6d8SPavel Labath   lldb_private::Log *log(GetLog(LLDBLog::Expressions));
8464dbb271fSSean Callanan 
8474dbb271fSSean Callanan   InstrList selector_loads;
8484dbb271fSSean Callanan 
849dced445bSRaphael Isemann   for (Instruction &inst : basic_block) {
8504dbb271fSSean Callanan     if (LoadInst *load = dyn_cast<LoadInst>(&inst))
8514dbb271fSSean Callanan       if (IsObjCSelectorRef(load->getPointerOperand()))
8524dbb271fSSean Callanan         selector_loads.push_back(&inst);
8534dbb271fSSean Callanan   }
8544dbb271fSSean Callanan 
855dced445bSRaphael Isemann   for (Instruction *inst : selector_loads) {
856dced445bSRaphael Isemann     if (!RewriteObjCSelector(inst)) {
857b9c1b51eSKate Stone       m_error_stream.Printf("Internal error [IRForTarget]: Couldn't change a "
858b9c1b51eSKate Stone                             "static reference to an Objective-C selector to a "
859b9c1b51eSKate Stone                             "dynamic reference\n");
8604dbb271fSSean Callanan 
8614ef50a33SRaphael Isemann       LLDB_LOG(log, "Couldn't rewrite a reference to an Objective-C selector");
8624dbb271fSSean Callanan 
8634dbb271fSSean Callanan       return false;
8644dbb271fSSean Callanan     }
8654dbb271fSSean Callanan   }
8664dbb271fSSean Callanan 
8674dbb271fSSean Callanan   return true;
8684dbb271fSSean Callanan }
8694dbb271fSSean Callanan 
IsObjCClassReference(Value * value)870ac90058bSSean Callanan static bool IsObjCClassReference(Value *value) {
871ac90058bSSean Callanan   GlobalVariable *global_variable = dyn_cast<GlobalVariable>(value);
872ac90058bSSean Callanan 
873a6682a41SJonas Devlieghere   return !(!global_variable || !global_variable->hasName() ||
874a6682a41SJonas Devlieghere            !global_variable->getName().startswith("OBJC_CLASS_REFERENCES_"));
875ac90058bSSean Callanan }
876ac90058bSSean Callanan 
877ac90058bSSean Callanan // This function does not report errors; its callers are responsible.
RewriteObjCClassReference(Instruction * class_load)878ac90058bSSean Callanan bool IRForTarget::RewriteObjCClassReference(Instruction *class_load) {
879a007a6d8SPavel Labath   lldb_private::Log *log(GetLog(LLDBLog::Expressions));
880ac90058bSSean Callanan 
881ac90058bSSean Callanan   LoadInst *load = dyn_cast<LoadInst>(class_load);
882ac90058bSSean Callanan 
883ac90058bSSean Callanan   if (!load)
884ac90058bSSean Callanan     return false;
885ac90058bSSean Callanan 
886ac90058bSSean Callanan   // Unpack the class name from the reference.  In LLVM IR, a reference to an
887ac90058bSSean Callanan   // Objective-C class gets represented as
888ac90058bSSean Callanan   //
889ac90058bSSean Callanan   // %tmp     = load %struct._objc_class*,
890ac90058bSSean Callanan   //            %struct._objc_class** @OBJC_CLASS_REFERENCES_, align 4
891ac90058bSSean Callanan   //
892ac90058bSSean Callanan   // @"OBJC_CLASS_REFERENCES_ is a bitcast of a character array called
89305097246SAdrian Prantl   // @OBJC_CLASS_NAME_. @OBJC_CLASS_NAME contains the string.
894ac90058bSSean Callanan 
89505097246SAdrian Prantl   // Find the pointer's initializer (a ConstantExpr with opcode BitCast) and
89605097246SAdrian Prantl   // get the string from its target
897ac90058bSSean Callanan 
898ac90058bSSean Callanan   GlobalVariable *_objc_class_references_ =
899ac90058bSSean Callanan       dyn_cast<GlobalVariable>(load->getPointerOperand());
900ac90058bSSean Callanan 
901ac90058bSSean Callanan   if (!_objc_class_references_ ||
902ac90058bSSean Callanan       !_objc_class_references_->hasInitializer())
903ac90058bSSean Callanan     return false;
904ac90058bSSean Callanan 
905ac90058bSSean Callanan   Constant *ocr_initializer = _objc_class_references_->getInitializer();
906ac90058bSSean Callanan 
907ac90058bSSean Callanan   ConstantExpr *ocr_initializer_expr = dyn_cast<ConstantExpr>(ocr_initializer);
908ac90058bSSean Callanan 
909ac90058bSSean Callanan   if (!ocr_initializer_expr ||
910ac90058bSSean Callanan       ocr_initializer_expr->getOpcode() != Instruction::BitCast)
911ac90058bSSean Callanan     return false;
912ac90058bSSean Callanan 
913ac90058bSSean Callanan   Value *ocr_initializer_base = ocr_initializer_expr->getOperand(0);
914ac90058bSSean Callanan 
915ac90058bSSean Callanan   if (!ocr_initializer_base)
916ac90058bSSean Callanan     return false;
917ac90058bSSean Callanan 
918ac90058bSSean Callanan   // Find the string's initializer (a ConstantArray) and get the string from it
919ac90058bSSean Callanan 
920ac90058bSSean Callanan   GlobalVariable *_objc_class_name_ =
921ac90058bSSean Callanan       dyn_cast<GlobalVariable>(ocr_initializer_base);
922ac90058bSSean Callanan 
923ac90058bSSean Callanan   if (!_objc_class_name_ || !_objc_class_name_->hasInitializer())
924ac90058bSSean Callanan     return false;
925ac90058bSSean Callanan 
926ac90058bSSean Callanan   Constant *ocn_initializer = _objc_class_name_->getInitializer();
927ac90058bSSean Callanan 
928ac90058bSSean Callanan   ConstantDataArray *ocn_initializer_array =
929ac90058bSSean Callanan       dyn_cast<ConstantDataArray>(ocn_initializer);
930ac90058bSSean Callanan 
931ac90058bSSean Callanan   if (!ocn_initializer_array->isString())
932ac90058bSSean Callanan     return false;
933ac90058bSSean Callanan 
934adcd0268SBenjamin Kramer   std::string ocn_initializer_string =
935adcd0268SBenjamin Kramer       std::string(ocn_initializer_array->getAsString());
936ac90058bSSean Callanan 
9374ef50a33SRaphael Isemann   LLDB_LOG(log, "Found Objective-C class reference \"{0}\"",
9384ef50a33SRaphael Isemann            ocn_initializer_string);
939ac90058bSSean Callanan 
940ac90058bSSean Callanan   // Construct a call to objc_getClass
941ac90058bSSean Callanan 
942ac90058bSSean Callanan   if (!m_objc_getClass) {
943ac90058bSSean Callanan     lldb::addr_t objc_getClass_addr;
944ac90058bSSean Callanan 
945f2128b28SJim Ingham     bool missing_weak = false;
946ac90058bSSean Callanan     static lldb_private::ConstString g_objc_getClass_str("objc_getClass");
947f2128b28SJim Ingham     objc_getClass_addr = m_execution_unit.FindSymbol(g_objc_getClass_str,
948f2128b28SJim Ingham                                                      missing_weak);
949f2128b28SJim Ingham     if (objc_getClass_addr == LLDB_INVALID_ADDRESS || missing_weak)
950ac90058bSSean Callanan       return false;
951ac90058bSSean Callanan 
9524ef50a33SRaphael Isemann     LLDB_LOG(log, "Found objc_getClass at {0}", objc_getClass_addr);
953ac90058bSSean Callanan 
954ac90058bSSean Callanan     // Build the function type: %struct._objc_class *objc_getClass(i8*)
955ac90058bSSean Callanan 
956ac90058bSSean Callanan     Type *class_type = load->getType();
957ac90058bSSean Callanan     Type *type_array[1];
958ac90058bSSean Callanan     type_array[0] = llvm::Type::getInt8PtrTy(m_module->getContext());
959ac90058bSSean Callanan 
960ac90058bSSean Callanan     ArrayRef<Type *> ogC_arg_types(type_array, 1);
961ac90058bSSean Callanan 
962ae2f9512SJames Y Knight     llvm::FunctionType *ogC_type =
963ac90058bSSean Callanan         FunctionType::get(class_type, ogC_arg_types, false);
964ac90058bSSean Callanan 
965ac90058bSSean Callanan     // Build the constant containing the pointer to the function
966ac90058bSSean Callanan     PointerType *ogC_ptr_ty = PointerType::getUnqual(ogC_type);
967ac90058bSSean Callanan     Constant *ogC_addr_int =
968ac90058bSSean Callanan         ConstantInt::get(m_intptr_ty, objc_getClass_addr, false);
969ae2f9512SJames Y Knight     m_objc_getClass = {ogC_type,
970ae2f9512SJames Y Knight                        ConstantExpr::getIntToPtr(ogC_addr_int, ogC_ptr_ty)};
971ac90058bSSean Callanan   }
972ac90058bSSean Callanan 
973ac90058bSSean Callanan   Value *argument_array[1];
974ac90058bSSean Callanan 
975ac90058bSSean Callanan   Constant *ocn_pointer = ConstantExpr::getBitCast(
976ac90058bSSean Callanan       _objc_class_name_, Type::getInt8PtrTy(m_module->getContext()));
977ac90058bSSean Callanan 
978ac90058bSSean Callanan   argument_array[0] = ocn_pointer;
979ac90058bSSean Callanan 
980ac90058bSSean Callanan   ArrayRef<Value *> ogC_arguments(argument_array, 1);
981ac90058bSSean Callanan 
982ac90058bSSean Callanan   CallInst *ogC_call = CallInst::Create(m_objc_getClass, ogC_arguments,
983ac90058bSSean Callanan                                         "objc_getClass", class_load);
984ac90058bSSean Callanan 
985ac90058bSSean Callanan   // Replace the load with the call in all users
986ac90058bSSean Callanan 
987ac90058bSSean Callanan   class_load->replaceAllUsesWith(ogC_call);
988ac90058bSSean Callanan 
989ac90058bSSean Callanan   class_load->eraseFromParent();
990ac90058bSSean Callanan 
991ac90058bSSean Callanan   return true;
992ac90058bSSean Callanan }
993ac90058bSSean Callanan 
RewriteObjCClassReferences(BasicBlock & basic_block)994ac90058bSSean Callanan bool IRForTarget::RewriteObjCClassReferences(BasicBlock &basic_block) {
995a007a6d8SPavel Labath   lldb_private::Log *log(GetLog(LLDBLog::Expressions));
996ac90058bSSean Callanan 
997ac90058bSSean Callanan   InstrList class_loads;
998ac90058bSSean Callanan 
999dced445bSRaphael Isemann   for (Instruction &inst : basic_block) {
1000ac90058bSSean Callanan     if (LoadInst *load = dyn_cast<LoadInst>(&inst))
1001ac90058bSSean Callanan       if (IsObjCClassReference(load->getPointerOperand()))
1002ac90058bSSean Callanan         class_loads.push_back(&inst);
1003ac90058bSSean Callanan   }
1004ac90058bSSean Callanan 
1005dced445bSRaphael Isemann   for (Instruction *inst : class_loads) {
1006dced445bSRaphael Isemann     if (!RewriteObjCClassReference(inst)) {
1007ac90058bSSean Callanan       m_error_stream.Printf("Internal error [IRForTarget]: Couldn't change a "
1008ac90058bSSean Callanan                             "static reference to an Objective-C class to a "
1009ac90058bSSean Callanan                             "dynamic reference\n");
1010ac90058bSSean Callanan 
10114ef50a33SRaphael Isemann       LLDB_LOG(log, "Couldn't rewrite a reference to an Objective-C class");
1012ac90058bSSean Callanan 
1013ac90058bSSean Callanan       return false;
1014ac90058bSSean Callanan     }
1015ac90058bSSean Callanan   }
1016ac90058bSSean Callanan 
1017ac90058bSSean Callanan   return true;
1018ac90058bSSean Callanan }
1019ac90058bSSean Callanan 
10204dbb271fSSean Callanan // This function does not report errors; its callers are responsible.
RewritePersistentAlloc(llvm::Instruction * persistent_alloc)1021b9c1b51eSKate Stone bool IRForTarget::RewritePersistentAlloc(llvm::Instruction *persistent_alloc) {
1022a007a6d8SPavel Labath   lldb_private::Log *log(GetLog(LLDBLog::Expressions));
10234dbb271fSSean Callanan 
10244dbb271fSSean Callanan   AllocaInst *alloc = dyn_cast<AllocaInst>(persistent_alloc);
10254dbb271fSSean Callanan 
10264dbb271fSSean Callanan   MDNode *alloc_md = alloc->getMetadata("clang.decl.ptr");
10274dbb271fSSean Callanan 
10284dbb271fSSean Callanan   if (!alloc_md || !alloc_md->getNumOperands())
10294dbb271fSSean Callanan     return false;
10304dbb271fSSean Callanan 
1031b9c1b51eSKate Stone   ConstantInt *constant_int =
1032b9c1b51eSKate Stone       mdconst::dyn_extract<ConstantInt>(alloc_md->getOperand(0));
10334dbb271fSSean Callanan 
10344dbb271fSSean Callanan   if (!constant_int)
10354dbb271fSSean Callanan     return false;
10364dbb271fSSean Callanan 
10374dbb271fSSean Callanan   // We attempt to register this as a new persistent variable with the DeclMap.
10384dbb271fSSean Callanan 
10394dbb271fSSean Callanan   uintptr_t ptr = constant_int->getZExtValue();
10404dbb271fSSean Callanan 
10414dbb271fSSean Callanan   clang::VarDecl *decl = reinterpret_cast<clang::VarDecl *>(ptr);
10424dbb271fSSean Callanan 
1043b9c1b51eSKate Stone   lldb_private::TypeFromParser result_decl_type(
1044df8a986fSRaphael Isemann       m_decl_map->GetTypeSystem()->GetType(decl->getType()));
10454dbb271fSSean Callanan 
10464dbb271fSSean Callanan   StringRef decl_name(decl->getName());
1047b9c1b51eSKate Stone   lldb_private::ConstString persistent_variable_name(decl_name.data(),
1048b9c1b51eSKate Stone                                                      decl_name.size());
1049b9c1b51eSKate Stone   if (!m_decl_map->AddPersistentVariable(decl, persistent_variable_name,
1050b9c1b51eSKate Stone                                          result_decl_type, false, false))
10514dbb271fSSean Callanan     return false;
10524dbb271fSSean Callanan 
1053b9c1b51eSKate Stone   GlobalVariable *persistent_global = new GlobalVariable(
1054b9c1b51eSKate Stone       (*m_module), alloc->getType(), false,  /* not constant */
1055248a1305SKonrad Kleine       GlobalValue::ExternalLinkage, nullptr, /* no initializer */
1056771ef6d4SMalcolm Parsons       alloc->getName().str());
10574dbb271fSSean Callanan 
105805097246SAdrian Prantl   // What we're going to do here is make believe this was a regular old
105905097246SAdrian Prantl   // external variable.  That means we need to make the metadata valid.
10604dbb271fSSean Callanan 
1061b9c1b51eSKate Stone   NamedMDNode *named_metadata =
1062b9c1b51eSKate Stone       m_module->getOrInsertNamedMetadata("clang.global.decl.ptrs");
10634dbb271fSSean Callanan 
10644dbb271fSSean Callanan   llvm::Metadata *values[2];
10654dbb271fSSean Callanan   values[0] = ConstantAsMetadata::get(persistent_global);
10664dbb271fSSean Callanan   values[1] = ConstantAsMetadata::get(constant_int);
10674dbb271fSSean Callanan 
10684dbb271fSSean Callanan   ArrayRef<llvm::Metadata *> value_ref(values, 2);
10694dbb271fSSean Callanan 
10704dbb271fSSean Callanan   MDNode *persistent_global_md = MDNode::get(m_module->getContext(), value_ref);
10714dbb271fSSean Callanan   named_metadata->addOperand(persistent_global_md);
10724dbb271fSSean Callanan 
1073b9c1b51eSKate Stone   // Now, since the variable is a pointer variable, we will drop in a load of
107405097246SAdrian Prantl   // that pointer variable.
10754dbb271fSSean Callanan 
1076ad1feef7SNikita Popov   LoadInst *persistent_load = new LoadInst(persistent_global->getValueType(),
10776612b826SMed Ismail Bennani                                            persistent_global, "", alloc);
10784dbb271fSSean Callanan 
10794ef50a33SRaphael Isemann   LLDB_LOG(log, "Replacing \"{0}\" with \"{1}\"", PrintValue(alloc),
10804ef50a33SRaphael Isemann            PrintValue(persistent_load));
10814dbb271fSSean Callanan 
10824dbb271fSSean Callanan   alloc->replaceAllUsesWith(persistent_load);
10834dbb271fSSean Callanan   alloc->eraseFromParent();
10844dbb271fSSean Callanan 
10854dbb271fSSean Callanan   return true;
10864dbb271fSSean Callanan }
10874dbb271fSSean Callanan 
RewritePersistentAllocs(llvm::BasicBlock & basic_block)1088b9c1b51eSKate Stone bool IRForTarget::RewritePersistentAllocs(llvm::BasicBlock &basic_block) {
10894dbb271fSSean Callanan   if (!m_resolve_vars)
10904dbb271fSSean Callanan     return true;
10914dbb271fSSean Callanan 
1092a007a6d8SPavel Labath   lldb_private::Log *log(GetLog(LLDBLog::Expressions));
10934dbb271fSSean Callanan 
10944dbb271fSSean Callanan   InstrList pvar_allocs;
10954dbb271fSSean Callanan 
1096dced445bSRaphael Isemann   for (Instruction &inst : basic_block) {
10974dbb271fSSean Callanan 
1098b9c1b51eSKate Stone     if (AllocaInst *alloc = dyn_cast<AllocaInst>(&inst)) {
10994dbb271fSSean Callanan       llvm::StringRef alloc_name = alloc->getName();
11004dbb271fSSean Callanan 
1101b9c1b51eSKate Stone       if (alloc_name.startswith("$") && !alloc_name.startswith("$__lldb")) {
1102b9c1b51eSKate Stone         if (alloc_name.find_first_of("0123456789") == 1) {
11034ef50a33SRaphael Isemann           LLDB_LOG(log, "Rejecting a numeric persistent variable.");
11044dbb271fSSean Callanan 
1105b9c1b51eSKate Stone           m_error_stream.Printf("Error [IRForTarget]: Names starting with $0, "
1106b9c1b51eSKate Stone                                 "$1, ... are reserved for use as result "
1107b9c1b51eSKate Stone                                 "names\n");
11084dbb271fSSean Callanan 
11094dbb271fSSean Callanan           return false;
11104dbb271fSSean Callanan         }
11114dbb271fSSean Callanan 
11124dbb271fSSean Callanan         pvar_allocs.push_back(alloc);
11134dbb271fSSean Callanan       }
11144dbb271fSSean Callanan     }
11154dbb271fSSean Callanan   }
11164dbb271fSSean Callanan 
1117dced445bSRaphael Isemann   for (Instruction *inst : pvar_allocs) {
1118dced445bSRaphael Isemann     if (!RewritePersistentAlloc(inst)) {
1119b9c1b51eSKate Stone       m_error_stream.Printf("Internal error [IRForTarget]: Couldn't rewrite "
1120b9c1b51eSKate Stone                             "the creation of a persistent variable\n");
11214dbb271fSSean Callanan 
11224ef50a33SRaphael Isemann       LLDB_LOG(log, "Couldn't rewrite the creation of a persistent variable");
11234dbb271fSSean Callanan 
11244dbb271fSSean Callanan       return false;
11254dbb271fSSean Callanan     }
11264dbb271fSSean Callanan   }
11274dbb271fSSean Callanan 
11284dbb271fSSean Callanan   return true;
11294dbb271fSSean Callanan }
11304dbb271fSSean Callanan 
11314dbb271fSSean Callanan // This function does not report errors; its callers are responsible.
MaybeHandleVariable(Value * llvm_value_ptr)1132b9c1b51eSKate Stone bool IRForTarget::MaybeHandleVariable(Value *llvm_value_ptr) {
1133a007a6d8SPavel Labath   lldb_private::Log *log(GetLog(LLDBLog::Expressions));
11344dbb271fSSean Callanan 
11354ef50a33SRaphael Isemann   LLDB_LOG(log, "MaybeHandleVariable ({0})", PrintValue(llvm_value_ptr));
11364dbb271fSSean Callanan 
1137b9c1b51eSKate Stone   if (ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(llvm_value_ptr)) {
1138b9c1b51eSKate Stone     switch (constant_expr->getOpcode()) {
11394dbb271fSSean Callanan     default:
11404dbb271fSSean Callanan       break;
11414dbb271fSSean Callanan     case Instruction::GetElementPtr:
11424dbb271fSSean Callanan     case Instruction::BitCast:
11434dbb271fSSean Callanan       Value *s = constant_expr->getOperand(0);
11444dbb271fSSean Callanan       if (!MaybeHandleVariable(s))
11454dbb271fSSean Callanan         return false;
11464dbb271fSSean Callanan     }
1147b9c1b51eSKate Stone   } else if (GlobalVariable *global_variable =
1148b9c1b51eSKate Stone                  dyn_cast<GlobalVariable>(llvm_value_ptr)) {
11494dbb271fSSean Callanan     if (!GlobalValue::isExternalLinkage(global_variable->getLinkage()))
11502a8fa2a8SSean Callanan       return true;
11514dbb271fSSean Callanan 
11524dbb271fSSean Callanan     clang::NamedDecl *named_decl = DeclForGlobal(global_variable);
11534dbb271fSSean Callanan 
1154b9c1b51eSKate Stone     if (!named_decl) {
1155e7daf78eSStella Stamenova       if (IsObjCSelectorRef(llvm_value_ptr))
1156e7daf78eSStella Stamenova         return true;
1157e7daf78eSStella Stamenova 
1158e7daf78eSStella Stamenova       if (!global_variable->hasExternalLinkage())
1159e7daf78eSStella Stamenova         return true;
1160e7daf78eSStella Stamenova 
11614ef50a33SRaphael Isemann       LLDB_LOG(log, "Found global variable \"{0}\" without metadata",
11624ef50a33SRaphael Isemann                global_variable->getName());
11634dbb271fSSean Callanan 
1164e7daf78eSStella Stamenova       return false;
11654dbb271fSSean Callanan     }
11664dbb271fSSean Callanan 
11677491f364SRaphael Isemann     llvm::StringRef name(named_decl->getName());
11684dbb271fSSean Callanan 
11694dbb271fSSean Callanan     clang::ValueDecl *value_decl = dyn_cast<clang::ValueDecl>(named_decl);
1170248a1305SKonrad Kleine     if (value_decl == nullptr)
11714dbb271fSSean Callanan       return false;
11724dbb271fSSean Callanan 
1173df8a986fSRaphael Isemann     lldb_private::CompilerType compiler_type =
1174df8a986fSRaphael Isemann         m_decl_map->GetTypeSystem()->GetType(value_decl->getType());
11754dbb271fSSean Callanan 
1176248a1305SKonrad Kleine     const Type *value_type = nullptr;
11774dbb271fSSean Callanan 
11787491f364SRaphael Isemann     if (name.startswith("$")) {
1179b9c1b51eSKate Stone       // The $__lldb_expr_result name indicates the return value has allocated
118005097246SAdrian Prantl       // as a static variable.  Per the comment at
118105097246SAdrian Prantl       // ASTResultSynthesizer::SynthesizeBodyResult, accesses to this static
118205097246SAdrian Prantl       // variable need to be redirected to the result of dereferencing a
118305097246SAdrian Prantl       // pointer that is passed in as one of the arguments.
11844dbb271fSSean Callanan       //
1185b9c1b51eSKate Stone       // Consequently, when reporting the size of the type, we report a pointer
118605097246SAdrian Prantl       // type pointing to the type of $__lldb_expr_result, not the type itself.
11874dbb271fSSean Callanan       //
11884dbb271fSSean Callanan       // We also do this for any user-declared persistent variables.
11894dbb271fSSean Callanan       compiler_type = compiler_type.GetPointerType();
11904dbb271fSSean Callanan       value_type = PointerType::get(global_variable->getType(), 0);
1191b9c1b51eSKate Stone     } else {
11924dbb271fSSean Callanan       value_type = global_variable->getType();
11934dbb271fSSean Callanan     }
11944dbb271fSSean Callanan 
119502f58373SAdrian Prantl     auto *target = m_execution_unit.GetTarget().get();
119602f58373SAdrian Prantl     llvm::Optional<uint64_t> value_size = compiler_type.GetByteSize(target);
1197d963a7c3SAdrian Prantl     if (!value_size)
1198d963a7c3SAdrian Prantl       return false;
119902f58373SAdrian Prantl     llvm::Optional<size_t> opt_alignment =
120002f58373SAdrian Prantl         compiler_type.GetTypeBitAlign(target);
120136f13e49SDavide Italiano     if (!opt_alignment)
120236f13e49SDavide Italiano       return false;
120336f13e49SDavide Italiano     lldb::offset_t value_alignment = (*opt_alignment + 7ull) / 8ull;
12044dbb271fSSean Callanan 
12054ef50a33SRaphael Isemann     LLDB_LOG(log,
12067491f364SRaphael Isemann              "Type of \"{0}\" is [clang \"{1}\", llvm \"{2}\"] [size {3}, "
12077491f364SRaphael Isemann              "align {4}]",
12087491f364SRaphael Isemann              name,
12097491f364SRaphael Isemann              lldb_private::ClangUtil::GetQualType(compiler_type).getAsString(),
12107491f364SRaphael Isemann              PrintType(value_type), *value_size, value_alignment);
12114dbb271fSSean Callanan 
12120e5eef5cSRaphael Isemann     if (named_decl)
12137491f364SRaphael Isemann       m_decl_map->AddValueToStruct(named_decl, lldb_private::ConstString(name),
12147491f364SRaphael Isemann                                    llvm_value_ptr, *value_size,
12157491f364SRaphael Isemann                                    value_alignment);
121662e48ed1SKazu Hirata   } else if (isa<llvm::Function>(llvm_value_ptr)) {
12174ef50a33SRaphael Isemann     LLDB_LOG(log, "Function pointers aren't handled right now");
12184dbb271fSSean Callanan 
12194dbb271fSSean Callanan     return false;
12204dbb271fSSean Callanan   }
12214dbb271fSSean Callanan 
12224dbb271fSSean Callanan   return true;
12234dbb271fSSean Callanan }
12244dbb271fSSean Callanan 
12254dbb271fSSean Callanan // This function does not report errors; its callers are responsible.
HandleSymbol(Value * symbol)1226b9c1b51eSKate Stone bool IRForTarget::HandleSymbol(Value *symbol) {
1227a007a6d8SPavel Labath   lldb_private::Log *log(GetLog(LLDBLog::Expressions));
12284dbb271fSSean Callanan 
12294dbb271fSSean Callanan   lldb_private::ConstString name(symbol->getName().str().c_str());
12304dbb271fSSean Callanan 
1231b9c1b51eSKate Stone   lldb::addr_t symbol_addr =
1232b9c1b51eSKate Stone       m_decl_map->GetSymbolAddress(name, lldb::eSymbolTypeAny);
12334dbb271fSSean Callanan 
1234b9c1b51eSKate Stone   if (symbol_addr == LLDB_INVALID_ADDRESS) {
12354ef50a33SRaphael Isemann     LLDB_LOG(log, "Symbol \"{0}\" had no address", name);
12364dbb271fSSean Callanan 
12374dbb271fSSean Callanan     return false;
12384dbb271fSSean Callanan   }
12394dbb271fSSean Callanan 
12404ef50a33SRaphael Isemann   LLDB_LOG(log, "Found \"{0}\" at {1}", name, symbol_addr);
12414dbb271fSSean Callanan 
12424dbb271fSSean Callanan   Type *symbol_type = symbol->getType();
12434dbb271fSSean Callanan 
12444dbb271fSSean Callanan   Constant *symbol_addr_int = ConstantInt::get(m_intptr_ty, symbol_addr, false);
12454dbb271fSSean Callanan 
1246b9c1b51eSKate Stone   Value *symbol_addr_ptr =
1247b9c1b51eSKate Stone       ConstantExpr::getIntToPtr(symbol_addr_int, symbol_type);
12484dbb271fSSean Callanan 
12494ef50a33SRaphael Isemann   LLDB_LOG(log, "Replacing {0} with {1}", PrintValue(symbol),
12504ef50a33SRaphael Isemann            PrintValue(symbol_addr_ptr));
12514dbb271fSSean Callanan 
12524dbb271fSSean Callanan   symbol->replaceAllUsesWith(symbol_addr_ptr);
12534dbb271fSSean Callanan 
12544dbb271fSSean Callanan   return true;
12554dbb271fSSean Callanan }
12564dbb271fSSean Callanan 
MaybeHandleCallArguments(CallInst * Old)1257b9c1b51eSKate Stone bool IRForTarget::MaybeHandleCallArguments(CallInst *Old) {
1258a007a6d8SPavel Labath   lldb_private::Log *log(GetLog(LLDBLog::Expressions));
12594dbb271fSSean Callanan 
12604ef50a33SRaphael Isemann   LLDB_LOG(log, "MaybeHandleCallArguments({0})", PrintValue(Old));
12614dbb271fSSean Callanan 
126280e39366SKazu Hirata   for (unsigned op_index = 0, num_ops = Old->arg_size();
1263b9c1b51eSKate Stone        op_index < num_ops; ++op_index)
1264dced445bSRaphael Isemann     // conservatively believe that this is a store
1265dced445bSRaphael Isemann     if (!MaybeHandleVariable(Old->getArgOperand(op_index))) {
1266b9c1b51eSKate Stone       m_error_stream.Printf("Internal error [IRForTarget]: Couldn't rewrite "
1267b9c1b51eSKate Stone                             "one of the arguments of a function call.\n");
12684dbb271fSSean Callanan 
12694dbb271fSSean Callanan       return false;
12704dbb271fSSean Callanan     }
12714dbb271fSSean Callanan 
12724dbb271fSSean Callanan   return true;
12734dbb271fSSean Callanan }
12744dbb271fSSean Callanan 
HandleObjCClass(Value * classlist_reference)1275b9c1b51eSKate Stone bool IRForTarget::HandleObjCClass(Value *classlist_reference) {
1276a007a6d8SPavel Labath   lldb_private::Log *log(GetLog(LLDBLog::Expressions));
12774dbb271fSSean Callanan 
1278b9c1b51eSKate Stone   GlobalVariable *global_variable =
1279b9c1b51eSKate Stone       dyn_cast<GlobalVariable>(classlist_reference);
12804dbb271fSSean Callanan 
12814dbb271fSSean Callanan   if (!global_variable)
12824dbb271fSSean Callanan     return false;
12834dbb271fSSean Callanan 
12844dbb271fSSean Callanan   Constant *initializer = global_variable->getInitializer();
12854dbb271fSSean Callanan 
12864dbb271fSSean Callanan   if (!initializer)
12874dbb271fSSean Callanan     return false;
12884dbb271fSSean Callanan 
12894dbb271fSSean Callanan   if (!initializer->hasName())
12904dbb271fSSean Callanan     return false;
12914dbb271fSSean Callanan 
12924dbb271fSSean Callanan   StringRef name(initializer->getName());
12934dbb271fSSean Callanan   lldb_private::ConstString name_cstr(name.str().c_str());
1294b9c1b51eSKate Stone   lldb::addr_t class_ptr =
1295b9c1b51eSKate Stone       m_decl_map->GetSymbolAddress(name_cstr, lldb::eSymbolTypeObjCClass);
12964dbb271fSSean Callanan 
12974ef50a33SRaphael Isemann   LLDB_LOG(log, "Found reference to Objective-C class {0} ({1})", name,
12984ef50a33SRaphael Isemann            (unsigned long long)class_ptr);
12994dbb271fSSean Callanan 
13004dbb271fSSean Callanan   if (class_ptr == LLDB_INVALID_ADDRESS)
13014dbb271fSSean Callanan     return false;
13024dbb271fSSean Callanan 
13034dbb271fSSean Callanan   if (global_variable->use_empty())
13044dbb271fSSean Callanan     return false;
13054dbb271fSSean Callanan 
13064dbb271fSSean Callanan   SmallVector<LoadInst *, 2> load_instructions;
13074dbb271fSSean Callanan 
1308b9c1b51eSKate Stone   for (llvm::User *u : global_variable->users()) {
13094dbb271fSSean Callanan     if (LoadInst *load_instruction = dyn_cast<LoadInst>(u))
13104dbb271fSSean Callanan       load_instructions.push_back(load_instruction);
13114dbb271fSSean Callanan   }
13124dbb271fSSean Callanan 
13134dbb271fSSean Callanan   if (load_instructions.empty())
13144dbb271fSSean Callanan     return false;
13154dbb271fSSean Callanan 
13164dbb271fSSean Callanan   Constant *class_addr = ConstantInt::get(m_intptr_ty, (uint64_t)class_ptr);
13174dbb271fSSean Callanan 
1318b9c1b51eSKate Stone   for (LoadInst *load_instruction : load_instructions) {
1319b9c1b51eSKate Stone     Constant *class_bitcast =
1320b9c1b51eSKate Stone         ConstantExpr::getIntToPtr(class_addr, load_instruction->getType());
13214dbb271fSSean Callanan 
13224dbb271fSSean Callanan     load_instruction->replaceAllUsesWith(class_bitcast);
13234dbb271fSSean Callanan 
13244dbb271fSSean Callanan     load_instruction->eraseFromParent();
13254dbb271fSSean Callanan   }
13264dbb271fSSean Callanan 
13274dbb271fSSean Callanan   return true;
13284dbb271fSSean Callanan }
13294dbb271fSSean Callanan 
RemoveCXAAtExit(BasicBlock & basic_block)1330b9c1b51eSKate Stone bool IRForTarget::RemoveCXAAtExit(BasicBlock &basic_block) {
13314dbb271fSSean Callanan   std::vector<CallInst *> calls_to_remove;
13324dbb271fSSean Callanan 
1333dced445bSRaphael Isemann   for (Instruction &inst : basic_block) {
13344dbb271fSSean Callanan     CallInst *call = dyn_cast<CallInst>(&inst);
13354dbb271fSSean Callanan 
13364dbb271fSSean Callanan     // MaybeHandleCallArguments handles error reporting; we are silent here
13374dbb271fSSean Callanan     if (!call)
13384dbb271fSSean Callanan       continue;
13394dbb271fSSean Callanan 
13404dbb271fSSean Callanan     bool remove = false;
13414dbb271fSSean Callanan 
13424dbb271fSSean Callanan     llvm::Function *func = call->getCalledFunction();
13434dbb271fSSean Callanan 
13444dbb271fSSean Callanan     if (func && func->getName() == "__cxa_atexit")
13454dbb271fSSean Callanan       remove = true;
13464dbb271fSSean Callanan 
1347a58b62b4SCraig Topper     llvm::Value *val = call->getCalledOperand();
13484dbb271fSSean Callanan 
13494dbb271fSSean Callanan     if (val && val->getName() == "__cxa_atexit")
13504dbb271fSSean Callanan       remove = true;
13514dbb271fSSean Callanan 
13524dbb271fSSean Callanan     if (remove)
13534dbb271fSSean Callanan       calls_to_remove.push_back(call);
13544dbb271fSSean Callanan   }
13554dbb271fSSean Callanan 
1356dced445bSRaphael Isemann   for (CallInst *ci : calls_to_remove)
1357dced445bSRaphael Isemann     ci->eraseFromParent();
13584dbb271fSSean Callanan 
13594dbb271fSSean Callanan   return true;
13604dbb271fSSean Callanan }
13614dbb271fSSean Callanan 
ResolveCalls(BasicBlock & basic_block)1362b9c1b51eSKate Stone bool IRForTarget::ResolveCalls(BasicBlock &basic_block) {
13634dbb271fSSean Callanan   // Prepare the current basic block for execution in the remote process
13644dbb271fSSean Callanan 
1365dced445bSRaphael Isemann   for (Instruction &inst : basic_block) {
13664dbb271fSSean Callanan     CallInst *call = dyn_cast<CallInst>(&inst);
13674dbb271fSSean Callanan 
13684dbb271fSSean Callanan     // MaybeHandleCallArguments handles error reporting; we are silent here
13694dbb271fSSean Callanan     if (call && !MaybeHandleCallArguments(call))
13704dbb271fSSean Callanan       return false;
13714dbb271fSSean Callanan   }
13724dbb271fSSean Callanan 
13734dbb271fSSean Callanan   return true;
13744dbb271fSSean Callanan }
13754dbb271fSSean Callanan 
ResolveExternals(Function & llvm_function)1376b9c1b51eSKate Stone bool IRForTarget::ResolveExternals(Function &llvm_function) {
1377a007a6d8SPavel Labath   lldb_private::Log *log(GetLog(LLDBLog::Expressions));
13784dbb271fSSean Callanan 
1379b9c1b51eSKate Stone   for (GlobalVariable &global_var : m_module->globals()) {
1380a7040525SRaphael Isemann     llvm::StringRef global_name = global_var.getName();
13814dbb271fSSean Callanan 
13824ef50a33SRaphael Isemann     LLDB_LOG(log, "Examining {0}, DeclForGlobalValue returns {1}", global_name,
13834ef50a33SRaphael Isemann              static_cast<void *>(DeclForGlobal(&global_var)));
13844dbb271fSSean Callanan 
1385a7040525SRaphael Isemann     if (global_name.startswith("OBJC_IVAR")) {
1386b9c1b51eSKate Stone       if (!HandleSymbol(&global_var)) {
1387a7040525SRaphael Isemann         m_error_stream.Format("Error [IRForTarget]: Couldn't find Objective-C "
1388a7040525SRaphael Isemann                               "indirect ivar symbol {0}\n",
1389a7040525SRaphael Isemann                               global_name);
13904dbb271fSSean Callanan 
13914dbb271fSSean Callanan         return false;
13924dbb271fSSean Callanan       }
1393a7040525SRaphael Isemann     } else if (global_name.contains("OBJC_CLASSLIST_REFERENCES_$")) {
1394b9c1b51eSKate Stone       if (!HandleObjCClass(&global_var)) {
1395b9c1b51eSKate Stone         m_error_stream.Printf("Error [IRForTarget]: Couldn't resolve the class "
1396b9c1b51eSKate Stone                               "for an Objective-C static method call\n");
13974dbb271fSSean Callanan 
13984dbb271fSSean Callanan         return false;
13994dbb271fSSean Callanan       }
1400a7040525SRaphael Isemann     } else if (global_name.contains("OBJC_CLASSLIST_SUP_REFS_$")) {
1401b9c1b51eSKate Stone       if (!HandleObjCClass(&global_var)) {
1402b9c1b51eSKate Stone         m_error_stream.Printf("Error [IRForTarget]: Couldn't resolve the class "
1403b9c1b51eSKate Stone                               "for an Objective-C static method call\n");
14044dbb271fSSean Callanan 
14054dbb271fSSean Callanan         return false;
14064dbb271fSSean Callanan       }
1407b9c1b51eSKate Stone     } else if (DeclForGlobal(&global_var)) {
1408b9c1b51eSKate Stone       if (!MaybeHandleVariable(&global_var)) {
1409a7040525SRaphael Isemann         m_error_stream.Format("Internal error [IRForTarget]: Couldn't rewrite "
1410a7040525SRaphael Isemann                               "external variable {0}\n",
1411a7040525SRaphael Isemann                               global_name);
14124dbb271fSSean Callanan 
14134dbb271fSSean Callanan         return false;
14144dbb271fSSean Callanan       }
14154dbb271fSSean Callanan     }
14164dbb271fSSean Callanan   }
14174dbb271fSSean Callanan 
14184dbb271fSSean Callanan   return true;
14194dbb271fSSean Callanan }
14204dbb271fSSean Callanan 
isGuardVariableRef(Value * V)1421b9c1b51eSKate Stone static bool isGuardVariableRef(Value *V) {
14227f7b2966SRaphael Isemann   Constant *Old = dyn_cast<Constant>(V);
14234dbb271fSSean Callanan 
14247f7b2966SRaphael Isemann   if (!Old)
14254dbb271fSSean Callanan     return false;
14264dbb271fSSean Callanan 
14277f7b2966SRaphael Isemann   if (auto CE = dyn_cast<ConstantExpr>(V)) {
14284dbb271fSSean Callanan     if (CE->getOpcode() != Instruction::BitCast)
14294dbb271fSSean Callanan       return false;
14304dbb271fSSean Callanan 
14314dbb271fSSean Callanan     Old = CE->getOperand(0);
14324dbb271fSSean Callanan   }
14334dbb271fSSean Callanan 
14344dbb271fSSean Callanan   GlobalVariable *GV = dyn_cast<GlobalVariable>(Old);
14354dbb271fSSean Callanan 
14367f7b2966SRaphael Isemann   if (!GV || !GV->hasName() || !isGuardVariableSymbol(GV->getName()))
14374dbb271fSSean Callanan     return false;
14384dbb271fSSean Callanan 
14394dbb271fSSean Callanan   return true;
14404dbb271fSSean Callanan }
14414dbb271fSSean Callanan 
TurnGuardLoadIntoZero(llvm::Instruction * guard_load)1442b9c1b51eSKate Stone void IRForTarget::TurnGuardLoadIntoZero(llvm::Instruction *guard_load) {
14434dbb271fSSean Callanan   Constant *zero(Constant::getNullValue(guard_load->getType()));
14444dbb271fSSean Callanan   guard_load->replaceAllUsesWith(zero);
14454dbb271fSSean Callanan   guard_load->eraseFromParent();
14464dbb271fSSean Callanan }
14474dbb271fSSean Callanan 
ExciseGuardStore(Instruction * guard_store)1448b9c1b51eSKate Stone static void ExciseGuardStore(Instruction *guard_store) {
14494dbb271fSSean Callanan   guard_store->eraseFromParent();
14504dbb271fSSean Callanan }
14514dbb271fSSean Callanan 
RemoveGuards(BasicBlock & basic_block)1452b9c1b51eSKate Stone bool IRForTarget::RemoveGuards(BasicBlock &basic_block) {
14534dbb271fSSean Callanan   // Eliminate any reference to guard variables found.
14544dbb271fSSean Callanan 
14554dbb271fSSean Callanan   InstrList guard_loads;
14564dbb271fSSean Callanan   InstrList guard_stores;
14574dbb271fSSean Callanan 
1458dced445bSRaphael Isemann   for (Instruction &inst : basic_block) {
14594dbb271fSSean Callanan 
14604dbb271fSSean Callanan     if (LoadInst *load = dyn_cast<LoadInst>(&inst))
14614dbb271fSSean Callanan       if (isGuardVariableRef(load->getPointerOperand()))
14624dbb271fSSean Callanan         guard_loads.push_back(&inst);
14634dbb271fSSean Callanan 
14644dbb271fSSean Callanan     if (StoreInst *store = dyn_cast<StoreInst>(&inst))
14654dbb271fSSean Callanan       if (isGuardVariableRef(store->getPointerOperand()))
14664dbb271fSSean Callanan         guard_stores.push_back(&inst);
14674dbb271fSSean Callanan   }
14684dbb271fSSean Callanan 
1469dced445bSRaphael Isemann   for (Instruction *inst : guard_loads)
1470dced445bSRaphael Isemann     TurnGuardLoadIntoZero(inst);
14714dbb271fSSean Callanan 
1472dced445bSRaphael Isemann   for (Instruction *inst : guard_stores)
1473dced445bSRaphael Isemann     ExciseGuardStore(inst);
14744dbb271fSSean Callanan 
14754dbb271fSSean Callanan   return true;
14764dbb271fSSean Callanan }
14774dbb271fSSean Callanan 
14784dbb271fSSean Callanan // This function does not report errors; its callers are responsible.
UnfoldConstant(Constant * old_constant,llvm::Function * llvm_function,FunctionValueCache & value_maker,FunctionValueCache & entry_instruction_finder,lldb_private::Stream & error_stream)1479b9c1b51eSKate Stone bool IRForTarget::UnfoldConstant(Constant *old_constant,
1480fc670cf6SSean Callanan                                  llvm::Function *llvm_function,
14814dbb271fSSean Callanan                                  FunctionValueCache &value_maker,
1482fc670cf6SSean Callanan                                  FunctionValueCache &entry_instruction_finder,
1483b9c1b51eSKate Stone                                  lldb_private::Stream &error_stream) {
14844dbb271fSSean Callanan   SmallVector<User *, 16> users;
14854dbb271fSSean Callanan 
14864dbb271fSSean Callanan   // We do this because the use list might change, invalidating our iterator.
14874dbb271fSSean Callanan   // Much better to keep a work list ourselves.
14884dbb271fSSean Callanan   for (llvm::User *u : old_constant->users())
14894dbb271fSSean Callanan     users.push_back(u);
14904dbb271fSSean Callanan 
1491b9c1b51eSKate Stone   for (size_t i = 0; i < users.size(); ++i) {
14924dbb271fSSean Callanan     User *user = users[i];
14934dbb271fSSean Callanan 
1494b9c1b51eSKate Stone     if (Constant *constant = dyn_cast<Constant>(user)) {
14954dbb271fSSean Callanan       // synthesize a new non-constant equivalent of the constant
14964dbb271fSSean Callanan 
1497b9c1b51eSKate Stone       if (ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(constant)) {
1498b9c1b51eSKate Stone         switch (constant_expr->getOpcode()) {
14994dbb271fSSean Callanan         default:
1500b9c1b51eSKate Stone           error_stream.Printf("error [IRForTarget internal]: Unhandled "
1501b9c1b51eSKate Stone                               "constant expression type: \"%s\"",
1502b9c1b51eSKate Stone                               PrintValue(constant_expr).c_str());
15034dbb271fSSean Callanan           return false;
1504b9c1b51eSKate Stone         case Instruction::BitCast: {
1505b9c1b51eSKate Stone           FunctionValueCache bit_cast_maker(
1506b9c1b51eSKate Stone               [&value_maker, &entry_instruction_finder, old_constant,
1507b9c1b51eSKate Stone                constant_expr](llvm::Function *function) -> llvm::Value * {
15084dbb271fSSean Callanan                 // UnaryExpr
15094dbb271fSSean Callanan                 //   OperandList[0] is value
15104dbb271fSSean Callanan 
15114dbb271fSSean Callanan                 if (constant_expr->getOperand(0) != old_constant)
15124dbb271fSSean Callanan                   return constant_expr;
15134dbb271fSSean Callanan 
1514b9c1b51eSKate Stone                 return new BitCastInst(
1515b9c1b51eSKate Stone                     value_maker.GetValue(function), constant_expr->getType(),
1516b9c1b51eSKate Stone                     "", llvm::cast<Instruction>(
1517b9c1b51eSKate Stone                             entry_instruction_finder.GetValue(function)));
15184dbb271fSSean Callanan               });
15194dbb271fSSean Callanan 
1520b9c1b51eSKate Stone           if (!UnfoldConstant(constant_expr, llvm_function, bit_cast_maker,
1521b9c1b51eSKate Stone                               entry_instruction_finder, error_stream))
15224dbb271fSSean Callanan             return false;
1523b9c1b51eSKate Stone         } break;
1524b9c1b51eSKate Stone         case Instruction::GetElementPtr: {
15254dbb271fSSean Callanan           // GetElementPtrConstantExpr
15264dbb271fSSean Callanan           //   OperandList[0] is base
15274dbb271fSSean Callanan           //   OperandList[1]... are indices
15284dbb271fSSean Callanan 
1529b9c1b51eSKate Stone           FunctionValueCache get_element_pointer_maker(
1530b9c1b51eSKate Stone               [&value_maker, &entry_instruction_finder, old_constant,
1531b9c1b51eSKate Stone                constant_expr](llvm::Function *function) -> llvm::Value * {
1532c476566bSNikita Popov                 auto *gep = cast<llvm::GEPOperator>(constant_expr);
1533c476566bSNikita Popov                 Value *ptr = gep->getPointerOperand();
15344dbb271fSSean Callanan 
15354dbb271fSSean Callanan                 if (ptr == old_constant)
15364dbb271fSSean Callanan                   ptr = value_maker.GetValue(function);
15374dbb271fSSean Callanan 
15384dbb271fSSean Callanan                 std::vector<Value *> index_vector;
15392e3f4694SNikita Popov                 for (Value *operand : gep->indices()) {
15404dbb271fSSean Callanan                   if (operand == old_constant)
15414dbb271fSSean Callanan                     operand = value_maker.GetValue(function);
15424dbb271fSSean Callanan 
15434dbb271fSSean Callanan                   index_vector.push_back(operand);
15444dbb271fSSean Callanan                 }
15454dbb271fSSean Callanan 
15464dbb271fSSean Callanan                 ArrayRef<Value *> indices(index_vector);
15474dbb271fSSean Callanan 
1548b9c1b51eSKate Stone                 return GetElementPtrInst::Create(
1549c476566bSNikita Popov                     gep->getSourceElementType(), ptr, indices, "",
1550b9c1b51eSKate Stone                     llvm::cast<Instruction>(
1551b9c1b51eSKate Stone                         entry_instruction_finder.GetValue(function)));
15524dbb271fSSean Callanan               });
15534dbb271fSSean Callanan 
1554b9c1b51eSKate Stone           if (!UnfoldConstant(constant_expr, llvm_function,
1555b9c1b51eSKate Stone                               get_element_pointer_maker,
1556b9c1b51eSKate Stone                               entry_instruction_finder, error_stream))
1557b9c1b51eSKate Stone             return false;
1558b9c1b51eSKate Stone         } break;
1559b9c1b51eSKate Stone         }
1560b9c1b51eSKate Stone       } else {
1561b9c1b51eSKate Stone         error_stream.Printf(
1562b9c1b51eSKate Stone             "error [IRForTarget internal]: Unhandled constant type: \"%s\"",
1563b9c1b51eSKate Stone             PrintValue(constant).c_str());
15644dbb271fSSean Callanan         return false;
15654dbb271fSSean Callanan       }
1566b9c1b51eSKate Stone     } else {
1567b9c1b51eSKate Stone       if (Instruction *inst = llvm::dyn_cast<Instruction>(user)) {
1568b9c1b51eSKate Stone         if (llvm_function && inst->getParent()->getParent() != llvm_function) {
1569b9c1b51eSKate Stone           error_stream.PutCString("error: Capturing non-local variables in "
1570b9c1b51eSKate Stone                                   "expressions is unsupported.\n");
15714dbb271fSSean Callanan           return false;
15724dbb271fSSean Callanan         }
1573b9c1b51eSKate Stone         inst->replaceUsesOfWith(
1574b9c1b51eSKate Stone             old_constant, value_maker.GetValue(inst->getParent()->getParent()));
1575b9c1b51eSKate Stone       } else {
1576b9c1b51eSKate Stone         error_stream.Printf(
1577b9c1b51eSKate Stone             "error [IRForTarget internal]: Unhandled non-constant type: \"%s\"",
1578b9c1b51eSKate Stone             PrintValue(user).c_str());
15794dbb271fSSean Callanan         return false;
15804dbb271fSSean Callanan       }
15814dbb271fSSean Callanan     }
15824dbb271fSSean Callanan   }
15834dbb271fSSean Callanan 
1584b9c1b51eSKate Stone   if (!isa<GlobalValue>(old_constant)) {
15854dbb271fSSean Callanan     old_constant->destroyConstant();
15864dbb271fSSean Callanan   }
15874dbb271fSSean Callanan 
15884dbb271fSSean Callanan   return true;
15894dbb271fSSean Callanan }
15904dbb271fSSean Callanan 
ReplaceVariables(Function & llvm_function)1591b9c1b51eSKate Stone bool IRForTarget::ReplaceVariables(Function &llvm_function) {
15924dbb271fSSean Callanan   if (!m_resolve_vars)
15934dbb271fSSean Callanan     return true;
15944dbb271fSSean Callanan 
1595a007a6d8SPavel Labath   lldb_private::Log *log(GetLog(LLDBLog::Expressions));
15964dbb271fSSean Callanan 
15974dbb271fSSean Callanan   m_decl_map->DoStructLayout();
15984dbb271fSSean Callanan 
15994ef50a33SRaphael Isemann   LLDB_LOG(log, "Element arrangement:");
16004dbb271fSSean Callanan 
16014dbb271fSSean Callanan   uint32_t num_elements;
16024dbb271fSSean Callanan   uint32_t element_index;
16034dbb271fSSean Callanan 
16044dbb271fSSean Callanan   size_t size;
16054dbb271fSSean Callanan   lldb::offset_t alignment;
16064dbb271fSSean Callanan 
16074dbb271fSSean Callanan   if (!m_decl_map->GetStructInfo(num_elements, size, alignment))
16084dbb271fSSean Callanan     return false;
16094dbb271fSSean Callanan 
161020670ba5SReid Kleckner   Function::arg_iterator iter(llvm_function.arg_begin());
16114dbb271fSSean Callanan 
161220670ba5SReid Kleckner   if (iter == llvm_function.arg_end()) {
1613b9c1b51eSKate Stone     m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes no "
1614b9c1b51eSKate Stone                           "arguments (should take at least a struct pointer)");
16154dbb271fSSean Callanan 
16164dbb271fSSean Callanan     return false;
16174dbb271fSSean Callanan   }
16184dbb271fSSean Callanan 
161933e43ca6SDuncan P. N. Exon Smith   Argument *argument = &*iter;
16204dbb271fSSean Callanan 
1621b9c1b51eSKate Stone   if (argument->getName().equals("this")) {
16224dbb271fSSean Callanan     ++iter;
16234dbb271fSSean Callanan 
162420670ba5SReid Kleckner     if (iter == llvm_function.arg_end()) {
1625b9c1b51eSKate Stone       m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes only "
1626b9c1b51eSKate Stone                             "'this' argument (should take a struct pointer "
1627b9c1b51eSKate Stone                             "too)");
16284dbb271fSSean Callanan 
16294dbb271fSSean Callanan       return false;
16304dbb271fSSean Callanan     }
16314dbb271fSSean Callanan 
163233e43ca6SDuncan P. N. Exon Smith     argument = &*iter;
1633b9c1b51eSKate Stone   } else if (argument->getName().equals("self")) {
16344dbb271fSSean Callanan     ++iter;
16354dbb271fSSean Callanan 
163620670ba5SReid Kleckner     if (iter == llvm_function.arg_end()) {
1637b9c1b51eSKate Stone       m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes only "
1638b9c1b51eSKate Stone                             "'self' argument (should take '_cmd' and a struct "
1639b9c1b51eSKate Stone                             "pointer too)");
16404dbb271fSSean Callanan 
16414dbb271fSSean Callanan       return false;
16424dbb271fSSean Callanan     }
16434dbb271fSSean Callanan 
1644b9c1b51eSKate Stone     if (!iter->getName().equals("_cmd")) {
1645a7040525SRaphael Isemann       m_error_stream.Format("Internal error [IRForTarget]: Wrapper takes '{0}' "
1646b9c1b51eSKate Stone                             "after 'self' argument (should take '_cmd')",
1647a7040525SRaphael Isemann                             iter->getName());
16484dbb271fSSean Callanan 
16494dbb271fSSean Callanan       return false;
16504dbb271fSSean Callanan     }
16514dbb271fSSean Callanan 
16524dbb271fSSean Callanan     ++iter;
16534dbb271fSSean Callanan 
165420670ba5SReid Kleckner     if (iter == llvm_function.arg_end()) {
1655b9c1b51eSKate Stone       m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes only "
1656b9c1b51eSKate Stone                             "'self' and '_cmd' arguments (should take a struct "
1657b9c1b51eSKate Stone                             "pointer too)");
16584dbb271fSSean Callanan 
16594dbb271fSSean Callanan       return false;
16604dbb271fSSean Callanan     }
16614dbb271fSSean Callanan 
166233e43ca6SDuncan P. N. Exon Smith     argument = &*iter;
16634dbb271fSSean Callanan   }
16644dbb271fSSean Callanan 
1665b9c1b51eSKate Stone   if (!argument->getName().equals("$__lldb_arg")) {
1666a7040525SRaphael Isemann     m_error_stream.Format("Internal error [IRForTarget]: Wrapper takes an "
1667a7040525SRaphael Isemann                           "argument named '{0}' instead of the struct pointer",
1668a7040525SRaphael Isemann                           argument->getName());
16694dbb271fSSean Callanan 
16704dbb271fSSean Callanan     return false;
16714dbb271fSSean Callanan   }
16724dbb271fSSean Callanan 
1673a7040525SRaphael Isemann   LLDB_LOG(log, "Arg: \"{0}\"", PrintValue(argument));
16744dbb271fSSean Callanan 
16754dbb271fSSean Callanan   BasicBlock &entry_block(llvm_function.getEntryBlock());
16764dbb271fSSean Callanan   Instruction *FirstEntryInstruction(entry_block.getFirstNonPHIOrDbg());
16774dbb271fSSean Callanan 
1678b9c1b51eSKate Stone   if (!FirstEntryInstruction) {
1679b9c1b51eSKate Stone     m_error_stream.Printf("Internal error [IRForTarget]: Couldn't find the "
1680b9c1b51eSKate Stone                           "first instruction in the wrapper for use in "
1681b9c1b51eSKate Stone                           "rewriting");
16824dbb271fSSean Callanan 
16834dbb271fSSean Callanan     return false;
16844dbb271fSSean Callanan   }
16854dbb271fSSean Callanan 
16864dbb271fSSean Callanan   LLVMContext &context(m_module->getContext());
16874dbb271fSSean Callanan   IntegerType *offset_type(Type::getInt32Ty(context));
16884dbb271fSSean Callanan 
1689b9c1b51eSKate Stone   if (!offset_type) {
1690b9c1b51eSKate Stone     m_error_stream.Printf(
1691b9c1b51eSKate Stone         "Internal error [IRForTarget]: Couldn't produce an offset type");
16924dbb271fSSean Callanan 
16934dbb271fSSean Callanan     return false;
16944dbb271fSSean Callanan   }
16954dbb271fSSean Callanan 
1696b9c1b51eSKate Stone   for (element_index = 0; element_index < num_elements; ++element_index) {
1697248a1305SKonrad Kleine     const clang::NamedDecl *decl = nullptr;
1698248a1305SKonrad Kleine     Value *value = nullptr;
16994dbb271fSSean Callanan     lldb::offset_t offset;
17004dbb271fSSean Callanan     lldb_private::ConstString name;
17014dbb271fSSean Callanan 
1702b9c1b51eSKate Stone     if (!m_decl_map->GetStructElement(decl, value, offset, name,
1703b9c1b51eSKate Stone                                       element_index)) {
1704b9c1b51eSKate Stone       m_error_stream.Printf(
1705b9c1b51eSKate Stone           "Internal error [IRForTarget]: Structure information is incomplete");
17064dbb271fSSean Callanan 
17074dbb271fSSean Callanan       return false;
17084dbb271fSSean Callanan     }
17094dbb271fSSean Callanan 
17104ef50a33SRaphael Isemann     LLDB_LOG(log, "  \"{0}\" (\"{1}\") placed at {2}", name,
1711a7040525SRaphael Isemann              decl->getNameAsString(), offset);
17124dbb271fSSean Callanan 
1713b9c1b51eSKate Stone     if (value) {
1714a7040525SRaphael Isemann       LLDB_LOG(log, "    Replacing [{0}]", PrintValue(value));
17154dbb271fSSean Callanan 
1716b9c1b51eSKate Stone       FunctionValueCache body_result_maker(
1717b9c1b51eSKate Stone           [this, name, offset_type, offset, argument,
1718b9c1b51eSKate Stone            value](llvm::Function *function) -> llvm::Value * {
171905097246SAdrian Prantl             // Per the comment at ASTResultSynthesizer::SynthesizeBodyResult,
172005097246SAdrian Prantl             // in cases where the result variable is an rvalue, we have to
172105097246SAdrian Prantl             // synthesize a dereference of the appropriate structure entry in
172205097246SAdrian Prantl             // order to produce the static variable that the AST thinks it is
172305097246SAdrian Prantl             // accessing.
17244dbb271fSSean Callanan 
1725b9c1b51eSKate Stone             llvm::Instruction *entry_instruction = llvm::cast<Instruction>(
1726b9c1b51eSKate Stone                 m_entry_instruction_finder.GetValue(function));
17274dbb271fSSean Callanan 
1728840bb725SNikita Popov             Type *int8Ty = Type::getInt8Ty(function->getContext());
1729b9c1b51eSKate Stone             ConstantInt *offset_int(
1730b9c1b51eSKate Stone                 ConstantInt::get(offset_type, offset, true));
1731b9c1b51eSKate Stone             GetElementPtrInst *get_element_ptr = GetElementPtrInst::Create(
1732840bb725SNikita Popov                 int8Ty, argument, offset_int, "", entry_instruction);
17334dbb271fSSean Callanan 
1734b9c1b51eSKate Stone             if (name == m_result_name && !m_result_is_pointer) {
1735b9c1b51eSKate Stone               BitCastInst *bit_cast = new BitCastInst(
1736b9c1b51eSKate Stone                   get_element_ptr, value->getType()->getPointerTo(), "",
17374dbb271fSSean Callanan                   entry_instruction);
17384dbb271fSSean Callanan 
1739840bb725SNikita Popov               LoadInst *load = new LoadInst(value->getType(), bit_cast, "",
1740840bb725SNikita Popov                                             entry_instruction);
17414dbb271fSSean Callanan 
17424dbb271fSSean Callanan               return load;
1743b9c1b51eSKate Stone             } else {
1744b9c1b51eSKate Stone               BitCastInst *bit_cast = new BitCastInst(
1745b9c1b51eSKate Stone                   get_element_ptr, value->getType(), "", entry_instruction);
17464dbb271fSSean Callanan 
17474dbb271fSSean Callanan               return bit_cast;
17484dbb271fSSean Callanan             }
17494dbb271fSSean Callanan           });
17504dbb271fSSean Callanan 
1751b9c1b51eSKate Stone       if (Constant *constant = dyn_cast<Constant>(value)) {
1752b9c1b51eSKate Stone         if (!UnfoldConstant(constant, &llvm_function, body_result_maker,
1753b9c1b51eSKate Stone                             m_entry_instruction_finder, m_error_stream)) {
1754fc670cf6SSean Callanan           return false;
1755fc670cf6SSean Callanan         }
1756b9c1b51eSKate Stone       } else if (Instruction *instruction = dyn_cast<Instruction>(value)) {
1757b9c1b51eSKate Stone         if (instruction->getParent()->getParent() != &llvm_function) {
1758b9c1b51eSKate Stone           m_error_stream.PutCString("error: Capturing non-local variables in "
1759b9c1b51eSKate Stone                                     "expressions is unsupported.\n");
1760fc670cf6SSean Callanan           return false;
1761fc670cf6SSean Callanan         }
1762b9c1b51eSKate Stone         value->replaceAllUsesWith(
1763b9c1b51eSKate Stone             body_result_maker.GetValue(instruction->getParent()->getParent()));
1764b9c1b51eSKate Stone       } else {
1765a7040525SRaphael Isemann         LLDB_LOG(log, "Unhandled non-constant type: \"{0}\"",
1766a7040525SRaphael Isemann                  PrintValue(value));
17674dbb271fSSean Callanan         return false;
17684dbb271fSSean Callanan       }
17694dbb271fSSean Callanan 
17704dbb271fSSean Callanan       if (GlobalVariable *var = dyn_cast<GlobalVariable>(value))
17714dbb271fSSean Callanan         var->eraseFromParent();
17724dbb271fSSean Callanan     }
17734dbb271fSSean Callanan   }
17744dbb271fSSean Callanan 
1775a7040525SRaphael Isemann   LLDB_LOG(log, "Total structure [align {0}, size {1}]", (int64_t)alignment,
1776a7040525SRaphael Isemann            (uint64_t)size);
17774dbb271fSSean Callanan 
17784dbb271fSSean Callanan   return true;
17794dbb271fSSean Callanan }
17804dbb271fSSean Callanan 
runOnModule(Module & llvm_module)1781b9c1b51eSKate Stone bool IRForTarget::runOnModule(Module &llvm_module) {
1782a007a6d8SPavel Labath   lldb_private::Log *log(GetLog(LLDBLog::Expressions));
17834dbb271fSSean Callanan 
17844dbb271fSSean Callanan   m_module = &llvm_module;
178506412daeSJonas Devlieghere   m_target_data = std::make_unique<DataLayout>(m_module);
1786b9c1b51eSKate Stone   m_intptr_ty = llvm::Type::getIntNTy(m_module->getContext(),
1787b9c1b51eSKate Stone                                       m_target_data->getPointerSizeInBits());
17884dbb271fSSean Callanan 
1789b9c1b51eSKate Stone   if (log) {
17904dbb271fSSean Callanan     std::string s;
17914dbb271fSSean Callanan     raw_string_ostream oss(s);
17924dbb271fSSean Callanan 
1793248a1305SKonrad Kleine     m_module->print(oss, nullptr);
17944dbb271fSSean Callanan 
17954dbb271fSSean Callanan     oss.flush();
17964dbb271fSSean Callanan 
1797a7040525SRaphael Isemann     LLDB_LOG(log, "Module as passed in to IRForTarget: \n\"{0}\"", s);
17984dbb271fSSean Callanan   }
17994dbb271fSSean Callanan 
1800b9c1b51eSKate Stone   Function *const main_function =
1801b9c1b51eSKate Stone       m_func_name.IsEmpty() ? nullptr
1802b9c1b51eSKate Stone                             : m_module->getFunction(m_func_name.GetStringRef());
18034dbb271fSSean Callanan 
1804b9c1b51eSKate Stone   if (!m_func_name.IsEmpty() && !main_function) {
1805a7040525SRaphael Isemann     LLDB_LOG(log, "Couldn't find \"{0}()\" in the module", m_func_name);
18064dbb271fSSean Callanan 
1807a7040525SRaphael Isemann     m_error_stream.Format("Internal error [IRForTarget]: Couldn't find wrapper "
1808a7040525SRaphael Isemann                           "'{0}' in the module",
1809a7040525SRaphael Isemann                           m_func_name);
18104dbb271fSSean Callanan 
18114dbb271fSSean Callanan     return false;
18124dbb271fSSean Callanan   }
18134dbb271fSSean Callanan 
1814b9c1b51eSKate Stone   if (main_function) {
1815b9c1b51eSKate Stone     if (!FixFunctionLinkage(*main_function)) {
18164ef50a33SRaphael Isemann       LLDB_LOG(log, "Couldn't fix the linkage for the function");
18174dbb271fSSean Callanan 
18184dbb271fSSean Callanan       return false;
18194dbb271fSSean Callanan     }
182000294b34SSean Callanan   }
18214dbb271fSSean Callanan 
18224dbb271fSSean Callanan   llvm::Type *int8_ty = Type::getInt8Ty(m_module->getContext());
18234dbb271fSSean Callanan 
1824b9c1b51eSKate Stone   m_reloc_placeholder = new llvm::GlobalVariable(
1825b9c1b51eSKate Stone       (*m_module), int8_ty, false /* IsConstant */,
1826b9c1b51eSKate Stone       GlobalVariable::InternalLinkage, Constant::getNullValue(int8_ty),
1827248a1305SKonrad Kleine       "reloc_placeholder", nullptr /* InsertBefore */,
1828b9c1b51eSKate Stone       GlobalVariable::NotThreadLocal /* ThreadLocal */, 0 /* AddressSpace */);
18294dbb271fSSean Callanan 
18304dbb271fSSean Callanan   ////////////////////////////////////////////////////////////
18314dbb271fSSean Callanan   // Replace $__lldb_expr_result with a persistent variable
18324dbb271fSSean Callanan   //
18334dbb271fSSean Callanan 
1834b9c1b51eSKate Stone   if (main_function) {
1835b9c1b51eSKate Stone     if (!CreateResultVariable(*main_function)) {
18364ef50a33SRaphael Isemann       LLDB_LOG(log, "CreateResultVariable() failed");
18374dbb271fSSean Callanan 
18384dbb271fSSean Callanan       // CreateResultVariable() reports its own errors, so we don't do so here
18394dbb271fSSean Callanan 
18404dbb271fSSean Callanan       return false;
18414dbb271fSSean Callanan     }
184200294b34SSean Callanan   }
18434dbb271fSSean Callanan 
1844b9c1b51eSKate Stone   if (log && log->GetVerbose()) {
18454dbb271fSSean Callanan     std::string s;
18464dbb271fSSean Callanan     raw_string_ostream oss(s);
18474dbb271fSSean Callanan 
1848248a1305SKonrad Kleine     m_module->print(oss, nullptr);
18494dbb271fSSean Callanan 
18504dbb271fSSean Callanan     oss.flush();
18514dbb271fSSean Callanan 
1852a7040525SRaphael Isemann     LLDB_LOG(log, "Module after creating the result variable: \n\"{0}\"", s);
18534dbb271fSSean Callanan   }
18544dbb271fSSean Callanan 
1855dced445bSRaphael Isemann   for (llvm::Function &function : *m_module) {
1856dced445bSRaphael Isemann     for (BasicBlock &bb : function) {
1857dced445bSRaphael Isemann       if (!RemoveGuards(bb)) {
18584ef50a33SRaphael Isemann         LLDB_LOG(log, "RemoveGuards() failed");
18594dbb271fSSean Callanan 
18604dbb271fSSean Callanan         // RemoveGuards() reports its own errors, so we don't do so here
18614dbb271fSSean Callanan 
18624dbb271fSSean Callanan         return false;
18634dbb271fSSean Callanan       }
18644dbb271fSSean Callanan 
1865dced445bSRaphael Isemann       if (!RewritePersistentAllocs(bb)) {
18664ef50a33SRaphael Isemann         LLDB_LOG(log, "RewritePersistentAllocs() failed");
18674dbb271fSSean Callanan 
1868b9c1b51eSKate Stone         // RewritePersistentAllocs() reports its own errors, so we don't do so
1869b9c1b51eSKate Stone         // here
18704dbb271fSSean Callanan 
18714dbb271fSSean Callanan         return false;
18724dbb271fSSean Callanan       }
18734dbb271fSSean Callanan 
1874dced445bSRaphael Isemann       if (!RemoveCXAAtExit(bb)) {
18754ef50a33SRaphael Isemann         LLDB_LOG(log, "RemoveCXAAtExit() failed");
18764dbb271fSSean Callanan 
18774dbb271fSSean Callanan         // RemoveCXAAtExit() reports its own errors, so we don't do so here
18784dbb271fSSean Callanan 
18794dbb271fSSean Callanan         return false;
18804dbb271fSSean Callanan       }
18814dbb271fSSean Callanan     }
18824dbb271fSSean Callanan   }
18834dbb271fSSean Callanan 
18844dbb271fSSean Callanan   ///////////////////////////////////////////////////////////////////////////////
18854dbb271fSSean Callanan   // Fix all Objective-C constant strings to use NSStringWithCString:encoding:
18864dbb271fSSean Callanan   //
18874dbb271fSSean Callanan 
1888b9c1b51eSKate Stone   if (!RewriteObjCConstStrings()) {
18894ef50a33SRaphael Isemann     LLDB_LOG(log, "RewriteObjCConstStrings() failed");
18904dbb271fSSean Callanan 
18914dbb271fSSean Callanan     // RewriteObjCConstStrings() reports its own errors, so we don't do so here
18924dbb271fSSean Callanan 
18934dbb271fSSean Callanan     return false;
18944dbb271fSSean Callanan   }
18954dbb271fSSean Callanan 
1896dced445bSRaphael Isemann   for (llvm::Function &function : *m_module) {
1897dced445bSRaphael Isemann     for (llvm::BasicBlock &bb : function) {
1898dced445bSRaphael Isemann       if (!RewriteObjCSelectors(bb)) {
18994ef50a33SRaphael Isemann         LLDB_LOG(log, "RewriteObjCSelectors() failed");
19004dbb271fSSean Callanan 
190105097246SAdrian Prantl         // RewriteObjCSelectors() reports its own errors, so we don't do so
190205097246SAdrian Prantl         // here
19034dbb271fSSean Callanan 
19044dbb271fSSean Callanan         return false;
19054dbb271fSSean Callanan       }
1906ac90058bSSean Callanan 
1907dced445bSRaphael Isemann       if (!RewriteObjCClassReferences(bb)) {
19084ef50a33SRaphael Isemann         LLDB_LOG(log, "RewriteObjCClassReferences() failed");
1909ac90058bSSean Callanan 
1910ac90058bSSean Callanan         // RewriteObjCClasses() reports its own errors, so we don't do so here
1911ac90058bSSean Callanan 
1912ac90058bSSean Callanan         return false;
1913ac90058bSSean Callanan       }
19144dbb271fSSean Callanan     }
19154dbb271fSSean Callanan   }
19164dbb271fSSean Callanan 
1917dced445bSRaphael Isemann   for (llvm::Function &function : *m_module) {
1918dced445bSRaphael Isemann     for (BasicBlock &bb : function) {
1919dced445bSRaphael Isemann       if (!ResolveCalls(bb)) {
19204ef50a33SRaphael Isemann         LLDB_LOG(log, "ResolveCalls() failed");
19214dbb271fSSean Callanan 
19224dbb271fSSean Callanan         // ResolveCalls() reports its own errors, so we don't do so here
19234dbb271fSSean Callanan 
19244dbb271fSSean Callanan         return false;
19254dbb271fSSean Callanan       }
19264dbb271fSSean Callanan     }
19274dbb271fSSean Callanan   }
19284dbb271fSSean Callanan 
19294dbb271fSSean Callanan   ////////////////////////////////////////////////////////////////////////
19304dbb271fSSean Callanan   // Run function-level passes that only make sense on the main function
19314dbb271fSSean Callanan   //
19324dbb271fSSean Callanan 
1933b9c1b51eSKate Stone   if (main_function) {
1934b9c1b51eSKate Stone     if (!ResolveExternals(*main_function)) {
19354ef50a33SRaphael Isemann       LLDB_LOG(log, "ResolveExternals() failed");
19364dbb271fSSean Callanan 
19374dbb271fSSean Callanan       // ResolveExternals() reports its own errors, so we don't do so here
19384dbb271fSSean Callanan 
19394dbb271fSSean Callanan       return false;
19404dbb271fSSean Callanan     }
19414dbb271fSSean Callanan 
1942b9c1b51eSKate Stone     if (!ReplaceVariables(*main_function)) {
19434ef50a33SRaphael Isemann       LLDB_LOG(log, "ReplaceVariables() failed");
19444dbb271fSSean Callanan 
19454dbb271fSSean Callanan       // ReplaceVariables() reports its own errors, so we don't do so here
19464dbb271fSSean Callanan 
19474dbb271fSSean Callanan       return false;
19484dbb271fSSean Callanan     }
194900294b34SSean Callanan   }
19504dbb271fSSean Callanan 
1951b9c1b51eSKate Stone   if (log && log->GetVerbose()) {
19524dbb271fSSean Callanan     std::string s;
19534dbb271fSSean Callanan     raw_string_ostream oss(s);
19544dbb271fSSean Callanan 
1955248a1305SKonrad Kleine     m_module->print(oss, nullptr);
19564dbb271fSSean Callanan 
19574dbb271fSSean Callanan     oss.flush();
19584dbb271fSSean Callanan 
1959a7040525SRaphael Isemann     LLDB_LOG(log, "Module after preparing for execution: \n\"{0}\"", s);
19604dbb271fSSean Callanan   }
19614dbb271fSSean Callanan 
19624dbb271fSSean Callanan   return true;
19634dbb271fSSean Callanan }
1964