xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1dda28197Spatrick //===-- IRForTarget.cpp ---------------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include "IRForTarget.h"
10061da546Spatrick 
11061da546Spatrick #include "ClangExpressionDeclMap.h"
12dda28197Spatrick #include "ClangUtil.h"
13061da546Spatrick 
14dda28197Spatrick #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
15061da546Spatrick #include "llvm/IR/Constants.h"
16061da546Spatrick #include "llvm/IR/DataLayout.h"
17be691f3bSpatrick #include "llvm/IR/Operator.h"
18061da546Spatrick #include "llvm/IR/InstrTypes.h"
19061da546Spatrick #include "llvm/IR/Instructions.h"
20061da546Spatrick #include "llvm/IR/Intrinsics.h"
21061da546Spatrick #include "llvm/IR/LegacyPassManager.h"
22061da546Spatrick #include "llvm/IR/Metadata.h"
23061da546Spatrick #include "llvm/IR/Module.h"
24061da546Spatrick #include "llvm/IR/ValueSymbolTable.h"
25061da546Spatrick #include "llvm/Support/raw_ostream.h"
26061da546Spatrick #include "llvm/Transforms/IPO.h"
27061da546Spatrick 
28061da546Spatrick #include "clang/AST/ASTContext.h"
29061da546Spatrick 
30061da546Spatrick #include "lldb/Core/dwarf.h"
31061da546Spatrick #include "lldb/Expression/IRExecutionUnit.h"
32061da546Spatrick #include "lldb/Expression/IRInterpreter.h"
33061da546Spatrick #include "lldb/Symbol/CompilerType.h"
34061da546Spatrick #include "lldb/Utility/ConstString.h"
35061da546Spatrick #include "lldb/Utility/DataBufferHeap.h"
36061da546Spatrick #include "lldb/Utility/Endian.h"
37*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
38061da546Spatrick #include "lldb/Utility/Log.h"
39061da546Spatrick #include "lldb/Utility/Scalar.h"
40061da546Spatrick #include "lldb/Utility/StreamString.h"
41061da546Spatrick 
42061da546Spatrick #include <map>
43*f6aab3d8Srobert #include <optional>
44061da546Spatrick 
45061da546Spatrick using namespace llvm;
46*f6aab3d8Srobert using lldb_private::LLDBLog;
47061da546Spatrick 
48061da546Spatrick typedef SmallVector<Instruction *, 2> InstrList;
49061da546Spatrick 
FunctionValueCache(Maker const & maker)50061da546Spatrick IRForTarget::FunctionValueCache::FunctionValueCache(Maker const &maker)
51061da546Spatrick     : m_maker(maker), m_values() {}
52061da546Spatrick 
53be691f3bSpatrick IRForTarget::FunctionValueCache::~FunctionValueCache() = default;
54061da546Spatrick 
55061da546Spatrick llvm::Value *
GetValue(llvm::Function * function)56061da546Spatrick IRForTarget::FunctionValueCache::GetValue(llvm::Function *function) {
57061da546Spatrick   if (!m_values.count(function)) {
58061da546Spatrick     llvm::Value *ret = m_maker(function);
59061da546Spatrick     m_values[function] = ret;
60061da546Spatrick     return ret;
61061da546Spatrick   }
62061da546Spatrick   return m_values[function];
63061da546Spatrick }
64061da546Spatrick 
FindEntryInstruction(llvm::Function * function)65061da546Spatrick static llvm::Value *FindEntryInstruction(llvm::Function *function) {
66061da546Spatrick   if (function->empty())
67061da546Spatrick     return nullptr;
68061da546Spatrick 
69061da546Spatrick   return function->getEntryBlock().getFirstNonPHIOrDbg();
70061da546Spatrick }
71061da546Spatrick 
IRForTarget(lldb_private::ClangExpressionDeclMap * decl_map,bool resolve_vars,lldb_private::IRExecutionUnit & execution_unit,lldb_private::Stream & error_stream,const char * func_name)72061da546Spatrick IRForTarget::IRForTarget(lldb_private::ClangExpressionDeclMap *decl_map,
73061da546Spatrick                          bool resolve_vars,
74061da546Spatrick                          lldb_private::IRExecutionUnit &execution_unit,
75061da546Spatrick                          lldb_private::Stream &error_stream,
76061da546Spatrick                          const char *func_name)
77be691f3bSpatrick     : m_resolve_vars(resolve_vars), m_func_name(func_name),
78be691f3bSpatrick       m_decl_map(decl_map), m_error_stream(error_stream),
79be691f3bSpatrick       m_execution_unit(execution_unit),
80061da546Spatrick       m_entry_instruction_finder(FindEntryInstruction) {}
81061da546Spatrick 
82061da546Spatrick /* Handy utility functions used at several places in the code */
83061da546Spatrick 
PrintValue(const Value * value,bool truncate=false)84061da546Spatrick static std::string PrintValue(const Value *value, bool truncate = false) {
85061da546Spatrick   std::string s;
86061da546Spatrick   if (value) {
87061da546Spatrick     raw_string_ostream rso(s);
88061da546Spatrick     value->print(rso);
89061da546Spatrick     rso.flush();
90061da546Spatrick     if (truncate)
91061da546Spatrick       s.resize(s.length() - 1);
92061da546Spatrick   }
93061da546Spatrick   return s;
94061da546Spatrick }
95061da546Spatrick 
PrintType(const llvm::Type * type,bool truncate=false)96061da546Spatrick static std::string PrintType(const llvm::Type *type, bool truncate = false) {
97061da546Spatrick   std::string s;
98061da546Spatrick   raw_string_ostream rso(s);
99061da546Spatrick   type->print(rso);
100061da546Spatrick   rso.flush();
101061da546Spatrick   if (truncate)
102061da546Spatrick     s.resize(s.length() - 1);
103061da546Spatrick   return s;
104061da546Spatrick }
105061da546Spatrick 
FixFunctionLinkage(llvm::Function & llvm_function)106061da546Spatrick bool IRForTarget::FixFunctionLinkage(llvm::Function &llvm_function) {
107061da546Spatrick   llvm_function.setLinkage(GlobalValue::ExternalLinkage);
108061da546Spatrick 
109061da546Spatrick   return true;
110061da546Spatrick }
111061da546Spatrick 
DeclForGlobal(const GlobalValue * global_val,Module * module)112061da546Spatrick clang::NamedDecl *IRForTarget::DeclForGlobal(const GlobalValue *global_val,
113061da546Spatrick                                              Module *module) {
114061da546Spatrick   NamedMDNode *named_metadata =
115061da546Spatrick       module->getNamedMetadata("clang.global.decl.ptrs");
116061da546Spatrick 
117061da546Spatrick   if (!named_metadata)
118061da546Spatrick     return nullptr;
119061da546Spatrick 
120061da546Spatrick   unsigned num_nodes = named_metadata->getNumOperands();
121061da546Spatrick   unsigned node_index;
122061da546Spatrick 
123061da546Spatrick   for (node_index = 0; node_index < num_nodes; ++node_index) {
124061da546Spatrick     llvm::MDNode *metadata_node =
125061da546Spatrick         dyn_cast<llvm::MDNode>(named_metadata->getOperand(node_index));
126061da546Spatrick     if (!metadata_node)
127061da546Spatrick       return nullptr;
128061da546Spatrick 
129061da546Spatrick     if (metadata_node->getNumOperands() != 2)
130061da546Spatrick       continue;
131061da546Spatrick 
132061da546Spatrick     if (mdconst::dyn_extract_or_null<GlobalValue>(
133061da546Spatrick             metadata_node->getOperand(0)) != global_val)
134061da546Spatrick       continue;
135061da546Spatrick 
136061da546Spatrick     ConstantInt *constant_int =
137061da546Spatrick         mdconst::dyn_extract<ConstantInt>(metadata_node->getOperand(1));
138061da546Spatrick 
139061da546Spatrick     if (!constant_int)
140061da546Spatrick       return nullptr;
141061da546Spatrick 
142061da546Spatrick     uintptr_t ptr = constant_int->getZExtValue();
143061da546Spatrick 
144061da546Spatrick     return reinterpret_cast<clang::NamedDecl *>(ptr);
145061da546Spatrick   }
146061da546Spatrick 
147061da546Spatrick   return nullptr;
148061da546Spatrick }
149061da546Spatrick 
DeclForGlobal(GlobalValue * global_val)150061da546Spatrick clang::NamedDecl *IRForTarget::DeclForGlobal(GlobalValue *global_val) {
151061da546Spatrick   return DeclForGlobal(global_val, m_module);
152061da546Spatrick }
153061da546Spatrick 
154061da546Spatrick /// Returns true iff the mangled symbol is for a static guard variable.
isGuardVariableSymbol(llvm::StringRef mangled_symbol,bool check_ms_abi=true)155061da546Spatrick static bool isGuardVariableSymbol(llvm::StringRef mangled_symbol,
156061da546Spatrick                                   bool check_ms_abi = true) {
157061da546Spatrick   bool result = mangled_symbol.startswith("_ZGV"); // Itanium ABI guard variable
158061da546Spatrick   if (check_ms_abi)
159061da546Spatrick     result |= mangled_symbol.endswith("@4IA"); // Microsoft ABI
160061da546Spatrick   return result;
161061da546Spatrick }
162061da546Spatrick 
CreateResultVariable(llvm::Function & llvm_function)163061da546Spatrick bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) {
164*f6aab3d8Srobert   lldb_private::Log *log(GetLog(LLDBLog::Expressions));
165061da546Spatrick 
166061da546Spatrick   if (!m_resolve_vars)
167061da546Spatrick     return true;
168061da546Spatrick 
169061da546Spatrick   // Find the result variable.  If it doesn't exist, we can give up right here.
170061da546Spatrick 
171061da546Spatrick   ValueSymbolTable &value_symbol_table = m_module->getValueSymbolTable();
172061da546Spatrick 
173061da546Spatrick   llvm::StringRef result_name;
174061da546Spatrick   bool found_result = false;
175061da546Spatrick 
176061da546Spatrick   for (StringMapEntry<llvm::Value *> &value_symbol : value_symbol_table) {
177061da546Spatrick     result_name = value_symbol.first();
178061da546Spatrick 
179061da546Spatrick     // Check if this is a guard variable. It seems this causes some hiccups
180061da546Spatrick     // on Windows, so let's only check for Itanium guard variables.
181061da546Spatrick     bool is_guard_var = isGuardVariableSymbol(result_name, /*MS ABI*/ false);
182061da546Spatrick 
183061da546Spatrick     if (result_name.contains("$__lldb_expr_result_ptr") && !is_guard_var) {
184061da546Spatrick       found_result = true;
185061da546Spatrick       m_result_is_pointer = true;
186061da546Spatrick       break;
187061da546Spatrick     }
188061da546Spatrick 
189061da546Spatrick     if (result_name.contains("$__lldb_expr_result") && !is_guard_var) {
190061da546Spatrick       found_result = true;
191061da546Spatrick       m_result_is_pointer = false;
192061da546Spatrick       break;
193061da546Spatrick     }
194061da546Spatrick   }
195061da546Spatrick 
196061da546Spatrick   if (!found_result) {
197061da546Spatrick     LLDB_LOG(log, "Couldn't find result variable");
198061da546Spatrick 
199061da546Spatrick     return true;
200061da546Spatrick   }
201061da546Spatrick 
202061da546Spatrick   LLDB_LOG(log, "Result name: \"{0}\"", result_name);
203061da546Spatrick 
204061da546Spatrick   Value *result_value = m_module->getNamedValue(result_name);
205061da546Spatrick 
206061da546Spatrick   if (!result_value) {
207061da546Spatrick     LLDB_LOG(log, "Result variable had no data");
208061da546Spatrick 
209061da546Spatrick     m_error_stream.Format("Internal error [IRForTarget]: Result variable's "
210061da546Spatrick                           "name ({0}) exists, but not its definition\n",
211061da546Spatrick                           result_name);
212061da546Spatrick 
213061da546Spatrick     return false;
214061da546Spatrick   }
215061da546Spatrick 
216061da546Spatrick   LLDB_LOG(log, "Found result in the IR: \"{0}\"",
217061da546Spatrick            PrintValue(result_value, false));
218061da546Spatrick 
219061da546Spatrick   GlobalVariable *result_global = dyn_cast<GlobalVariable>(result_value);
220061da546Spatrick 
221061da546Spatrick   if (!result_global) {
222061da546Spatrick     LLDB_LOG(log, "Result variable isn't a GlobalVariable");
223061da546Spatrick 
224061da546Spatrick     m_error_stream.Format("Internal error [IRForTarget]: Result variable ({0}) "
225061da546Spatrick                           "is defined, but is not a global variable\n",
226061da546Spatrick                           result_name);
227061da546Spatrick 
228061da546Spatrick     return false;
229061da546Spatrick   }
230061da546Spatrick 
231061da546Spatrick   clang::NamedDecl *result_decl = DeclForGlobal(result_global);
232061da546Spatrick   if (!result_decl) {
233061da546Spatrick     LLDB_LOG(log, "Result variable doesn't have a corresponding Decl");
234061da546Spatrick 
235061da546Spatrick     m_error_stream.Format("Internal error [IRForTarget]: Result variable ({0}) "
236061da546Spatrick                           "does not have a corresponding Clang entity\n",
237061da546Spatrick                           result_name);
238061da546Spatrick 
239061da546Spatrick     return false;
240061da546Spatrick   }
241061da546Spatrick 
242061da546Spatrick   if (log) {
243061da546Spatrick     std::string decl_desc_str;
244061da546Spatrick     raw_string_ostream decl_desc_stream(decl_desc_str);
245061da546Spatrick     result_decl->print(decl_desc_stream);
246061da546Spatrick     decl_desc_stream.flush();
247061da546Spatrick 
248061da546Spatrick     LLDB_LOG(log, "Found result decl: \"{0}\"", decl_desc_str);
249061da546Spatrick   }
250061da546Spatrick 
251061da546Spatrick   clang::VarDecl *result_var = dyn_cast<clang::VarDecl>(result_decl);
252061da546Spatrick   if (!result_var) {
253061da546Spatrick     LLDB_LOG(log, "Result variable Decl isn't a VarDecl");
254061da546Spatrick 
255061da546Spatrick     m_error_stream.Format("Internal error [IRForTarget]: Result variable "
256061da546Spatrick                           "({0})'s corresponding Clang entity isn't a "
257061da546Spatrick                           "variable\n",
258061da546Spatrick                           result_name);
259061da546Spatrick 
260061da546Spatrick     return false;
261061da546Spatrick   }
262061da546Spatrick 
263061da546Spatrick   // Get the next available result name from m_decl_map and create the
264061da546Spatrick   // persistent variable for it
265061da546Spatrick 
266061da546Spatrick   // If the result is an Lvalue, it is emitted as a pointer; see
267061da546Spatrick   // ASTResultSynthesizer::SynthesizeBodyResult.
268061da546Spatrick   if (m_result_is_pointer) {
269061da546Spatrick     clang::QualType pointer_qual_type = result_var->getType();
270061da546Spatrick     const clang::Type *pointer_type = pointer_qual_type.getTypePtr();
271061da546Spatrick 
272061da546Spatrick     const clang::PointerType *pointer_pointertype =
273061da546Spatrick         pointer_type->getAs<clang::PointerType>();
274061da546Spatrick     const clang::ObjCObjectPointerType *pointer_objcobjpointertype =
275061da546Spatrick         pointer_type->getAs<clang::ObjCObjectPointerType>();
276061da546Spatrick 
277061da546Spatrick     if (pointer_pointertype) {
278061da546Spatrick       clang::QualType element_qual_type = pointer_pointertype->getPointeeType();
279061da546Spatrick 
280061da546Spatrick       m_result_type = lldb_private::TypeFromParser(
281dda28197Spatrick           m_decl_map->GetTypeSystem()->GetType(element_qual_type));
282061da546Spatrick     } else if (pointer_objcobjpointertype) {
283061da546Spatrick       clang::QualType element_qual_type =
284061da546Spatrick           clang::QualType(pointer_objcobjpointertype->getObjectType(), 0);
285061da546Spatrick 
286061da546Spatrick       m_result_type = lldb_private::TypeFromParser(
287dda28197Spatrick           m_decl_map->GetTypeSystem()->GetType(element_qual_type));
288061da546Spatrick     } else {
289061da546Spatrick       LLDB_LOG(log, "Expected result to have pointer type, but it did not");
290061da546Spatrick 
291061da546Spatrick       m_error_stream.Format("Internal error [IRForTarget]: Lvalue result ({0}) "
292061da546Spatrick                             "is not a pointer variable\n",
293061da546Spatrick                             result_name);
294061da546Spatrick 
295061da546Spatrick       return false;
296061da546Spatrick     }
297061da546Spatrick   } else {
298061da546Spatrick     m_result_type = lldb_private::TypeFromParser(
299dda28197Spatrick         m_decl_map->GetTypeSystem()->GetType(result_var->getType()));
300061da546Spatrick   }
301061da546Spatrick 
302061da546Spatrick   lldb::TargetSP target_sp(m_execution_unit.GetTarget());
303*f6aab3d8Srobert   std::optional<uint64_t> bit_size = m_result_type.GetBitSize(target_sp.get());
304061da546Spatrick   if (!bit_size) {
305061da546Spatrick     lldb_private::StreamString type_desc_stream;
306061da546Spatrick     m_result_type.DumpTypeDescription(&type_desc_stream);
307061da546Spatrick 
308061da546Spatrick     LLDB_LOG(log, "Result type has unknown size");
309061da546Spatrick 
310061da546Spatrick     m_error_stream.Printf("Error [IRForTarget]: Size of result type '%s' "
311061da546Spatrick                           "couldn't be determined\n",
312061da546Spatrick                           type_desc_stream.GetData());
313061da546Spatrick     return false;
314061da546Spatrick   }
315061da546Spatrick 
316061da546Spatrick   if (log) {
317061da546Spatrick     lldb_private::StreamString type_desc_stream;
318061da546Spatrick     m_result_type.DumpTypeDescription(&type_desc_stream);
319061da546Spatrick 
320061da546Spatrick     LLDB_LOG(log, "Result decl type: \"{0}\"", type_desc_stream.GetData());
321061da546Spatrick   }
322061da546Spatrick 
323061da546Spatrick   m_result_name = lldb_private::ConstString("$RESULT_NAME");
324061da546Spatrick 
325061da546Spatrick   LLDB_LOG(log, "Creating a new result global: \"{0}\" with size {1}",
326be691f3bSpatrick            m_result_name,
327*f6aab3d8Srobert            m_result_type.GetByteSize(target_sp.get()).value_or(0));
328061da546Spatrick 
329061da546Spatrick   // Construct a new result global and set up its metadata
330061da546Spatrick 
331061da546Spatrick   GlobalVariable *new_result_global = new GlobalVariable(
332*f6aab3d8Srobert       (*m_module), result_global->getValueType(), false, /* not constant */
333061da546Spatrick       GlobalValue::ExternalLinkage, nullptr,             /* no initializer */
334061da546Spatrick       m_result_name.GetCString());
335061da546Spatrick 
336061da546Spatrick   // It's too late in compilation to create a new VarDecl for this, but we
337061da546Spatrick   // don't need to.  We point the metadata at the old VarDecl.  This creates an
338061da546Spatrick   // odd anomaly: a variable with a Value whose name is something like $0 and a
339061da546Spatrick   // Decl whose name is $__lldb_expr_result.  This condition is handled in
340061da546Spatrick   // ClangExpressionDeclMap::DoMaterialize, and the name of the variable is
341061da546Spatrick   // fixed up.
342061da546Spatrick 
343061da546Spatrick   ConstantInt *new_constant_int =
344061da546Spatrick       ConstantInt::get(llvm::Type::getInt64Ty(m_module->getContext()),
345061da546Spatrick                        reinterpret_cast<uintptr_t>(result_decl), false);
346061da546Spatrick 
347061da546Spatrick   llvm::Metadata *values[2];
348061da546Spatrick   values[0] = ConstantAsMetadata::get(new_result_global);
349061da546Spatrick   values[1] = ConstantAsMetadata::get(new_constant_int);
350061da546Spatrick 
351061da546Spatrick   ArrayRef<Metadata *> value_ref(values, 2);
352061da546Spatrick 
353061da546Spatrick   MDNode *persistent_global_md = MDNode::get(m_module->getContext(), value_ref);
354061da546Spatrick   NamedMDNode *named_metadata =
355061da546Spatrick       m_module->getNamedMetadata("clang.global.decl.ptrs");
356061da546Spatrick   named_metadata->addOperand(persistent_global_md);
357061da546Spatrick 
358061da546Spatrick   LLDB_LOG(log, "Replacing \"{0}\" with \"{1}\"", PrintValue(result_global),
359061da546Spatrick            PrintValue(new_result_global));
360061da546Spatrick 
361061da546Spatrick   if (result_global->use_empty()) {
362061da546Spatrick     // We need to synthesize a store for this variable, because otherwise
363061da546Spatrick     // there's nothing to put into its equivalent persistent variable.
364061da546Spatrick 
365061da546Spatrick     BasicBlock &entry_block(llvm_function.getEntryBlock());
366061da546Spatrick     Instruction *first_entry_instruction(entry_block.getFirstNonPHIOrDbg());
367061da546Spatrick 
368061da546Spatrick     if (!first_entry_instruction)
369061da546Spatrick       return false;
370061da546Spatrick 
371061da546Spatrick     if (!result_global->hasInitializer()) {
372061da546Spatrick       LLDB_LOG(log, "Couldn't find initializer for unused variable");
373061da546Spatrick 
374061da546Spatrick       m_error_stream.Format("Internal error [IRForTarget]: Result variable "
375061da546Spatrick                             "({0}) has no writes and no initializer\n",
376061da546Spatrick                             result_name);
377061da546Spatrick 
378061da546Spatrick       return false;
379061da546Spatrick     }
380061da546Spatrick 
381061da546Spatrick     Constant *initializer = result_global->getInitializer();
382061da546Spatrick 
383061da546Spatrick     StoreInst *synthesized_store =
384061da546Spatrick         new StoreInst(initializer, new_result_global, first_entry_instruction);
385061da546Spatrick 
386061da546Spatrick     LLDB_LOG(log, "Synthesized result store \"{0}\"\n",
387061da546Spatrick              PrintValue(synthesized_store));
388061da546Spatrick   } else {
389061da546Spatrick     result_global->replaceAllUsesWith(new_result_global);
390061da546Spatrick   }
391061da546Spatrick 
392061da546Spatrick   if (!m_decl_map->AddPersistentVariable(
393061da546Spatrick           result_decl, m_result_name, m_result_type, true, m_result_is_pointer))
394061da546Spatrick     return false;
395061da546Spatrick 
396061da546Spatrick   result_global->eraseFromParent();
397061da546Spatrick 
398061da546Spatrick   return true;
399061da546Spatrick }
400061da546Spatrick 
RewriteObjCConstString(llvm::GlobalVariable * ns_str,llvm::GlobalVariable * cstr)401061da546Spatrick bool IRForTarget::RewriteObjCConstString(llvm::GlobalVariable *ns_str,
402061da546Spatrick                                          llvm::GlobalVariable *cstr) {
403*f6aab3d8Srobert   lldb_private::Log *log(GetLog(LLDBLog::Expressions));
404061da546Spatrick 
405061da546Spatrick   Type *ns_str_ty = ns_str->getType();
406061da546Spatrick 
407061da546Spatrick   Type *i8_ptr_ty = Type::getInt8PtrTy(m_module->getContext());
408061da546Spatrick   Type *i32_ty = Type::getInt32Ty(m_module->getContext());
409061da546Spatrick   Type *i8_ty = Type::getInt8Ty(m_module->getContext());
410061da546Spatrick 
411061da546Spatrick   if (!m_CFStringCreateWithBytes) {
412061da546Spatrick     lldb::addr_t CFStringCreateWithBytes_addr;
413061da546Spatrick 
414061da546Spatrick     static lldb_private::ConstString g_CFStringCreateWithBytes_str(
415061da546Spatrick         "CFStringCreateWithBytes");
416061da546Spatrick 
417061da546Spatrick     bool missing_weak = false;
418061da546Spatrick     CFStringCreateWithBytes_addr =
419061da546Spatrick         m_execution_unit.FindSymbol(g_CFStringCreateWithBytes_str,
420061da546Spatrick                                     missing_weak);
421061da546Spatrick     if (CFStringCreateWithBytes_addr == LLDB_INVALID_ADDRESS || missing_weak) {
422dda28197Spatrick       LLDB_LOG(log, "Couldn't find CFStringCreateWithBytes in the target");
423061da546Spatrick 
424061da546Spatrick       m_error_stream.Printf("Error [IRForTarget]: Rewriting an Objective-C "
425061da546Spatrick                             "constant string requires "
426061da546Spatrick                             "CFStringCreateWithBytes\n");
427061da546Spatrick 
428061da546Spatrick       return false;
429061da546Spatrick     }
430061da546Spatrick 
431061da546Spatrick     LLDB_LOG(log, "Found CFStringCreateWithBytes at {0}",
432061da546Spatrick              CFStringCreateWithBytes_addr);
433061da546Spatrick 
434061da546Spatrick     // Build the function type:
435061da546Spatrick     //
436061da546Spatrick     // CFStringRef CFStringCreateWithBytes (
437061da546Spatrick     //   CFAllocatorRef alloc,
438061da546Spatrick     //   const UInt8 *bytes,
439061da546Spatrick     //   CFIndex numBytes,
440061da546Spatrick     //   CFStringEncoding encoding,
441061da546Spatrick     //   Boolean isExternalRepresentation
442061da546Spatrick     // );
443061da546Spatrick     //
444061da546Spatrick     // We make the following substitutions:
445061da546Spatrick     //
446061da546Spatrick     // CFStringRef -> i8*
447061da546Spatrick     // CFAllocatorRef -> i8*
448061da546Spatrick     // UInt8 * -> i8*
449061da546Spatrick     // CFIndex -> long (i32 or i64, as appropriate; we ask the module for its
450061da546Spatrick     // pointer size for now) CFStringEncoding -> i32 Boolean -> i8
451061da546Spatrick 
452061da546Spatrick     Type *arg_type_array[5];
453061da546Spatrick 
454061da546Spatrick     arg_type_array[0] = i8_ptr_ty;
455061da546Spatrick     arg_type_array[1] = i8_ptr_ty;
456061da546Spatrick     arg_type_array[2] = m_intptr_ty;
457061da546Spatrick     arg_type_array[3] = i32_ty;
458061da546Spatrick     arg_type_array[4] = i8_ty;
459061da546Spatrick 
460061da546Spatrick     ArrayRef<Type *> CFSCWB_arg_types(arg_type_array, 5);
461061da546Spatrick 
462061da546Spatrick     llvm::FunctionType *CFSCWB_ty =
463061da546Spatrick         FunctionType::get(ns_str_ty, CFSCWB_arg_types, false);
464061da546Spatrick 
465061da546Spatrick     // Build the constant containing the pointer to the function
466061da546Spatrick     PointerType *CFSCWB_ptr_ty = PointerType::getUnqual(CFSCWB_ty);
467061da546Spatrick     Constant *CFSCWB_addr_int =
468061da546Spatrick         ConstantInt::get(m_intptr_ty, CFStringCreateWithBytes_addr, false);
469061da546Spatrick     m_CFStringCreateWithBytes = {
470061da546Spatrick         CFSCWB_ty, ConstantExpr::getIntToPtr(CFSCWB_addr_int, CFSCWB_ptr_ty)};
471061da546Spatrick   }
472061da546Spatrick 
473061da546Spatrick   ConstantDataSequential *string_array = nullptr;
474061da546Spatrick 
475061da546Spatrick   if (cstr)
476061da546Spatrick     string_array = dyn_cast<ConstantDataSequential>(cstr->getInitializer());
477061da546Spatrick 
478061da546Spatrick   Constant *alloc_arg = Constant::getNullValue(i8_ptr_ty);
479061da546Spatrick   Constant *bytes_arg = cstr ? ConstantExpr::getBitCast(cstr, i8_ptr_ty)
480061da546Spatrick                              : Constant::getNullValue(i8_ptr_ty);
481061da546Spatrick   Constant *numBytes_arg = ConstantInt::get(
482061da546Spatrick       m_intptr_ty, cstr ? (string_array->getNumElements() - 1) * string_array->getElementByteSize() : 0, false);
483061da546Spatrick  int encoding_flags = 0;
484061da546Spatrick  switch (cstr ? string_array->getElementByteSize() : 1) {
485061da546Spatrick  case 1:
486061da546Spatrick    encoding_flags = 0x08000100; /* 0x08000100 is kCFStringEncodingUTF8 */
487061da546Spatrick    break;
488061da546Spatrick  case 2:
489061da546Spatrick    encoding_flags = 0x0100; /* 0x0100 is kCFStringEncodingUTF16 */
490061da546Spatrick    break;
491061da546Spatrick  case 4:
492061da546Spatrick    encoding_flags = 0x0c000100; /* 0x0c000100 is kCFStringEncodingUTF32 */
493061da546Spatrick    break;
494061da546Spatrick  default:
495061da546Spatrick    encoding_flags = 0x0600; /* fall back to 0x0600, kCFStringEncodingASCII */
496061da546Spatrick    LLDB_LOG(log, "Encountered an Objective-C constant string with unusual "
497061da546Spatrick                  "element size {0}",
498061da546Spatrick             string_array->getElementByteSize());
499061da546Spatrick  }
500061da546Spatrick  Constant *encoding_arg = ConstantInt::get(i32_ty, encoding_flags, false);
501061da546Spatrick  Constant *isExternal_arg =
502061da546Spatrick      ConstantInt::get(i8_ty, 0x0, false); /* 0x0 is false */
503061da546Spatrick 
504061da546Spatrick  Value *argument_array[5];
505061da546Spatrick 
506061da546Spatrick  argument_array[0] = alloc_arg;
507061da546Spatrick  argument_array[1] = bytes_arg;
508061da546Spatrick  argument_array[2] = numBytes_arg;
509061da546Spatrick  argument_array[3] = encoding_arg;
510061da546Spatrick  argument_array[4] = isExternal_arg;
511061da546Spatrick 
512061da546Spatrick  ArrayRef<Value *> CFSCWB_arguments(argument_array, 5);
513061da546Spatrick 
514061da546Spatrick  FunctionValueCache CFSCWB_Caller(
515061da546Spatrick      [this, &CFSCWB_arguments](llvm::Function *function) -> llvm::Value * {
516061da546Spatrick        return CallInst::Create(
517061da546Spatrick            m_CFStringCreateWithBytes, CFSCWB_arguments,
518061da546Spatrick            "CFStringCreateWithBytes",
519061da546Spatrick            llvm::cast<Instruction>(
520061da546Spatrick                m_entry_instruction_finder.GetValue(function)));
521061da546Spatrick      });
522061da546Spatrick 
523061da546Spatrick  if (!UnfoldConstant(ns_str, nullptr, CFSCWB_Caller, m_entry_instruction_finder,
524061da546Spatrick                      m_error_stream)) {
525061da546Spatrick    LLDB_LOG(log, "Couldn't replace the NSString with the result of the call");
526061da546Spatrick 
527061da546Spatrick    m_error_stream.Printf("error [IRForTarget internal]: Couldn't replace an "
528061da546Spatrick                          "Objective-C constant string with a dynamic "
529061da546Spatrick                          "string\n");
530061da546Spatrick 
531061da546Spatrick    return false;
532061da546Spatrick   }
533061da546Spatrick 
534061da546Spatrick   ns_str->eraseFromParent();
535061da546Spatrick 
536061da546Spatrick   return true;
537061da546Spatrick }
538061da546Spatrick 
RewriteObjCConstStrings()539061da546Spatrick bool IRForTarget::RewriteObjCConstStrings() {
540*f6aab3d8Srobert   lldb_private::Log *log(GetLog(LLDBLog::Expressions));
541061da546Spatrick 
542061da546Spatrick   ValueSymbolTable &value_symbol_table = m_module->getValueSymbolTable();
543061da546Spatrick 
544061da546Spatrick   for (StringMapEntry<llvm::Value *> &value_symbol : value_symbol_table) {
545061da546Spatrick     llvm::StringRef value_name = value_symbol.first();
546061da546Spatrick 
547061da546Spatrick     if (value_name.contains("_unnamed_cfstring_")) {
548061da546Spatrick       Value *nsstring_value = value_symbol.second;
549061da546Spatrick 
550061da546Spatrick       GlobalVariable *nsstring_global =
551061da546Spatrick           dyn_cast<GlobalVariable>(nsstring_value);
552061da546Spatrick 
553061da546Spatrick       if (!nsstring_global) {
554061da546Spatrick         LLDB_LOG(log, "NSString variable is not a GlobalVariable");
555061da546Spatrick 
556061da546Spatrick         m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C "
557061da546Spatrick                               "constant string is not a global variable\n");
558061da546Spatrick 
559061da546Spatrick         return false;
560061da546Spatrick       }
561061da546Spatrick 
562061da546Spatrick       if (!nsstring_global->hasInitializer()) {
563061da546Spatrick         LLDB_LOG(log, "NSString variable does not have an initializer");
564061da546Spatrick 
565061da546Spatrick         m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C "
566061da546Spatrick                               "constant string does not have an initializer\n");
567061da546Spatrick 
568061da546Spatrick         return false;
569061da546Spatrick       }
570061da546Spatrick 
571061da546Spatrick       ConstantStruct *nsstring_struct =
572061da546Spatrick           dyn_cast<ConstantStruct>(nsstring_global->getInitializer());
573061da546Spatrick 
574061da546Spatrick       if (!nsstring_struct) {
575061da546Spatrick         LLDB_LOG(log,
576061da546Spatrick                  "NSString variable's initializer is not a ConstantStruct");
577061da546Spatrick 
578061da546Spatrick         m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C "
579061da546Spatrick                               "constant string is not a structure constant\n");
580061da546Spatrick 
581061da546Spatrick         return false;
582061da546Spatrick       }
583061da546Spatrick 
584061da546Spatrick       // We expect the following structure:
585061da546Spatrick       //
586061da546Spatrick       // struct {
587061da546Spatrick       //   int *isa;
588061da546Spatrick       //   int flags;
589061da546Spatrick       //   char *str;
590061da546Spatrick       //   long length;
591061da546Spatrick       // };
592061da546Spatrick 
593061da546Spatrick       if (nsstring_struct->getNumOperands() != 4) {
594061da546Spatrick 
595061da546Spatrick         LLDB_LOG(log,
596061da546Spatrick                  "NSString variable's initializer structure has an "
597061da546Spatrick                  "unexpected number of members.  Should be 4, is {0}",
598061da546Spatrick                  nsstring_struct->getNumOperands());
599061da546Spatrick 
600061da546Spatrick         m_error_stream.Printf("Internal error [IRForTarget]: The struct for an "
601061da546Spatrick                               "Objective-C constant string is not as "
602061da546Spatrick                               "expected\n");
603061da546Spatrick 
604061da546Spatrick         return false;
605061da546Spatrick       }
606061da546Spatrick 
607061da546Spatrick       Constant *nsstring_member = nsstring_struct->getOperand(2);
608061da546Spatrick 
609061da546Spatrick       if (!nsstring_member) {
610061da546Spatrick         LLDB_LOG(log, "NSString initializer's str element was empty");
611061da546Spatrick 
612061da546Spatrick         m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C "
613061da546Spatrick                               "constant string does not have a string "
614061da546Spatrick                               "initializer\n");
615061da546Spatrick 
616061da546Spatrick         return false;
617061da546Spatrick       }
618061da546Spatrick 
619*f6aab3d8Srobert       auto *cstr_global = dyn_cast<GlobalVariable>(nsstring_member);
620061da546Spatrick       if (!cstr_global) {
621061da546Spatrick         LLDB_LOG(log,
622061da546Spatrick                  "NSString initializer's str element is not a GlobalVariable");
623061da546Spatrick 
624061da546Spatrick         m_error_stream.Printf("Internal error [IRForTarget]: Unhandled"
625061da546Spatrick                               "constant string initializer\n");
626061da546Spatrick 
627061da546Spatrick         return false;
628061da546Spatrick       }
629061da546Spatrick 
630061da546Spatrick       if (!cstr_global->hasInitializer()) {
631061da546Spatrick         LLDB_LOG(log, "NSString initializer's str element does not have an "
632061da546Spatrick                       "initializer");
633061da546Spatrick 
634061da546Spatrick         m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C "
635061da546Spatrick                               "constant string's string initializer doesn't "
636061da546Spatrick                               "point to initialized data\n");
637061da546Spatrick 
638061da546Spatrick         return false;
639061da546Spatrick       }
640061da546Spatrick 
641061da546Spatrick       /*
642061da546Spatrick       if (!cstr_array)
643061da546Spatrick       {
644061da546Spatrick           if (log)
645061da546Spatrick               log->PutCString("NSString initializer's str element is not a
646061da546Spatrick       ConstantArray");
647061da546Spatrick 
648061da546Spatrick           if (m_error_stream)
649061da546Spatrick               m_error_stream.Printf("Internal error [IRForTarget]: An
650061da546Spatrick       Objective-C constant string's string initializer doesn't point to an
651061da546Spatrick       array\n");
652061da546Spatrick 
653061da546Spatrick           return false;
654061da546Spatrick       }
655061da546Spatrick 
656061da546Spatrick       if (!cstr_array->isCString())
657061da546Spatrick       {
658061da546Spatrick           if (log)
659061da546Spatrick               log->PutCString("NSString initializer's str element is not a C
660061da546Spatrick       string array");
661061da546Spatrick 
662061da546Spatrick           if (m_error_stream)
663061da546Spatrick               m_error_stream.Printf("Internal error [IRForTarget]: An
664061da546Spatrick       Objective-C constant string's string initializer doesn't point to a C
665061da546Spatrick       string\n");
666061da546Spatrick 
667061da546Spatrick           return false;
668061da546Spatrick       }
669061da546Spatrick       */
670061da546Spatrick 
671061da546Spatrick       ConstantDataArray *cstr_array =
672061da546Spatrick           dyn_cast<ConstantDataArray>(cstr_global->getInitializer());
673061da546Spatrick 
674061da546Spatrick       if (cstr_array)
675061da546Spatrick         LLDB_LOG(log, "Found NSString constant {0}, which contains \"{1}\"",
676061da546Spatrick                  value_name, cstr_array->getAsString());
677061da546Spatrick       else
678061da546Spatrick         LLDB_LOG(log, "Found NSString constant {0}, which contains \"\"",
679061da546Spatrick                  value_name);
680061da546Spatrick 
681061da546Spatrick       if (!cstr_array)
682061da546Spatrick         cstr_global = nullptr;
683061da546Spatrick 
684061da546Spatrick       if (!RewriteObjCConstString(nsstring_global, cstr_global)) {
685061da546Spatrick         LLDB_LOG(log, "Error rewriting the constant string");
686061da546Spatrick 
687061da546Spatrick         // We don't print an error message here because RewriteObjCConstString
688061da546Spatrick         // has done so for us.
689061da546Spatrick 
690061da546Spatrick         return false;
691061da546Spatrick       }
692061da546Spatrick     }
693061da546Spatrick   }
694061da546Spatrick 
695061da546Spatrick   for (StringMapEntry<llvm::Value *> &value_symbol : value_symbol_table) {
696061da546Spatrick     llvm::StringRef value_name = value_symbol.first();
697061da546Spatrick 
698061da546Spatrick     if (value_name == "__CFConstantStringClassReference") {
699061da546Spatrick       GlobalVariable *gv = dyn_cast<GlobalVariable>(value_symbol.second);
700061da546Spatrick 
701061da546Spatrick       if (!gv) {
702061da546Spatrick         LLDB_LOG(log,
703061da546Spatrick                  "__CFConstantStringClassReference is not a global variable");
704061da546Spatrick 
705061da546Spatrick         m_error_stream.Printf("Internal error [IRForTarget]: Found a "
706061da546Spatrick                               "CFConstantStringClassReference, but it is not a "
707061da546Spatrick                               "global object\n");
708061da546Spatrick 
709061da546Spatrick         return false;
710061da546Spatrick       }
711061da546Spatrick 
712061da546Spatrick       gv->eraseFromParent();
713061da546Spatrick 
714061da546Spatrick       break;
715061da546Spatrick     }
716061da546Spatrick   }
717061da546Spatrick 
718061da546Spatrick   return true;
719061da546Spatrick }
720061da546Spatrick 
IsObjCSelectorRef(Value * value)721061da546Spatrick static bool IsObjCSelectorRef(Value *value) {
722061da546Spatrick   GlobalVariable *global_variable = dyn_cast<GlobalVariable>(value);
723061da546Spatrick 
724061da546Spatrick   return !(!global_variable || !global_variable->hasName() ||
725061da546Spatrick            !global_variable->getName().startswith("OBJC_SELECTOR_REFERENCES_"));
726061da546Spatrick }
727061da546Spatrick 
728061da546Spatrick // This function does not report errors; its callers are responsible.
RewriteObjCSelector(Instruction * selector_load)729061da546Spatrick bool IRForTarget::RewriteObjCSelector(Instruction *selector_load) {
730*f6aab3d8Srobert   lldb_private::Log *log(GetLog(LLDBLog::Expressions));
731061da546Spatrick 
732061da546Spatrick   LoadInst *load = dyn_cast<LoadInst>(selector_load);
733061da546Spatrick 
734061da546Spatrick   if (!load)
735061da546Spatrick     return false;
736061da546Spatrick 
737061da546Spatrick   // Unpack the message name from the selector.  In LLVM IR, an objc_msgSend
738061da546Spatrick   // gets represented as
739061da546Spatrick   //
740*f6aab3d8Srobert   //   %sel = load ptr, ptr @OBJC_SELECTOR_REFERENCES_, align 8
741*f6aab3d8Srobert   //   call i8 @objc_msgSend(ptr %obj, ptr %sel, ...)
742061da546Spatrick   //
743*f6aab3d8Srobert   // where %obj is the object pointer and %sel is the selector.
744061da546Spatrick   //
745061da546Spatrick   // @"OBJC_SELECTOR_REFERENCES_" is a pointer to a character array called
746061da546Spatrick   // @"\01L_OBJC_llvm_moduleETH_VAR_NAllvm_moduleE_".
747061da546Spatrick   // @"\01L_OBJC_llvm_moduleETH_VAR_NAllvm_moduleE_" contains the string.
748061da546Spatrick 
749*f6aab3d8Srobert   // Find the pointer's initializer and get the string from its target.
750061da546Spatrick 
751061da546Spatrick   GlobalVariable *_objc_selector_references_ =
752061da546Spatrick       dyn_cast<GlobalVariable>(load->getPointerOperand());
753061da546Spatrick 
754061da546Spatrick   if (!_objc_selector_references_ ||
755061da546Spatrick       !_objc_selector_references_->hasInitializer())
756061da546Spatrick     return false;
757061da546Spatrick 
758061da546Spatrick   Constant *osr_initializer = _objc_selector_references_->getInitializer();
759*f6aab3d8Srobert   if (!osr_initializer)
760061da546Spatrick     return false;
761061da546Spatrick 
762061da546Spatrick   // Find the string's initializer (a ConstantArray) and get the string from it
763061da546Spatrick 
764061da546Spatrick   GlobalVariable *_objc_meth_var_name_ =
765*f6aab3d8Srobert       dyn_cast<GlobalVariable>(osr_initializer);
766061da546Spatrick 
767061da546Spatrick   if (!_objc_meth_var_name_ || !_objc_meth_var_name_->hasInitializer())
768061da546Spatrick     return false;
769061da546Spatrick 
770061da546Spatrick   Constant *omvn_initializer = _objc_meth_var_name_->getInitializer();
771061da546Spatrick 
772061da546Spatrick   ConstantDataArray *omvn_initializer_array =
773061da546Spatrick       dyn_cast<ConstantDataArray>(omvn_initializer);
774061da546Spatrick 
775061da546Spatrick   if (!omvn_initializer_array->isString())
776061da546Spatrick     return false;
777061da546Spatrick 
778dda28197Spatrick   std::string omvn_initializer_string =
779dda28197Spatrick       std::string(omvn_initializer_array->getAsString());
780061da546Spatrick 
781061da546Spatrick   LLDB_LOG(log, "Found Objective-C selector reference \"{0}\"",
782061da546Spatrick            omvn_initializer_string);
783061da546Spatrick 
784061da546Spatrick   // Construct a call to sel_registerName
785061da546Spatrick 
786061da546Spatrick   if (!m_sel_registerName) {
787061da546Spatrick     lldb::addr_t sel_registerName_addr;
788061da546Spatrick 
789061da546Spatrick     bool missing_weak = false;
790061da546Spatrick     static lldb_private::ConstString g_sel_registerName_str("sel_registerName");
791061da546Spatrick     sel_registerName_addr = m_execution_unit.FindSymbol(g_sel_registerName_str,
792061da546Spatrick                                                         missing_weak);
793061da546Spatrick     if (sel_registerName_addr == LLDB_INVALID_ADDRESS || missing_weak)
794061da546Spatrick       return false;
795061da546Spatrick 
796061da546Spatrick     LLDB_LOG(log, "Found sel_registerName at {0}", sel_registerName_addr);
797061da546Spatrick 
798061da546Spatrick     // Build the function type: struct objc_selector
799061da546Spatrick     // *sel_registerName(uint8_t*)
800061da546Spatrick 
801061da546Spatrick     // The below code would be "more correct," but in actuality what's required
802061da546Spatrick     // is uint8_t*
803061da546Spatrick     // Type *sel_type = StructType::get(m_module->getContext());
804061da546Spatrick     // Type *sel_ptr_type = PointerType::getUnqual(sel_type);
805061da546Spatrick     Type *sel_ptr_type = Type::getInt8PtrTy(m_module->getContext());
806061da546Spatrick 
807061da546Spatrick     Type *type_array[1];
808061da546Spatrick 
809061da546Spatrick     type_array[0] = llvm::Type::getInt8PtrTy(m_module->getContext());
810061da546Spatrick 
811061da546Spatrick     ArrayRef<Type *> srN_arg_types(type_array, 1);
812061da546Spatrick 
813061da546Spatrick     llvm::FunctionType *srN_type =
814061da546Spatrick         FunctionType::get(sel_ptr_type, srN_arg_types, false);
815061da546Spatrick 
816061da546Spatrick     // Build the constant containing the pointer to the function
817061da546Spatrick     PointerType *srN_ptr_ty = PointerType::getUnqual(srN_type);
818061da546Spatrick     Constant *srN_addr_int =
819061da546Spatrick         ConstantInt::get(m_intptr_ty, sel_registerName_addr, false);
820061da546Spatrick     m_sel_registerName = {srN_type,
821061da546Spatrick                           ConstantExpr::getIntToPtr(srN_addr_int, srN_ptr_ty)};
822061da546Spatrick   }
823061da546Spatrick 
824061da546Spatrick   Value *argument_array[1];
825061da546Spatrick 
826061da546Spatrick   Constant *omvn_pointer = ConstantExpr::getBitCast(
827061da546Spatrick       _objc_meth_var_name_, Type::getInt8PtrTy(m_module->getContext()));
828061da546Spatrick 
829061da546Spatrick   argument_array[0] = omvn_pointer;
830061da546Spatrick 
831061da546Spatrick   ArrayRef<Value *> srN_arguments(argument_array, 1);
832061da546Spatrick 
833061da546Spatrick   CallInst *srN_call = CallInst::Create(m_sel_registerName, srN_arguments,
834061da546Spatrick                                         "sel_registerName", selector_load);
835061da546Spatrick 
836061da546Spatrick   // Replace the load with the call in all users
837061da546Spatrick 
838061da546Spatrick   selector_load->replaceAllUsesWith(srN_call);
839061da546Spatrick 
840061da546Spatrick   selector_load->eraseFromParent();
841061da546Spatrick 
842061da546Spatrick   return true;
843061da546Spatrick }
844061da546Spatrick 
RewriteObjCSelectors(BasicBlock & basic_block)845061da546Spatrick bool IRForTarget::RewriteObjCSelectors(BasicBlock &basic_block) {
846*f6aab3d8Srobert   lldb_private::Log *log(GetLog(LLDBLog::Expressions));
847061da546Spatrick 
848061da546Spatrick   InstrList selector_loads;
849061da546Spatrick 
850061da546Spatrick   for (Instruction &inst : basic_block) {
851061da546Spatrick     if (LoadInst *load = dyn_cast<LoadInst>(&inst))
852061da546Spatrick       if (IsObjCSelectorRef(load->getPointerOperand()))
853061da546Spatrick         selector_loads.push_back(&inst);
854061da546Spatrick   }
855061da546Spatrick 
856061da546Spatrick   for (Instruction *inst : selector_loads) {
857061da546Spatrick     if (!RewriteObjCSelector(inst)) {
858061da546Spatrick       m_error_stream.Printf("Internal error [IRForTarget]: Couldn't change a "
859061da546Spatrick                             "static reference to an Objective-C selector to a "
860061da546Spatrick                             "dynamic reference\n");
861061da546Spatrick 
862061da546Spatrick       LLDB_LOG(log, "Couldn't rewrite a reference to an Objective-C selector");
863061da546Spatrick 
864061da546Spatrick       return false;
865061da546Spatrick     }
866061da546Spatrick   }
867061da546Spatrick 
868061da546Spatrick   return true;
869061da546Spatrick }
870061da546Spatrick 
IsObjCClassReference(Value * value)871061da546Spatrick static bool IsObjCClassReference(Value *value) {
872061da546Spatrick   GlobalVariable *global_variable = dyn_cast<GlobalVariable>(value);
873061da546Spatrick 
874061da546Spatrick   return !(!global_variable || !global_variable->hasName() ||
875061da546Spatrick            !global_variable->getName().startswith("OBJC_CLASS_REFERENCES_"));
876061da546Spatrick }
877061da546Spatrick 
878061da546Spatrick // This function does not report errors; its callers are responsible.
RewriteObjCClassReference(Instruction * class_load)879061da546Spatrick bool IRForTarget::RewriteObjCClassReference(Instruction *class_load) {
880*f6aab3d8Srobert   lldb_private::Log *log(GetLog(LLDBLog::Expressions));
881061da546Spatrick 
882061da546Spatrick   LoadInst *load = dyn_cast<LoadInst>(class_load);
883061da546Spatrick 
884061da546Spatrick   if (!load)
885061da546Spatrick     return false;
886061da546Spatrick 
887061da546Spatrick   // Unpack the class name from the reference.  In LLVM IR, a reference to an
888061da546Spatrick   // Objective-C class gets represented as
889061da546Spatrick   //
890061da546Spatrick   // %tmp     = load %struct._objc_class*,
891061da546Spatrick   //            %struct._objc_class** @OBJC_CLASS_REFERENCES_, align 4
892061da546Spatrick   //
893061da546Spatrick   // @"OBJC_CLASS_REFERENCES_ is a bitcast of a character array called
894061da546Spatrick   // @OBJC_CLASS_NAME_. @OBJC_CLASS_NAME contains the string.
895061da546Spatrick 
896061da546Spatrick   // Find the pointer's initializer (a ConstantExpr with opcode BitCast) and
897061da546Spatrick   // get the string from its target
898061da546Spatrick 
899061da546Spatrick   GlobalVariable *_objc_class_references_ =
900061da546Spatrick       dyn_cast<GlobalVariable>(load->getPointerOperand());
901061da546Spatrick 
902061da546Spatrick   if (!_objc_class_references_ ||
903061da546Spatrick       !_objc_class_references_->hasInitializer())
904061da546Spatrick     return false;
905061da546Spatrick 
906061da546Spatrick   Constant *ocr_initializer = _objc_class_references_->getInitializer();
907061da546Spatrick 
908061da546Spatrick   ConstantExpr *ocr_initializer_expr = dyn_cast<ConstantExpr>(ocr_initializer);
909061da546Spatrick 
910061da546Spatrick   if (!ocr_initializer_expr ||
911061da546Spatrick       ocr_initializer_expr->getOpcode() != Instruction::BitCast)
912061da546Spatrick     return false;
913061da546Spatrick 
914061da546Spatrick   Value *ocr_initializer_base = ocr_initializer_expr->getOperand(0);
915061da546Spatrick 
916061da546Spatrick   if (!ocr_initializer_base)
917061da546Spatrick     return false;
918061da546Spatrick 
919061da546Spatrick   // Find the string's initializer (a ConstantArray) and get the string from it
920061da546Spatrick 
921061da546Spatrick   GlobalVariable *_objc_class_name_ =
922061da546Spatrick       dyn_cast<GlobalVariable>(ocr_initializer_base);
923061da546Spatrick 
924061da546Spatrick   if (!_objc_class_name_ || !_objc_class_name_->hasInitializer())
925061da546Spatrick     return false;
926061da546Spatrick 
927061da546Spatrick   Constant *ocn_initializer = _objc_class_name_->getInitializer();
928061da546Spatrick 
929061da546Spatrick   ConstantDataArray *ocn_initializer_array =
930061da546Spatrick       dyn_cast<ConstantDataArray>(ocn_initializer);
931061da546Spatrick 
932061da546Spatrick   if (!ocn_initializer_array->isString())
933061da546Spatrick     return false;
934061da546Spatrick 
935dda28197Spatrick   std::string ocn_initializer_string =
936dda28197Spatrick       std::string(ocn_initializer_array->getAsString());
937061da546Spatrick 
938061da546Spatrick   LLDB_LOG(log, "Found Objective-C class reference \"{0}\"",
939061da546Spatrick            ocn_initializer_string);
940061da546Spatrick 
941061da546Spatrick   // Construct a call to objc_getClass
942061da546Spatrick 
943061da546Spatrick   if (!m_objc_getClass) {
944061da546Spatrick     lldb::addr_t objc_getClass_addr;
945061da546Spatrick 
946061da546Spatrick     bool missing_weak = false;
947061da546Spatrick     static lldb_private::ConstString g_objc_getClass_str("objc_getClass");
948061da546Spatrick     objc_getClass_addr = m_execution_unit.FindSymbol(g_objc_getClass_str,
949061da546Spatrick                                                      missing_weak);
950061da546Spatrick     if (objc_getClass_addr == LLDB_INVALID_ADDRESS || missing_weak)
951061da546Spatrick       return false;
952061da546Spatrick 
953061da546Spatrick     LLDB_LOG(log, "Found objc_getClass at {0}", objc_getClass_addr);
954061da546Spatrick 
955061da546Spatrick     // Build the function type: %struct._objc_class *objc_getClass(i8*)
956061da546Spatrick 
957061da546Spatrick     Type *class_type = load->getType();
958061da546Spatrick     Type *type_array[1];
959061da546Spatrick     type_array[0] = llvm::Type::getInt8PtrTy(m_module->getContext());
960061da546Spatrick 
961061da546Spatrick     ArrayRef<Type *> ogC_arg_types(type_array, 1);
962061da546Spatrick 
963061da546Spatrick     llvm::FunctionType *ogC_type =
964061da546Spatrick         FunctionType::get(class_type, ogC_arg_types, false);
965061da546Spatrick 
966061da546Spatrick     // Build the constant containing the pointer to the function
967061da546Spatrick     PointerType *ogC_ptr_ty = PointerType::getUnqual(ogC_type);
968061da546Spatrick     Constant *ogC_addr_int =
969061da546Spatrick         ConstantInt::get(m_intptr_ty, objc_getClass_addr, false);
970061da546Spatrick     m_objc_getClass = {ogC_type,
971061da546Spatrick                        ConstantExpr::getIntToPtr(ogC_addr_int, ogC_ptr_ty)};
972061da546Spatrick   }
973061da546Spatrick 
974061da546Spatrick   Value *argument_array[1];
975061da546Spatrick 
976061da546Spatrick   Constant *ocn_pointer = ConstantExpr::getBitCast(
977061da546Spatrick       _objc_class_name_, Type::getInt8PtrTy(m_module->getContext()));
978061da546Spatrick 
979061da546Spatrick   argument_array[0] = ocn_pointer;
980061da546Spatrick 
981061da546Spatrick   ArrayRef<Value *> ogC_arguments(argument_array, 1);
982061da546Spatrick 
983061da546Spatrick   CallInst *ogC_call = CallInst::Create(m_objc_getClass, ogC_arguments,
984061da546Spatrick                                         "objc_getClass", class_load);
985061da546Spatrick 
986061da546Spatrick   // Replace the load with the call in all users
987061da546Spatrick 
988061da546Spatrick   class_load->replaceAllUsesWith(ogC_call);
989061da546Spatrick 
990061da546Spatrick   class_load->eraseFromParent();
991061da546Spatrick 
992061da546Spatrick   return true;
993061da546Spatrick }
994061da546Spatrick 
RewriteObjCClassReferences(BasicBlock & basic_block)995061da546Spatrick bool IRForTarget::RewriteObjCClassReferences(BasicBlock &basic_block) {
996*f6aab3d8Srobert   lldb_private::Log *log(GetLog(LLDBLog::Expressions));
997061da546Spatrick 
998061da546Spatrick   InstrList class_loads;
999061da546Spatrick 
1000061da546Spatrick   for (Instruction &inst : basic_block) {
1001061da546Spatrick     if (LoadInst *load = dyn_cast<LoadInst>(&inst))
1002061da546Spatrick       if (IsObjCClassReference(load->getPointerOperand()))
1003061da546Spatrick         class_loads.push_back(&inst);
1004061da546Spatrick   }
1005061da546Spatrick 
1006061da546Spatrick   for (Instruction *inst : class_loads) {
1007061da546Spatrick     if (!RewriteObjCClassReference(inst)) {
1008061da546Spatrick       m_error_stream.Printf("Internal error [IRForTarget]: Couldn't change a "
1009061da546Spatrick                             "static reference to an Objective-C class to a "
1010061da546Spatrick                             "dynamic reference\n");
1011061da546Spatrick 
1012061da546Spatrick       LLDB_LOG(log, "Couldn't rewrite a reference to an Objective-C class");
1013061da546Spatrick 
1014061da546Spatrick       return false;
1015061da546Spatrick     }
1016061da546Spatrick   }
1017061da546Spatrick 
1018061da546Spatrick   return true;
1019061da546Spatrick }
1020061da546Spatrick 
1021061da546Spatrick // This function does not report errors; its callers are responsible.
RewritePersistentAlloc(llvm::Instruction * persistent_alloc)1022061da546Spatrick bool IRForTarget::RewritePersistentAlloc(llvm::Instruction *persistent_alloc) {
1023*f6aab3d8Srobert   lldb_private::Log *log(GetLog(LLDBLog::Expressions));
1024061da546Spatrick 
1025061da546Spatrick   AllocaInst *alloc = dyn_cast<AllocaInst>(persistent_alloc);
1026061da546Spatrick 
1027061da546Spatrick   MDNode *alloc_md = alloc->getMetadata("clang.decl.ptr");
1028061da546Spatrick 
1029061da546Spatrick   if (!alloc_md || !alloc_md->getNumOperands())
1030061da546Spatrick     return false;
1031061da546Spatrick 
1032061da546Spatrick   ConstantInt *constant_int =
1033061da546Spatrick       mdconst::dyn_extract<ConstantInt>(alloc_md->getOperand(0));
1034061da546Spatrick 
1035061da546Spatrick   if (!constant_int)
1036061da546Spatrick     return false;
1037061da546Spatrick 
1038061da546Spatrick   // We attempt to register this as a new persistent variable with the DeclMap.
1039061da546Spatrick 
1040061da546Spatrick   uintptr_t ptr = constant_int->getZExtValue();
1041061da546Spatrick 
1042061da546Spatrick   clang::VarDecl *decl = reinterpret_cast<clang::VarDecl *>(ptr);
1043061da546Spatrick 
1044061da546Spatrick   lldb_private::TypeFromParser result_decl_type(
1045dda28197Spatrick       m_decl_map->GetTypeSystem()->GetType(decl->getType()));
1046061da546Spatrick 
1047061da546Spatrick   StringRef decl_name(decl->getName());
1048061da546Spatrick   lldb_private::ConstString persistent_variable_name(decl_name.data(),
1049061da546Spatrick                                                      decl_name.size());
1050061da546Spatrick   if (!m_decl_map->AddPersistentVariable(decl, persistent_variable_name,
1051061da546Spatrick                                          result_decl_type, false, false))
1052061da546Spatrick     return false;
1053061da546Spatrick 
1054061da546Spatrick   GlobalVariable *persistent_global = new GlobalVariable(
1055061da546Spatrick       (*m_module), alloc->getType(), false,  /* not constant */
1056061da546Spatrick       GlobalValue::ExternalLinkage, nullptr, /* no initializer */
1057061da546Spatrick       alloc->getName().str());
1058061da546Spatrick 
1059061da546Spatrick   // What we're going to do here is make believe this was a regular old
1060061da546Spatrick   // external variable.  That means we need to make the metadata valid.
1061061da546Spatrick 
1062061da546Spatrick   NamedMDNode *named_metadata =
1063061da546Spatrick       m_module->getOrInsertNamedMetadata("clang.global.decl.ptrs");
1064061da546Spatrick 
1065061da546Spatrick   llvm::Metadata *values[2];
1066061da546Spatrick   values[0] = ConstantAsMetadata::get(persistent_global);
1067061da546Spatrick   values[1] = ConstantAsMetadata::get(constant_int);
1068061da546Spatrick 
1069061da546Spatrick   ArrayRef<llvm::Metadata *> value_ref(values, 2);
1070061da546Spatrick 
1071061da546Spatrick   MDNode *persistent_global_md = MDNode::get(m_module->getContext(), value_ref);
1072061da546Spatrick   named_metadata->addOperand(persistent_global_md);
1073061da546Spatrick 
1074061da546Spatrick   // Now, since the variable is a pointer variable, we will drop in a load of
1075061da546Spatrick   // that pointer variable.
1076061da546Spatrick 
1077*f6aab3d8Srobert   LoadInst *persistent_load = new LoadInst(persistent_global->getValueType(),
1078dda28197Spatrick                                            persistent_global, "", alloc);
1079061da546Spatrick 
1080061da546Spatrick   LLDB_LOG(log, "Replacing \"{0}\" with \"{1}\"", PrintValue(alloc),
1081061da546Spatrick            PrintValue(persistent_load));
1082061da546Spatrick 
1083061da546Spatrick   alloc->replaceAllUsesWith(persistent_load);
1084061da546Spatrick   alloc->eraseFromParent();
1085061da546Spatrick 
1086061da546Spatrick   return true;
1087061da546Spatrick }
1088061da546Spatrick 
RewritePersistentAllocs(llvm::BasicBlock & basic_block)1089061da546Spatrick bool IRForTarget::RewritePersistentAllocs(llvm::BasicBlock &basic_block) {
1090061da546Spatrick   if (!m_resolve_vars)
1091061da546Spatrick     return true;
1092061da546Spatrick 
1093*f6aab3d8Srobert   lldb_private::Log *log(GetLog(LLDBLog::Expressions));
1094061da546Spatrick 
1095061da546Spatrick   InstrList pvar_allocs;
1096061da546Spatrick 
1097061da546Spatrick   for (Instruction &inst : basic_block) {
1098061da546Spatrick 
1099061da546Spatrick     if (AllocaInst *alloc = dyn_cast<AllocaInst>(&inst)) {
1100061da546Spatrick       llvm::StringRef alloc_name = alloc->getName();
1101061da546Spatrick 
1102061da546Spatrick       if (alloc_name.startswith("$") && !alloc_name.startswith("$__lldb")) {
1103061da546Spatrick         if (alloc_name.find_first_of("0123456789") == 1) {
1104061da546Spatrick           LLDB_LOG(log, "Rejecting a numeric persistent variable.");
1105061da546Spatrick 
1106061da546Spatrick           m_error_stream.Printf("Error [IRForTarget]: Names starting with $0, "
1107061da546Spatrick                                 "$1, ... are reserved for use as result "
1108061da546Spatrick                                 "names\n");
1109061da546Spatrick 
1110061da546Spatrick           return false;
1111061da546Spatrick         }
1112061da546Spatrick 
1113061da546Spatrick         pvar_allocs.push_back(alloc);
1114061da546Spatrick       }
1115061da546Spatrick     }
1116061da546Spatrick   }
1117061da546Spatrick 
1118061da546Spatrick   for (Instruction *inst : pvar_allocs) {
1119061da546Spatrick     if (!RewritePersistentAlloc(inst)) {
1120061da546Spatrick       m_error_stream.Printf("Internal error [IRForTarget]: Couldn't rewrite "
1121061da546Spatrick                             "the creation of a persistent variable\n");
1122061da546Spatrick 
1123061da546Spatrick       LLDB_LOG(log, "Couldn't rewrite the creation of a persistent variable");
1124061da546Spatrick 
1125061da546Spatrick       return false;
1126061da546Spatrick     }
1127061da546Spatrick   }
1128061da546Spatrick 
1129061da546Spatrick   return true;
1130061da546Spatrick }
1131061da546Spatrick 
1132061da546Spatrick // This function does not report errors; its callers are responsible.
MaybeHandleVariable(Value * llvm_value_ptr)1133061da546Spatrick bool IRForTarget::MaybeHandleVariable(Value *llvm_value_ptr) {
1134*f6aab3d8Srobert   lldb_private::Log *log(GetLog(LLDBLog::Expressions));
1135061da546Spatrick 
1136061da546Spatrick   LLDB_LOG(log, "MaybeHandleVariable ({0})", PrintValue(llvm_value_ptr));
1137061da546Spatrick 
1138061da546Spatrick   if (ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(llvm_value_ptr)) {
1139061da546Spatrick     switch (constant_expr->getOpcode()) {
1140061da546Spatrick     default:
1141061da546Spatrick       break;
1142061da546Spatrick     case Instruction::GetElementPtr:
1143061da546Spatrick     case Instruction::BitCast:
1144061da546Spatrick       Value *s = constant_expr->getOperand(0);
1145061da546Spatrick       if (!MaybeHandleVariable(s))
1146061da546Spatrick         return false;
1147061da546Spatrick     }
1148061da546Spatrick   } else if (GlobalVariable *global_variable =
1149061da546Spatrick                  dyn_cast<GlobalVariable>(llvm_value_ptr)) {
1150061da546Spatrick     if (!GlobalValue::isExternalLinkage(global_variable->getLinkage()))
1151061da546Spatrick       return true;
1152061da546Spatrick 
1153061da546Spatrick     clang::NamedDecl *named_decl = DeclForGlobal(global_variable);
1154061da546Spatrick 
1155061da546Spatrick     if (!named_decl) {
1156061da546Spatrick       if (IsObjCSelectorRef(llvm_value_ptr))
1157061da546Spatrick         return true;
1158061da546Spatrick 
1159061da546Spatrick       if (!global_variable->hasExternalLinkage())
1160061da546Spatrick         return true;
1161061da546Spatrick 
1162061da546Spatrick       LLDB_LOG(log, "Found global variable \"{0}\" without metadata",
1163061da546Spatrick                global_variable->getName());
1164061da546Spatrick 
1165061da546Spatrick       return false;
1166061da546Spatrick     }
1167061da546Spatrick 
1168061da546Spatrick     llvm::StringRef name(named_decl->getName());
1169061da546Spatrick 
1170061da546Spatrick     clang::ValueDecl *value_decl = dyn_cast<clang::ValueDecl>(named_decl);
1171061da546Spatrick     if (value_decl == nullptr)
1172061da546Spatrick       return false;
1173061da546Spatrick 
1174dda28197Spatrick     lldb_private::CompilerType compiler_type =
1175dda28197Spatrick         m_decl_map->GetTypeSystem()->GetType(value_decl->getType());
1176061da546Spatrick 
1177061da546Spatrick     const Type *value_type = nullptr;
1178061da546Spatrick 
1179061da546Spatrick     if (name.startswith("$")) {
1180061da546Spatrick       // The $__lldb_expr_result name indicates the return value has allocated
1181061da546Spatrick       // as a static variable.  Per the comment at
1182061da546Spatrick       // ASTResultSynthesizer::SynthesizeBodyResult, accesses to this static
1183061da546Spatrick       // variable need to be redirected to the result of dereferencing a
1184061da546Spatrick       // pointer that is passed in as one of the arguments.
1185061da546Spatrick       //
1186061da546Spatrick       // Consequently, when reporting the size of the type, we report a pointer
1187061da546Spatrick       // type pointing to the type of $__lldb_expr_result, not the type itself.
1188061da546Spatrick       //
1189061da546Spatrick       // We also do this for any user-declared persistent variables.
1190061da546Spatrick       compiler_type = compiler_type.GetPointerType();
1191061da546Spatrick       value_type = PointerType::get(global_variable->getType(), 0);
1192061da546Spatrick     } else {
1193061da546Spatrick       value_type = global_variable->getType();
1194061da546Spatrick     }
1195061da546Spatrick 
1196be691f3bSpatrick     auto *target = m_execution_unit.GetTarget().get();
1197*f6aab3d8Srobert     std::optional<uint64_t> value_size = compiler_type.GetByteSize(target);
1198061da546Spatrick     if (!value_size)
1199061da546Spatrick       return false;
1200*f6aab3d8Srobert     std::optional<size_t> opt_alignment = compiler_type.GetTypeBitAlign(target);
1201061da546Spatrick     if (!opt_alignment)
1202061da546Spatrick       return false;
1203061da546Spatrick     lldb::offset_t value_alignment = (*opt_alignment + 7ull) / 8ull;
1204061da546Spatrick 
1205061da546Spatrick     LLDB_LOG(log,
1206061da546Spatrick              "Type of \"{0}\" is [clang \"{1}\", llvm \"{2}\"] [size {3}, "
1207061da546Spatrick              "align {4}]",
1208061da546Spatrick              name,
1209061da546Spatrick              lldb_private::ClangUtil::GetQualType(compiler_type).getAsString(),
1210061da546Spatrick              PrintType(value_type), *value_size, value_alignment);
1211061da546Spatrick 
1212061da546Spatrick     if (named_decl)
1213061da546Spatrick       m_decl_map->AddValueToStruct(named_decl, lldb_private::ConstString(name),
1214061da546Spatrick                                    llvm_value_ptr, *value_size,
1215061da546Spatrick                                    value_alignment);
1216*f6aab3d8Srobert   } else if (isa<llvm::Function>(llvm_value_ptr)) {
1217061da546Spatrick     LLDB_LOG(log, "Function pointers aren't handled right now");
1218061da546Spatrick 
1219061da546Spatrick     return false;
1220061da546Spatrick   }
1221061da546Spatrick 
1222061da546Spatrick   return true;
1223061da546Spatrick }
1224061da546Spatrick 
1225061da546Spatrick // This function does not report errors; its callers are responsible.
HandleSymbol(Value * symbol)1226061da546Spatrick bool IRForTarget::HandleSymbol(Value *symbol) {
1227*f6aab3d8Srobert   lldb_private::Log *log(GetLog(LLDBLog::Expressions));
1228061da546Spatrick 
1229061da546Spatrick   lldb_private::ConstString name(symbol->getName().str().c_str());
1230061da546Spatrick 
1231061da546Spatrick   lldb::addr_t symbol_addr =
1232061da546Spatrick       m_decl_map->GetSymbolAddress(name, lldb::eSymbolTypeAny);
1233061da546Spatrick 
1234061da546Spatrick   if (symbol_addr == LLDB_INVALID_ADDRESS) {
1235061da546Spatrick     LLDB_LOG(log, "Symbol \"{0}\" had no address", name);
1236061da546Spatrick 
1237061da546Spatrick     return false;
1238061da546Spatrick   }
1239061da546Spatrick 
1240061da546Spatrick   LLDB_LOG(log, "Found \"{0}\" at {1}", name, symbol_addr);
1241061da546Spatrick 
1242061da546Spatrick   Type *symbol_type = symbol->getType();
1243061da546Spatrick 
1244061da546Spatrick   Constant *symbol_addr_int = ConstantInt::get(m_intptr_ty, symbol_addr, false);
1245061da546Spatrick 
1246061da546Spatrick   Value *symbol_addr_ptr =
1247061da546Spatrick       ConstantExpr::getIntToPtr(symbol_addr_int, symbol_type);
1248061da546Spatrick 
1249061da546Spatrick   LLDB_LOG(log, "Replacing {0} with {1}", PrintValue(symbol),
1250061da546Spatrick            PrintValue(symbol_addr_ptr));
1251061da546Spatrick 
1252061da546Spatrick   symbol->replaceAllUsesWith(symbol_addr_ptr);
1253061da546Spatrick 
1254061da546Spatrick   return true;
1255061da546Spatrick }
1256061da546Spatrick 
MaybeHandleCallArguments(CallInst * Old)1257061da546Spatrick bool IRForTarget::MaybeHandleCallArguments(CallInst *Old) {
1258*f6aab3d8Srobert   lldb_private::Log *log(GetLog(LLDBLog::Expressions));
1259061da546Spatrick 
1260061da546Spatrick   LLDB_LOG(log, "MaybeHandleCallArguments({0})", PrintValue(Old));
1261061da546Spatrick 
1262*f6aab3d8Srobert   for (unsigned op_index = 0, num_ops = Old->arg_size();
1263061da546Spatrick        op_index < num_ops; ++op_index)
1264061da546Spatrick     // conservatively believe that this is a store
1265061da546Spatrick     if (!MaybeHandleVariable(Old->getArgOperand(op_index))) {
1266061da546Spatrick       m_error_stream.Printf("Internal error [IRForTarget]: Couldn't rewrite "
1267061da546Spatrick                             "one of the arguments of a function call.\n");
1268061da546Spatrick 
1269061da546Spatrick       return false;
1270061da546Spatrick     }
1271061da546Spatrick 
1272061da546Spatrick   return true;
1273061da546Spatrick }
1274061da546Spatrick 
HandleObjCClass(Value * classlist_reference)1275061da546Spatrick bool IRForTarget::HandleObjCClass(Value *classlist_reference) {
1276*f6aab3d8Srobert   lldb_private::Log *log(GetLog(LLDBLog::Expressions));
1277061da546Spatrick 
1278061da546Spatrick   GlobalVariable *global_variable =
1279061da546Spatrick       dyn_cast<GlobalVariable>(classlist_reference);
1280061da546Spatrick 
1281061da546Spatrick   if (!global_variable)
1282061da546Spatrick     return false;
1283061da546Spatrick 
1284061da546Spatrick   Constant *initializer = global_variable->getInitializer();
1285061da546Spatrick 
1286061da546Spatrick   if (!initializer)
1287061da546Spatrick     return false;
1288061da546Spatrick 
1289061da546Spatrick   if (!initializer->hasName())
1290061da546Spatrick     return false;
1291061da546Spatrick 
1292061da546Spatrick   StringRef name(initializer->getName());
1293061da546Spatrick   lldb_private::ConstString name_cstr(name.str().c_str());
1294061da546Spatrick   lldb::addr_t class_ptr =
1295061da546Spatrick       m_decl_map->GetSymbolAddress(name_cstr, lldb::eSymbolTypeObjCClass);
1296061da546Spatrick 
1297061da546Spatrick   LLDB_LOG(log, "Found reference to Objective-C class {0} ({1})", name,
1298061da546Spatrick            (unsigned long long)class_ptr);
1299061da546Spatrick 
1300061da546Spatrick   if (class_ptr == LLDB_INVALID_ADDRESS)
1301061da546Spatrick     return false;
1302061da546Spatrick 
1303061da546Spatrick   if (global_variable->use_empty())
1304061da546Spatrick     return false;
1305061da546Spatrick 
1306061da546Spatrick   SmallVector<LoadInst *, 2> load_instructions;
1307061da546Spatrick 
1308061da546Spatrick   for (llvm::User *u : global_variable->users()) {
1309061da546Spatrick     if (LoadInst *load_instruction = dyn_cast<LoadInst>(u))
1310061da546Spatrick       load_instructions.push_back(load_instruction);
1311061da546Spatrick   }
1312061da546Spatrick 
1313061da546Spatrick   if (load_instructions.empty())
1314061da546Spatrick     return false;
1315061da546Spatrick 
1316061da546Spatrick   Constant *class_addr = ConstantInt::get(m_intptr_ty, (uint64_t)class_ptr);
1317061da546Spatrick 
1318061da546Spatrick   for (LoadInst *load_instruction : load_instructions) {
1319061da546Spatrick     Constant *class_bitcast =
1320061da546Spatrick         ConstantExpr::getIntToPtr(class_addr, load_instruction->getType());
1321061da546Spatrick 
1322061da546Spatrick     load_instruction->replaceAllUsesWith(class_bitcast);
1323061da546Spatrick 
1324061da546Spatrick     load_instruction->eraseFromParent();
1325061da546Spatrick   }
1326061da546Spatrick 
1327061da546Spatrick   return true;
1328061da546Spatrick }
1329061da546Spatrick 
RemoveCXAAtExit(BasicBlock & basic_block)1330061da546Spatrick bool IRForTarget::RemoveCXAAtExit(BasicBlock &basic_block) {
1331061da546Spatrick   std::vector<CallInst *> calls_to_remove;
1332061da546Spatrick 
1333061da546Spatrick   for (Instruction &inst : basic_block) {
1334061da546Spatrick     CallInst *call = dyn_cast<CallInst>(&inst);
1335061da546Spatrick 
1336061da546Spatrick     // MaybeHandleCallArguments handles error reporting; we are silent here
1337061da546Spatrick     if (!call)
1338061da546Spatrick       continue;
1339061da546Spatrick 
1340061da546Spatrick     bool remove = false;
1341061da546Spatrick 
1342061da546Spatrick     llvm::Function *func = call->getCalledFunction();
1343061da546Spatrick 
1344061da546Spatrick     if (func && func->getName() == "__cxa_atexit")
1345061da546Spatrick       remove = true;
1346061da546Spatrick 
1347dda28197Spatrick     llvm::Value *val = call->getCalledOperand();
1348061da546Spatrick 
1349061da546Spatrick     if (val && val->getName() == "__cxa_atexit")
1350061da546Spatrick       remove = true;
1351061da546Spatrick 
1352061da546Spatrick     if (remove)
1353061da546Spatrick       calls_to_remove.push_back(call);
1354061da546Spatrick   }
1355061da546Spatrick 
1356061da546Spatrick   for (CallInst *ci : calls_to_remove)
1357061da546Spatrick     ci->eraseFromParent();
1358061da546Spatrick 
1359061da546Spatrick   return true;
1360061da546Spatrick }
1361061da546Spatrick 
ResolveCalls(BasicBlock & basic_block)1362061da546Spatrick bool IRForTarget::ResolveCalls(BasicBlock &basic_block) {
1363061da546Spatrick   // Prepare the current basic block for execution in the remote process
1364061da546Spatrick 
1365061da546Spatrick   for (Instruction &inst : basic_block) {
1366061da546Spatrick     CallInst *call = dyn_cast<CallInst>(&inst);
1367061da546Spatrick 
1368061da546Spatrick     // MaybeHandleCallArguments handles error reporting; we are silent here
1369061da546Spatrick     if (call && !MaybeHandleCallArguments(call))
1370061da546Spatrick       return false;
1371061da546Spatrick   }
1372061da546Spatrick 
1373061da546Spatrick   return true;
1374061da546Spatrick }
1375061da546Spatrick 
ResolveExternals(Function & llvm_function)1376061da546Spatrick bool IRForTarget::ResolveExternals(Function &llvm_function) {
1377*f6aab3d8Srobert   lldb_private::Log *log(GetLog(LLDBLog::Expressions));
1378061da546Spatrick 
1379061da546Spatrick   for (GlobalVariable &global_var : m_module->globals()) {
1380061da546Spatrick     llvm::StringRef global_name = global_var.getName();
1381061da546Spatrick 
1382061da546Spatrick     LLDB_LOG(log, "Examining {0}, DeclForGlobalValue returns {1}", global_name,
1383061da546Spatrick              static_cast<void *>(DeclForGlobal(&global_var)));
1384061da546Spatrick 
1385061da546Spatrick     if (global_name.startswith("OBJC_IVAR")) {
1386061da546Spatrick       if (!HandleSymbol(&global_var)) {
1387061da546Spatrick         m_error_stream.Format("Error [IRForTarget]: Couldn't find Objective-C "
1388061da546Spatrick                               "indirect ivar symbol {0}\n",
1389061da546Spatrick                               global_name);
1390061da546Spatrick 
1391061da546Spatrick         return false;
1392061da546Spatrick       }
1393061da546Spatrick     } else if (global_name.contains("OBJC_CLASSLIST_REFERENCES_$")) {
1394061da546Spatrick       if (!HandleObjCClass(&global_var)) {
1395061da546Spatrick         m_error_stream.Printf("Error [IRForTarget]: Couldn't resolve the class "
1396061da546Spatrick                               "for an Objective-C static method call\n");
1397061da546Spatrick 
1398061da546Spatrick         return false;
1399061da546Spatrick       }
1400061da546Spatrick     } else if (global_name.contains("OBJC_CLASSLIST_SUP_REFS_$")) {
1401061da546Spatrick       if (!HandleObjCClass(&global_var)) {
1402061da546Spatrick         m_error_stream.Printf("Error [IRForTarget]: Couldn't resolve the class "
1403061da546Spatrick                               "for an Objective-C static method call\n");
1404061da546Spatrick 
1405061da546Spatrick         return false;
1406061da546Spatrick       }
1407061da546Spatrick     } else if (DeclForGlobal(&global_var)) {
1408061da546Spatrick       if (!MaybeHandleVariable(&global_var)) {
1409061da546Spatrick         m_error_stream.Format("Internal error [IRForTarget]: Couldn't rewrite "
1410061da546Spatrick                               "external variable {0}\n",
1411061da546Spatrick                               global_name);
1412061da546Spatrick 
1413061da546Spatrick         return false;
1414061da546Spatrick       }
1415061da546Spatrick     }
1416061da546Spatrick   }
1417061da546Spatrick 
1418061da546Spatrick   return true;
1419061da546Spatrick }
1420061da546Spatrick 
isGuardVariableRef(Value * V)1421061da546Spatrick static bool isGuardVariableRef(Value *V) {
1422061da546Spatrick   Constant *Old = dyn_cast<Constant>(V);
1423061da546Spatrick 
1424061da546Spatrick   if (!Old)
1425061da546Spatrick     return false;
1426061da546Spatrick 
1427061da546Spatrick   if (auto CE = dyn_cast<ConstantExpr>(V)) {
1428061da546Spatrick     if (CE->getOpcode() != Instruction::BitCast)
1429061da546Spatrick       return false;
1430061da546Spatrick 
1431061da546Spatrick     Old = CE->getOperand(0);
1432061da546Spatrick   }
1433061da546Spatrick 
1434061da546Spatrick   GlobalVariable *GV = dyn_cast<GlobalVariable>(Old);
1435061da546Spatrick 
1436061da546Spatrick   if (!GV || !GV->hasName() || !isGuardVariableSymbol(GV->getName()))
1437061da546Spatrick     return false;
1438061da546Spatrick 
1439061da546Spatrick   return true;
1440061da546Spatrick }
1441061da546Spatrick 
TurnGuardLoadIntoZero(llvm::Instruction * guard_load)1442061da546Spatrick void IRForTarget::TurnGuardLoadIntoZero(llvm::Instruction *guard_load) {
1443061da546Spatrick   Constant *zero(Constant::getNullValue(guard_load->getType()));
1444061da546Spatrick   guard_load->replaceAllUsesWith(zero);
1445061da546Spatrick   guard_load->eraseFromParent();
1446061da546Spatrick }
1447061da546Spatrick 
ExciseGuardStore(Instruction * guard_store)1448061da546Spatrick static void ExciseGuardStore(Instruction *guard_store) {
1449061da546Spatrick   guard_store->eraseFromParent();
1450061da546Spatrick }
1451061da546Spatrick 
RemoveGuards(BasicBlock & basic_block)1452061da546Spatrick bool IRForTarget::RemoveGuards(BasicBlock &basic_block) {
1453061da546Spatrick   // Eliminate any reference to guard variables found.
1454061da546Spatrick 
1455061da546Spatrick   InstrList guard_loads;
1456061da546Spatrick   InstrList guard_stores;
1457061da546Spatrick 
1458061da546Spatrick   for (Instruction &inst : basic_block) {
1459061da546Spatrick 
1460061da546Spatrick     if (LoadInst *load = dyn_cast<LoadInst>(&inst))
1461061da546Spatrick       if (isGuardVariableRef(load->getPointerOperand()))
1462061da546Spatrick         guard_loads.push_back(&inst);
1463061da546Spatrick 
1464061da546Spatrick     if (StoreInst *store = dyn_cast<StoreInst>(&inst))
1465061da546Spatrick       if (isGuardVariableRef(store->getPointerOperand()))
1466061da546Spatrick         guard_stores.push_back(&inst);
1467061da546Spatrick   }
1468061da546Spatrick 
1469061da546Spatrick   for (Instruction *inst : guard_loads)
1470061da546Spatrick     TurnGuardLoadIntoZero(inst);
1471061da546Spatrick 
1472061da546Spatrick   for (Instruction *inst : guard_stores)
1473061da546Spatrick     ExciseGuardStore(inst);
1474061da546Spatrick 
1475061da546Spatrick   return true;
1476061da546Spatrick }
1477061da546Spatrick 
1478061da546Spatrick // 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)1479061da546Spatrick bool IRForTarget::UnfoldConstant(Constant *old_constant,
1480061da546Spatrick                                  llvm::Function *llvm_function,
1481061da546Spatrick                                  FunctionValueCache &value_maker,
1482061da546Spatrick                                  FunctionValueCache &entry_instruction_finder,
1483061da546Spatrick                                  lldb_private::Stream &error_stream) {
1484061da546Spatrick   SmallVector<User *, 16> users;
1485061da546Spatrick 
1486061da546Spatrick   // We do this because the use list might change, invalidating our iterator.
1487061da546Spatrick   // Much better to keep a work list ourselves.
1488061da546Spatrick   for (llvm::User *u : old_constant->users())
1489061da546Spatrick     users.push_back(u);
1490061da546Spatrick 
1491061da546Spatrick   for (size_t i = 0; i < users.size(); ++i) {
1492061da546Spatrick     User *user = users[i];
1493061da546Spatrick 
1494061da546Spatrick     if (Constant *constant = dyn_cast<Constant>(user)) {
1495061da546Spatrick       // synthesize a new non-constant equivalent of the constant
1496061da546Spatrick 
1497061da546Spatrick       if (ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(constant)) {
1498061da546Spatrick         switch (constant_expr->getOpcode()) {
1499061da546Spatrick         default:
1500061da546Spatrick           error_stream.Printf("error [IRForTarget internal]: Unhandled "
1501061da546Spatrick                               "constant expression type: \"%s\"",
1502061da546Spatrick                               PrintValue(constant_expr).c_str());
1503061da546Spatrick           return false;
1504061da546Spatrick         case Instruction::BitCast: {
1505061da546Spatrick           FunctionValueCache bit_cast_maker(
1506061da546Spatrick               [&value_maker, &entry_instruction_finder, old_constant,
1507061da546Spatrick                constant_expr](llvm::Function *function) -> llvm::Value * {
1508061da546Spatrick                 // UnaryExpr
1509061da546Spatrick                 //   OperandList[0] is value
1510061da546Spatrick 
1511061da546Spatrick                 if (constant_expr->getOperand(0) != old_constant)
1512061da546Spatrick                   return constant_expr;
1513061da546Spatrick 
1514061da546Spatrick                 return new BitCastInst(
1515061da546Spatrick                     value_maker.GetValue(function), constant_expr->getType(),
1516061da546Spatrick                     "", llvm::cast<Instruction>(
1517061da546Spatrick                             entry_instruction_finder.GetValue(function)));
1518061da546Spatrick               });
1519061da546Spatrick 
1520061da546Spatrick           if (!UnfoldConstant(constant_expr, llvm_function, bit_cast_maker,
1521061da546Spatrick                               entry_instruction_finder, error_stream))
1522061da546Spatrick             return false;
1523061da546Spatrick         } break;
1524061da546Spatrick         case Instruction::GetElementPtr: {
1525061da546Spatrick           // GetElementPtrConstantExpr
1526061da546Spatrick           //   OperandList[0] is base
1527061da546Spatrick           //   OperandList[1]... are indices
1528061da546Spatrick 
1529061da546Spatrick           FunctionValueCache get_element_pointer_maker(
1530061da546Spatrick               [&value_maker, &entry_instruction_finder, old_constant,
1531061da546Spatrick                constant_expr](llvm::Function *function) -> llvm::Value * {
1532be691f3bSpatrick                 auto *gep = cast<llvm::GEPOperator>(constant_expr);
1533be691f3bSpatrick                 Value *ptr = gep->getPointerOperand();
1534061da546Spatrick 
1535061da546Spatrick                 if (ptr == old_constant)
1536061da546Spatrick                   ptr = value_maker.GetValue(function);
1537061da546Spatrick 
1538061da546Spatrick                 std::vector<Value *> index_vector;
1539be691f3bSpatrick                 for (Value *operand : gep->indices()) {
1540061da546Spatrick                   if (operand == old_constant)
1541061da546Spatrick                     operand = value_maker.GetValue(function);
1542061da546Spatrick 
1543061da546Spatrick                   index_vector.push_back(operand);
1544061da546Spatrick                 }
1545061da546Spatrick 
1546061da546Spatrick                 ArrayRef<Value *> indices(index_vector);
1547061da546Spatrick 
1548061da546Spatrick                 return GetElementPtrInst::Create(
1549be691f3bSpatrick                     gep->getSourceElementType(), ptr, indices, "",
1550061da546Spatrick                     llvm::cast<Instruction>(
1551061da546Spatrick                         entry_instruction_finder.GetValue(function)));
1552061da546Spatrick               });
1553061da546Spatrick 
1554061da546Spatrick           if (!UnfoldConstant(constant_expr, llvm_function,
1555061da546Spatrick                               get_element_pointer_maker,
1556061da546Spatrick                               entry_instruction_finder, error_stream))
1557061da546Spatrick             return false;
1558061da546Spatrick         } break;
1559061da546Spatrick         }
1560061da546Spatrick       } else {
1561061da546Spatrick         error_stream.Printf(
1562061da546Spatrick             "error [IRForTarget internal]: Unhandled constant type: \"%s\"",
1563061da546Spatrick             PrintValue(constant).c_str());
1564061da546Spatrick         return false;
1565061da546Spatrick       }
1566061da546Spatrick     } else {
1567061da546Spatrick       if (Instruction *inst = llvm::dyn_cast<Instruction>(user)) {
1568061da546Spatrick         if (llvm_function && inst->getParent()->getParent() != llvm_function) {
1569061da546Spatrick           error_stream.PutCString("error: Capturing non-local variables in "
1570061da546Spatrick                                   "expressions is unsupported.\n");
1571061da546Spatrick           return false;
1572061da546Spatrick         }
1573061da546Spatrick         inst->replaceUsesOfWith(
1574061da546Spatrick             old_constant, value_maker.GetValue(inst->getParent()->getParent()));
1575061da546Spatrick       } else {
1576061da546Spatrick         error_stream.Printf(
1577061da546Spatrick             "error [IRForTarget internal]: Unhandled non-constant type: \"%s\"",
1578061da546Spatrick             PrintValue(user).c_str());
1579061da546Spatrick         return false;
1580061da546Spatrick       }
1581061da546Spatrick     }
1582061da546Spatrick   }
1583061da546Spatrick 
1584061da546Spatrick   if (!isa<GlobalValue>(old_constant)) {
1585061da546Spatrick     old_constant->destroyConstant();
1586061da546Spatrick   }
1587061da546Spatrick 
1588061da546Spatrick   return true;
1589061da546Spatrick }
1590061da546Spatrick 
ReplaceVariables(Function & llvm_function)1591061da546Spatrick bool IRForTarget::ReplaceVariables(Function &llvm_function) {
1592061da546Spatrick   if (!m_resolve_vars)
1593061da546Spatrick     return true;
1594061da546Spatrick 
1595*f6aab3d8Srobert   lldb_private::Log *log(GetLog(LLDBLog::Expressions));
1596061da546Spatrick 
1597061da546Spatrick   m_decl_map->DoStructLayout();
1598061da546Spatrick 
1599061da546Spatrick   LLDB_LOG(log, "Element arrangement:");
1600061da546Spatrick 
1601061da546Spatrick   uint32_t num_elements;
1602061da546Spatrick   uint32_t element_index;
1603061da546Spatrick 
1604061da546Spatrick   size_t size;
1605061da546Spatrick   lldb::offset_t alignment;
1606061da546Spatrick 
1607061da546Spatrick   if (!m_decl_map->GetStructInfo(num_elements, size, alignment))
1608061da546Spatrick     return false;
1609061da546Spatrick 
1610061da546Spatrick   Function::arg_iterator iter(llvm_function.arg_begin());
1611061da546Spatrick 
1612061da546Spatrick   if (iter == llvm_function.arg_end()) {
1613061da546Spatrick     m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes no "
1614061da546Spatrick                           "arguments (should take at least a struct pointer)");
1615061da546Spatrick 
1616061da546Spatrick     return false;
1617061da546Spatrick   }
1618061da546Spatrick 
1619061da546Spatrick   Argument *argument = &*iter;
1620061da546Spatrick 
1621061da546Spatrick   if (argument->getName().equals("this")) {
1622061da546Spatrick     ++iter;
1623061da546Spatrick 
1624061da546Spatrick     if (iter == llvm_function.arg_end()) {
1625061da546Spatrick       m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes only "
1626061da546Spatrick                             "'this' argument (should take a struct pointer "
1627061da546Spatrick                             "too)");
1628061da546Spatrick 
1629061da546Spatrick       return false;
1630061da546Spatrick     }
1631061da546Spatrick 
1632061da546Spatrick     argument = &*iter;
1633061da546Spatrick   } else if (argument->getName().equals("self")) {
1634061da546Spatrick     ++iter;
1635061da546Spatrick 
1636061da546Spatrick     if (iter == llvm_function.arg_end()) {
1637061da546Spatrick       m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes only "
1638061da546Spatrick                             "'self' argument (should take '_cmd' and a struct "
1639061da546Spatrick                             "pointer too)");
1640061da546Spatrick 
1641061da546Spatrick       return false;
1642061da546Spatrick     }
1643061da546Spatrick 
1644061da546Spatrick     if (!iter->getName().equals("_cmd")) {
1645061da546Spatrick       m_error_stream.Format("Internal error [IRForTarget]: Wrapper takes '{0}' "
1646061da546Spatrick                             "after 'self' argument (should take '_cmd')",
1647061da546Spatrick                             iter->getName());
1648061da546Spatrick 
1649061da546Spatrick       return false;
1650061da546Spatrick     }
1651061da546Spatrick 
1652061da546Spatrick     ++iter;
1653061da546Spatrick 
1654061da546Spatrick     if (iter == llvm_function.arg_end()) {
1655061da546Spatrick       m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes only "
1656061da546Spatrick                             "'self' and '_cmd' arguments (should take a struct "
1657061da546Spatrick                             "pointer too)");
1658061da546Spatrick 
1659061da546Spatrick       return false;
1660061da546Spatrick     }
1661061da546Spatrick 
1662061da546Spatrick     argument = &*iter;
1663061da546Spatrick   }
1664061da546Spatrick 
1665061da546Spatrick   if (!argument->getName().equals("$__lldb_arg")) {
1666061da546Spatrick     m_error_stream.Format("Internal error [IRForTarget]: Wrapper takes an "
1667061da546Spatrick                           "argument named '{0}' instead of the struct pointer",
1668061da546Spatrick                           argument->getName());
1669061da546Spatrick 
1670061da546Spatrick     return false;
1671061da546Spatrick   }
1672061da546Spatrick 
1673061da546Spatrick   LLDB_LOG(log, "Arg: \"{0}\"", PrintValue(argument));
1674061da546Spatrick 
1675061da546Spatrick   BasicBlock &entry_block(llvm_function.getEntryBlock());
1676061da546Spatrick   Instruction *FirstEntryInstruction(entry_block.getFirstNonPHIOrDbg());
1677061da546Spatrick 
1678061da546Spatrick   if (!FirstEntryInstruction) {
1679061da546Spatrick     m_error_stream.Printf("Internal error [IRForTarget]: Couldn't find the "
1680061da546Spatrick                           "first instruction in the wrapper for use in "
1681061da546Spatrick                           "rewriting");
1682061da546Spatrick 
1683061da546Spatrick     return false;
1684061da546Spatrick   }
1685061da546Spatrick 
1686061da546Spatrick   LLVMContext &context(m_module->getContext());
1687061da546Spatrick   IntegerType *offset_type(Type::getInt32Ty(context));
1688061da546Spatrick 
1689061da546Spatrick   if (!offset_type) {
1690061da546Spatrick     m_error_stream.Printf(
1691061da546Spatrick         "Internal error [IRForTarget]: Couldn't produce an offset type");
1692061da546Spatrick 
1693061da546Spatrick     return false;
1694061da546Spatrick   }
1695061da546Spatrick 
1696061da546Spatrick   for (element_index = 0; element_index < num_elements; ++element_index) {
1697061da546Spatrick     const clang::NamedDecl *decl = nullptr;
1698061da546Spatrick     Value *value = nullptr;
1699061da546Spatrick     lldb::offset_t offset;
1700061da546Spatrick     lldb_private::ConstString name;
1701061da546Spatrick 
1702061da546Spatrick     if (!m_decl_map->GetStructElement(decl, value, offset, name,
1703061da546Spatrick                                       element_index)) {
1704061da546Spatrick       m_error_stream.Printf(
1705061da546Spatrick           "Internal error [IRForTarget]: Structure information is incomplete");
1706061da546Spatrick 
1707061da546Spatrick       return false;
1708061da546Spatrick     }
1709061da546Spatrick 
1710061da546Spatrick     LLDB_LOG(log, "  \"{0}\" (\"{1}\") placed at {2}", name,
1711061da546Spatrick              decl->getNameAsString(), offset);
1712061da546Spatrick 
1713061da546Spatrick     if (value) {
1714061da546Spatrick       LLDB_LOG(log, "    Replacing [{0}]", PrintValue(value));
1715061da546Spatrick 
1716061da546Spatrick       FunctionValueCache body_result_maker(
1717061da546Spatrick           [this, name, offset_type, offset, argument,
1718061da546Spatrick            value](llvm::Function *function) -> llvm::Value * {
1719061da546Spatrick             // Per the comment at ASTResultSynthesizer::SynthesizeBodyResult,
1720061da546Spatrick             // in cases where the result variable is an rvalue, we have to
1721061da546Spatrick             // synthesize a dereference of the appropriate structure entry in
1722061da546Spatrick             // order to produce the static variable that the AST thinks it is
1723061da546Spatrick             // accessing.
1724061da546Spatrick 
1725061da546Spatrick             llvm::Instruction *entry_instruction = llvm::cast<Instruction>(
1726061da546Spatrick                 m_entry_instruction_finder.GetValue(function));
1727061da546Spatrick 
1728*f6aab3d8Srobert             Type *int8Ty = Type::getInt8Ty(function->getContext());
1729061da546Spatrick             ConstantInt *offset_int(
1730061da546Spatrick                 ConstantInt::get(offset_type, offset, true));
1731061da546Spatrick             GetElementPtrInst *get_element_ptr = GetElementPtrInst::Create(
1732*f6aab3d8Srobert                 int8Ty, argument, offset_int, "", entry_instruction);
1733061da546Spatrick 
1734061da546Spatrick             if (name == m_result_name && !m_result_is_pointer) {
1735061da546Spatrick               BitCastInst *bit_cast = new BitCastInst(
1736061da546Spatrick                   get_element_ptr, value->getType()->getPointerTo(), "",
1737061da546Spatrick                   entry_instruction);
1738061da546Spatrick 
1739*f6aab3d8Srobert               LoadInst *load = new LoadInst(value->getType(), bit_cast, "",
1740*f6aab3d8Srobert                                             entry_instruction);
1741061da546Spatrick 
1742061da546Spatrick               return load;
1743061da546Spatrick             } else {
1744061da546Spatrick               BitCastInst *bit_cast = new BitCastInst(
1745061da546Spatrick                   get_element_ptr, value->getType(), "", entry_instruction);
1746061da546Spatrick 
1747061da546Spatrick               return bit_cast;
1748061da546Spatrick             }
1749061da546Spatrick           });
1750061da546Spatrick 
1751061da546Spatrick       if (Constant *constant = dyn_cast<Constant>(value)) {
1752061da546Spatrick         if (!UnfoldConstant(constant, &llvm_function, body_result_maker,
1753061da546Spatrick                             m_entry_instruction_finder, m_error_stream)) {
1754061da546Spatrick           return false;
1755061da546Spatrick         }
1756061da546Spatrick       } else if (Instruction *instruction = dyn_cast<Instruction>(value)) {
1757061da546Spatrick         if (instruction->getParent()->getParent() != &llvm_function) {
1758061da546Spatrick           m_error_stream.PutCString("error: Capturing non-local variables in "
1759061da546Spatrick                                     "expressions is unsupported.\n");
1760061da546Spatrick           return false;
1761061da546Spatrick         }
1762061da546Spatrick         value->replaceAllUsesWith(
1763061da546Spatrick             body_result_maker.GetValue(instruction->getParent()->getParent()));
1764061da546Spatrick       } else {
1765061da546Spatrick         LLDB_LOG(log, "Unhandled non-constant type: \"{0}\"",
1766061da546Spatrick                  PrintValue(value));
1767061da546Spatrick         return false;
1768061da546Spatrick       }
1769061da546Spatrick 
1770061da546Spatrick       if (GlobalVariable *var = dyn_cast<GlobalVariable>(value))
1771061da546Spatrick         var->eraseFromParent();
1772061da546Spatrick     }
1773061da546Spatrick   }
1774061da546Spatrick 
1775061da546Spatrick   LLDB_LOG(log, "Total structure [align {0}, size {1}]", (int64_t)alignment,
1776061da546Spatrick            (uint64_t)size);
1777061da546Spatrick 
1778061da546Spatrick   return true;
1779061da546Spatrick }
1780061da546Spatrick 
runOnModule(Module & llvm_module)1781061da546Spatrick bool IRForTarget::runOnModule(Module &llvm_module) {
1782*f6aab3d8Srobert   lldb_private::Log *log(GetLog(LLDBLog::Expressions));
1783061da546Spatrick 
1784061da546Spatrick   m_module = &llvm_module;
1785dda28197Spatrick   m_target_data = std::make_unique<DataLayout>(m_module);
1786061da546Spatrick   m_intptr_ty = llvm::Type::getIntNTy(m_module->getContext(),
1787061da546Spatrick                                       m_target_data->getPointerSizeInBits());
1788061da546Spatrick 
1789061da546Spatrick   if (log) {
1790061da546Spatrick     std::string s;
1791061da546Spatrick     raw_string_ostream oss(s);
1792061da546Spatrick 
1793061da546Spatrick     m_module->print(oss, nullptr);
1794061da546Spatrick 
1795061da546Spatrick     oss.flush();
1796061da546Spatrick 
1797061da546Spatrick     LLDB_LOG(log, "Module as passed in to IRForTarget: \n\"{0}\"", s);
1798061da546Spatrick   }
1799061da546Spatrick 
1800061da546Spatrick   Function *const main_function =
1801061da546Spatrick       m_func_name.IsEmpty() ? nullptr
1802061da546Spatrick                             : m_module->getFunction(m_func_name.GetStringRef());
1803061da546Spatrick 
1804061da546Spatrick   if (!m_func_name.IsEmpty() && !main_function) {
1805061da546Spatrick     LLDB_LOG(log, "Couldn't find \"{0}()\" in the module", m_func_name);
1806061da546Spatrick 
1807061da546Spatrick     m_error_stream.Format("Internal error [IRForTarget]: Couldn't find wrapper "
1808061da546Spatrick                           "'{0}' in the module",
1809061da546Spatrick                           m_func_name);
1810061da546Spatrick 
1811061da546Spatrick     return false;
1812061da546Spatrick   }
1813061da546Spatrick 
1814061da546Spatrick   if (main_function) {
1815061da546Spatrick     if (!FixFunctionLinkage(*main_function)) {
1816061da546Spatrick       LLDB_LOG(log, "Couldn't fix the linkage for the function");
1817061da546Spatrick 
1818061da546Spatrick       return false;
1819061da546Spatrick     }
1820061da546Spatrick   }
1821061da546Spatrick 
1822061da546Spatrick   llvm::Type *int8_ty = Type::getInt8Ty(m_module->getContext());
1823061da546Spatrick 
1824061da546Spatrick   m_reloc_placeholder = new llvm::GlobalVariable(
1825061da546Spatrick       (*m_module), int8_ty, false /* IsConstant */,
1826061da546Spatrick       GlobalVariable::InternalLinkage, Constant::getNullValue(int8_ty),
1827061da546Spatrick       "reloc_placeholder", nullptr /* InsertBefore */,
1828061da546Spatrick       GlobalVariable::NotThreadLocal /* ThreadLocal */, 0 /* AddressSpace */);
1829061da546Spatrick 
1830061da546Spatrick   ////////////////////////////////////////////////////////////
1831061da546Spatrick   // Replace $__lldb_expr_result with a persistent variable
1832061da546Spatrick   //
1833061da546Spatrick 
1834061da546Spatrick   if (main_function) {
1835061da546Spatrick     if (!CreateResultVariable(*main_function)) {
1836061da546Spatrick       LLDB_LOG(log, "CreateResultVariable() failed");
1837061da546Spatrick 
1838061da546Spatrick       // CreateResultVariable() reports its own errors, so we don't do so here
1839061da546Spatrick 
1840061da546Spatrick       return false;
1841061da546Spatrick     }
1842061da546Spatrick   }
1843061da546Spatrick 
1844061da546Spatrick   if (log && log->GetVerbose()) {
1845061da546Spatrick     std::string s;
1846061da546Spatrick     raw_string_ostream oss(s);
1847061da546Spatrick 
1848061da546Spatrick     m_module->print(oss, nullptr);
1849061da546Spatrick 
1850061da546Spatrick     oss.flush();
1851061da546Spatrick 
1852061da546Spatrick     LLDB_LOG(log, "Module after creating the result variable: \n\"{0}\"", s);
1853061da546Spatrick   }
1854061da546Spatrick 
1855061da546Spatrick   for (llvm::Function &function : *m_module) {
1856061da546Spatrick     for (BasicBlock &bb : function) {
1857061da546Spatrick       if (!RemoveGuards(bb)) {
1858061da546Spatrick         LLDB_LOG(log, "RemoveGuards() failed");
1859061da546Spatrick 
1860061da546Spatrick         // RemoveGuards() reports its own errors, so we don't do so here
1861061da546Spatrick 
1862061da546Spatrick         return false;
1863061da546Spatrick       }
1864061da546Spatrick 
1865061da546Spatrick       if (!RewritePersistentAllocs(bb)) {
1866061da546Spatrick         LLDB_LOG(log, "RewritePersistentAllocs() failed");
1867061da546Spatrick 
1868061da546Spatrick         // RewritePersistentAllocs() reports its own errors, so we don't do so
1869061da546Spatrick         // here
1870061da546Spatrick 
1871061da546Spatrick         return false;
1872061da546Spatrick       }
1873061da546Spatrick 
1874061da546Spatrick       if (!RemoveCXAAtExit(bb)) {
1875061da546Spatrick         LLDB_LOG(log, "RemoveCXAAtExit() failed");
1876061da546Spatrick 
1877061da546Spatrick         // RemoveCXAAtExit() reports its own errors, so we don't do so here
1878061da546Spatrick 
1879061da546Spatrick         return false;
1880061da546Spatrick       }
1881061da546Spatrick     }
1882061da546Spatrick   }
1883061da546Spatrick 
1884061da546Spatrick   ///////////////////////////////////////////////////////////////////////////////
1885061da546Spatrick   // Fix all Objective-C constant strings to use NSStringWithCString:encoding:
1886061da546Spatrick   //
1887061da546Spatrick 
1888061da546Spatrick   if (!RewriteObjCConstStrings()) {
1889061da546Spatrick     LLDB_LOG(log, "RewriteObjCConstStrings() failed");
1890061da546Spatrick 
1891061da546Spatrick     // RewriteObjCConstStrings() reports its own errors, so we don't do so here
1892061da546Spatrick 
1893061da546Spatrick     return false;
1894061da546Spatrick   }
1895061da546Spatrick 
1896061da546Spatrick   for (llvm::Function &function : *m_module) {
1897061da546Spatrick     for (llvm::BasicBlock &bb : function) {
1898061da546Spatrick       if (!RewriteObjCSelectors(bb)) {
1899061da546Spatrick         LLDB_LOG(log, "RewriteObjCSelectors() failed");
1900061da546Spatrick 
1901061da546Spatrick         // RewriteObjCSelectors() reports its own errors, so we don't do so
1902061da546Spatrick         // here
1903061da546Spatrick 
1904061da546Spatrick         return false;
1905061da546Spatrick       }
1906061da546Spatrick 
1907061da546Spatrick       if (!RewriteObjCClassReferences(bb)) {
1908061da546Spatrick         LLDB_LOG(log, "RewriteObjCClassReferences() failed");
1909061da546Spatrick 
1910061da546Spatrick         // RewriteObjCClasses() reports its own errors, so we don't do so here
1911061da546Spatrick 
1912061da546Spatrick         return false;
1913061da546Spatrick       }
1914061da546Spatrick     }
1915061da546Spatrick   }
1916061da546Spatrick 
1917061da546Spatrick   for (llvm::Function &function : *m_module) {
1918061da546Spatrick     for (BasicBlock &bb : function) {
1919061da546Spatrick       if (!ResolveCalls(bb)) {
1920061da546Spatrick         LLDB_LOG(log, "ResolveCalls() failed");
1921061da546Spatrick 
1922061da546Spatrick         // ResolveCalls() reports its own errors, so we don't do so here
1923061da546Spatrick 
1924061da546Spatrick         return false;
1925061da546Spatrick       }
1926061da546Spatrick     }
1927061da546Spatrick   }
1928061da546Spatrick 
1929061da546Spatrick   ////////////////////////////////////////////////////////////////////////
1930061da546Spatrick   // Run function-level passes that only make sense on the main function
1931061da546Spatrick   //
1932061da546Spatrick 
1933061da546Spatrick   if (main_function) {
1934061da546Spatrick     if (!ResolveExternals(*main_function)) {
1935061da546Spatrick       LLDB_LOG(log, "ResolveExternals() failed");
1936061da546Spatrick 
1937061da546Spatrick       // ResolveExternals() reports its own errors, so we don't do so here
1938061da546Spatrick 
1939061da546Spatrick       return false;
1940061da546Spatrick     }
1941061da546Spatrick 
1942061da546Spatrick     if (!ReplaceVariables(*main_function)) {
1943061da546Spatrick       LLDB_LOG(log, "ReplaceVariables() failed");
1944061da546Spatrick 
1945061da546Spatrick       // ReplaceVariables() reports its own errors, so we don't do so here
1946061da546Spatrick 
1947061da546Spatrick       return false;
1948061da546Spatrick     }
1949061da546Spatrick   }
1950061da546Spatrick 
1951061da546Spatrick   if (log && log->GetVerbose()) {
1952061da546Spatrick     std::string s;
1953061da546Spatrick     raw_string_ostream oss(s);
1954061da546Spatrick 
1955061da546Spatrick     m_module->print(oss, nullptr);
1956061da546Spatrick 
1957061da546Spatrick     oss.flush();
1958061da546Spatrick 
1959061da546Spatrick     LLDB_LOG(log, "Module after preparing for execution: \n\"{0}\"", s);
1960061da546Spatrick   }
1961061da546Spatrick 
1962061da546Spatrick   return true;
1963061da546Spatrick }
1964