Bug Summary

File:src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
Warning:line 809, column 8
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name IRForTarget.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/llvm/include -I /usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../include -I /usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/obj -I /usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/obj/../include -D NDEBUG -D __STDC_LIMIT_MACROS -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D LLVM_PREFIX="/usr" -I /usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/include -I /usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source -I /usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/clang/include -internal-isystem /usr/include/c++/v1 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-comment -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/obj -ferror-limit 19 -fvisibility-inlines-hidden -fwrapv -stack-protector 2 -fno-rtti -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c++ /usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp

/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp

1//===-- IRForTarget.cpp ---------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "IRForTarget.h"
10
11#include "ClangExpressionDeclMap.h"
12#include "ClangUtil.h"
13
14#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
15#include "llvm/IR/Constants.h"
16#include "llvm/IR/DataLayout.h"
17#include "llvm/IR/Operator.h"
18#include "llvm/IR/InstrTypes.h"
19#include "llvm/IR/Instructions.h"
20#include "llvm/IR/Intrinsics.h"
21#include "llvm/IR/LegacyPassManager.h"
22#include "llvm/IR/Metadata.h"
23#include "llvm/IR/Module.h"
24#include "llvm/IR/ValueSymbolTable.h"
25#include "llvm/Support/raw_ostream.h"
26#include "llvm/Transforms/IPO.h"
27
28#include "clang/AST/ASTContext.h"
29
30#include "lldb/Core/dwarf.h"
31#include "lldb/Expression/IRExecutionUnit.h"
32#include "lldb/Expression/IRInterpreter.h"
33#include "lldb/Symbol/CompilerType.h"
34#include "lldb/Utility/ConstString.h"
35#include "lldb/Utility/DataBufferHeap.h"
36#include "lldb/Utility/Endian.h"
37#include "lldb/Utility/Log.h"
38#include "lldb/Utility/Scalar.h"
39#include "lldb/Utility/StreamString.h"
40
41#include <map>
42
43using namespace llvm;
44
45typedef SmallVector<Instruction *, 2> InstrList;
46
47IRForTarget::FunctionValueCache::FunctionValueCache(Maker const &maker)
48 : m_maker(maker), m_values() {}
49
50IRForTarget::FunctionValueCache::~FunctionValueCache() = default;
51
52llvm::Value *
53IRForTarget::FunctionValueCache::GetValue(llvm::Function *function) {
54 if (!m_values.count(function)) {
55 llvm::Value *ret = m_maker(function);
56 m_values[function] = ret;
57 return ret;
58 }
59 return m_values[function];
60}
61
62static llvm::Value *FindEntryInstruction(llvm::Function *function) {
63 if (function->empty())
64 return nullptr;
65
66 return function->getEntryBlock().getFirstNonPHIOrDbg();
67}
68
69IRForTarget::IRForTarget(lldb_private::ClangExpressionDeclMap *decl_map,
70 bool resolve_vars,
71 lldb_private::IRExecutionUnit &execution_unit,
72 lldb_private::Stream &error_stream,
73 const char *func_name)
74 : m_resolve_vars(resolve_vars), m_func_name(func_name),
75 m_decl_map(decl_map), m_error_stream(error_stream),
76 m_execution_unit(execution_unit),
77 m_entry_instruction_finder(FindEntryInstruction) {}
78
79/* Handy utility functions used at several places in the code */
80
81static std::string PrintValue(const Value *value, bool truncate = false) {
82 std::string s;
83 if (value) {
84 raw_string_ostream rso(s);
85 value->print(rso);
86 rso.flush();
87 if (truncate)
88 s.resize(s.length() - 1);
89 }
90 return s;
91}
92
93static std::string PrintType(const llvm::Type *type, bool truncate = false) {
94 std::string s;
95 raw_string_ostream rso(s);
96 type->print(rso);
97 rso.flush();
98 if (truncate)
99 s.resize(s.length() - 1);
100 return s;
101}
102
103bool IRForTarget::FixFunctionLinkage(llvm::Function &llvm_function) {
104 llvm_function.setLinkage(GlobalValue::ExternalLinkage);
105
106 return true;
107}
108
109clang::NamedDecl *IRForTarget::DeclForGlobal(const GlobalValue *global_val,
110 Module *module) {
111 NamedMDNode *named_metadata =
112 module->getNamedMetadata("clang.global.decl.ptrs");
113
114 if (!named_metadata)
115 return nullptr;
116
117 unsigned num_nodes = named_metadata->getNumOperands();
118 unsigned node_index;
119
120 for (node_index = 0; node_index < num_nodes; ++node_index) {
121 llvm::MDNode *metadata_node =
122 dyn_cast<llvm::MDNode>(named_metadata->getOperand(node_index));
123 if (!metadata_node)
124 return nullptr;
125
126 if (metadata_node->getNumOperands() != 2)
127 continue;
128
129 if (mdconst::dyn_extract_or_null<GlobalValue>(
130 metadata_node->getOperand(0)) != global_val)
131 continue;
132
133 ConstantInt *constant_int =
134 mdconst::dyn_extract<ConstantInt>(metadata_node->getOperand(1));
135
136 if (!constant_int)
137 return nullptr;
138
139 uintptr_t ptr = constant_int->getZExtValue();
140
141 return reinterpret_cast<clang::NamedDecl *>(ptr);
142 }
143
144 return nullptr;
145}
146
147clang::NamedDecl *IRForTarget::DeclForGlobal(GlobalValue *global_val) {
148 return DeclForGlobal(global_val, m_module);
149}
150
151/// Returns true iff the mangled symbol is for a static guard variable.
152static bool isGuardVariableSymbol(llvm::StringRef mangled_symbol,
153 bool check_ms_abi = true) {
154 bool result = mangled_symbol.startswith("_ZGV"); // Itanium ABI guard variable
155 if (check_ms_abi)
156 result |= mangled_symbol.endswith("@4IA"); // Microsoft ABI
157 return result;
158}
159
160bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) {
161 lldb_private::Log *log(
162 lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS(1u << 8)));
163
164 if (!m_resolve_vars)
165 return true;
166
167 // Find the result variable. If it doesn't exist, we can give up right here.
168
169 ValueSymbolTable &value_symbol_table = m_module->getValueSymbolTable();
170
171 llvm::StringRef result_name;
172 bool found_result = false;
173
174 for (StringMapEntry<llvm::Value *> &value_symbol : value_symbol_table) {
175 result_name = value_symbol.first();
176
177 // Check if this is a guard variable. It seems this causes some hiccups
178 // on Windows, so let's only check for Itanium guard variables.
179 bool is_guard_var = isGuardVariableSymbol(result_name, /*MS ABI*/ false);
180
181 if (result_name.contains("$__lldb_expr_result_ptr") && !is_guard_var) {
182 found_result = true;
183 m_result_is_pointer = true;
184 break;
185 }
186
187 if (result_name.contains("$__lldb_expr_result") && !is_guard_var) {
188 found_result = true;
189 m_result_is_pointer = false;
190 break;
191 }
192 }
193
194 if (!found_result) {
195 LLDB_LOG(log, "Couldn't find result variable")do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Couldn't find result variable"); } while (0)
;
196
197 return true;
198 }
199
200 LLDB_LOG(log, "Result name: \"{0}\"", result_name)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Result name: \"{0}\"", result_name); } while (0)
;
201
202 Value *result_value = m_module->getNamedValue(result_name);
203
204 if (!result_value) {
205 LLDB_LOG(log, "Result variable had no data")do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Result variable had no data"); } while (0)
;
206
207 m_error_stream.Format("Internal error [IRForTarget]: Result variable's "
208 "name ({0}) exists, but not its definition\n",
209 result_name);
210
211 return false;
212 }
213
214 LLDB_LOG(log, "Found result in the IR: \"{0}\"",do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Found result in the IR: \"{0}\"", PrintValue(result_value
, false)); } while (0)
215 PrintValue(result_value, false))do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Found result in the IR: \"{0}\"", PrintValue(result_value
, false)); } while (0)
;
216
217 GlobalVariable *result_global = dyn_cast<GlobalVariable>(result_value);
218
219 if (!result_global) {
220 LLDB_LOG(log, "Result variable isn't a GlobalVariable")do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Result variable isn't a GlobalVariable"); } while
(0)
;
221
222 m_error_stream.Format("Internal error [IRForTarget]: Result variable ({0}) "
223 "is defined, but is not a global variable\n",
224 result_name);
225
226 return false;
227 }
228
229 clang::NamedDecl *result_decl = DeclForGlobal(result_global);
230 if (!result_decl) {
231 LLDB_LOG(log, "Result variable doesn't have a corresponding Decl")do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Result variable doesn't have a corresponding Decl"
); } while (0)
;
232
233 m_error_stream.Format("Internal error [IRForTarget]: Result variable ({0}) "
234 "does not have a corresponding Clang entity\n",
235 result_name);
236
237 return false;
238 }
239
240 if (log) {
241 std::string decl_desc_str;
242 raw_string_ostream decl_desc_stream(decl_desc_str);
243 result_decl->print(decl_desc_stream);
244 decl_desc_stream.flush();
245
246 LLDB_LOG(log, "Found result decl: \"{0}\"", decl_desc_str)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Found result decl: \"{0}\"", decl_desc_str); } while
(0)
;
247 }
248
249 clang::VarDecl *result_var = dyn_cast<clang::VarDecl>(result_decl);
250 if (!result_var) {
251 LLDB_LOG(log, "Result variable Decl isn't a VarDecl")do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Result variable Decl isn't a VarDecl"); } while (
0)
;
252
253 m_error_stream.Format("Internal error [IRForTarget]: Result variable "
254 "({0})'s corresponding Clang entity isn't a "
255 "variable\n",
256 result_name);
257
258 return false;
259 }
260
261 // Get the next available result name from m_decl_map and create the
262 // persistent variable for it
263
264 // If the result is an Lvalue, it is emitted as a pointer; see
265 // ASTResultSynthesizer::SynthesizeBodyResult.
266 if (m_result_is_pointer) {
267 clang::QualType pointer_qual_type = result_var->getType();
268 const clang::Type *pointer_type = pointer_qual_type.getTypePtr();
269
270 const clang::PointerType *pointer_pointertype =
271 pointer_type->getAs<clang::PointerType>();
272 const clang::ObjCObjectPointerType *pointer_objcobjpointertype =
273 pointer_type->getAs<clang::ObjCObjectPointerType>();
274
275 if (pointer_pointertype) {
276 clang::QualType element_qual_type = pointer_pointertype->getPointeeType();
277
278 m_result_type = lldb_private::TypeFromParser(
279 m_decl_map->GetTypeSystem()->GetType(element_qual_type));
280 } else if (pointer_objcobjpointertype) {
281 clang::QualType element_qual_type =
282 clang::QualType(pointer_objcobjpointertype->getObjectType(), 0);
283
284 m_result_type = lldb_private::TypeFromParser(
285 m_decl_map->GetTypeSystem()->GetType(element_qual_type));
286 } else {
287 LLDB_LOG(log, "Expected result to have pointer type, but it did not")do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Expected result to have pointer type, but it did not"
); } while (0)
;
288
289 m_error_stream.Format("Internal error [IRForTarget]: Lvalue result ({0}) "
290 "is not a pointer variable\n",
291 result_name);
292
293 return false;
294 }
295 } else {
296 m_result_type = lldb_private::TypeFromParser(
297 m_decl_map->GetTypeSystem()->GetType(result_var->getType()));
298 }
299
300 lldb::TargetSP target_sp(m_execution_unit.GetTarget());
301 llvm::Optional<uint64_t> bit_size = m_result_type.GetBitSize(target_sp.get());
302 if (!bit_size) {
303 lldb_private::StreamString type_desc_stream;
304 m_result_type.DumpTypeDescription(&type_desc_stream);
305
306 LLDB_LOG(log, "Result type has unknown size")do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Result type has unknown size"); } while (0)
;
307
308 m_error_stream.Printf("Error [IRForTarget]: Size of result type '%s' "
309 "couldn't be determined\n",
310 type_desc_stream.GetData());
311 return false;
312 }
313
314 if (log) {
315 lldb_private::StreamString type_desc_stream;
316 m_result_type.DumpTypeDescription(&type_desc_stream);
317
318 LLDB_LOG(log, "Result decl type: \"{0}\"", type_desc_stream.GetData())do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Result decl type: \"{0}\"", type_desc_stream.GetData
()); } while (0)
;
319 }
320
321 m_result_name = lldb_private::ConstString("$RESULT_NAME");
322
323 LLDB_LOG(log, "Creating a new result global: \"{0}\" with size {1}",do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Creating a new result global: \"{0}\" with size {1}"
, m_result_name, m_result_type.GetByteSize(target_sp.get()).getValueOr
(0)); } while (0)
324 m_result_name,do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Creating a new result global: \"{0}\" with size {1}"
, m_result_name, m_result_type.GetByteSize(target_sp.get()).getValueOr
(0)); } while (0)
325 m_result_type.GetByteSize(target_sp.get()).getValueOr(0))do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Creating a new result global: \"{0}\" with size {1}"
, m_result_name, m_result_type.GetByteSize(target_sp.get()).getValueOr
(0)); } while (0)
;
326
327 // Construct a new result global and set up its metadata
328
329 GlobalVariable *new_result_global = new GlobalVariable(
330 (*m_module), result_global->getType()->getElementType(),
331 false, /* not constant */
332 GlobalValue::ExternalLinkage, nullptr, /* no initializer */
333 m_result_name.GetCString());
334
335 // It's too late in compilation to create a new VarDecl for this, but we
336 // don't need to. We point the metadata at the old VarDecl. This creates an
337 // odd anomaly: a variable with a Value whose name is something like $0 and a
338 // Decl whose name is $__lldb_expr_result. This condition is handled in
339 // ClangExpressionDeclMap::DoMaterialize, and the name of the variable is
340 // fixed up.
341
342 ConstantInt *new_constant_int =
343 ConstantInt::get(llvm::Type::getInt64Ty(m_module->getContext()),
344 reinterpret_cast<uintptr_t>(result_decl), false);
345
346 llvm::Metadata *values[2];
347 values[0] = ConstantAsMetadata::get(new_result_global);
348 values[1] = ConstantAsMetadata::get(new_constant_int);
349
350 ArrayRef<Metadata *> value_ref(values, 2);
351
352 MDNode *persistent_global_md = MDNode::get(m_module->getContext(), value_ref);
353 NamedMDNode *named_metadata =
354 m_module->getNamedMetadata("clang.global.decl.ptrs");
355 named_metadata->addOperand(persistent_global_md);
356
357 LLDB_LOG(log, "Replacing \"{0}\" with \"{1}\"", PrintValue(result_global),do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Replacing \"{0}\" with \"{1}\"", PrintValue(result_global
), PrintValue(new_result_global)); } while (0)
358 PrintValue(new_result_global))do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Replacing \"{0}\" with \"{1}\"", PrintValue(result_global
), PrintValue(new_result_global)); } while (0)
;
359
360 if (result_global->use_empty()) {
361 // We need to synthesize a store for this variable, because otherwise
362 // there's nothing to put into its equivalent persistent variable.
363
364 BasicBlock &entry_block(llvm_function.getEntryBlock());
365 Instruction *first_entry_instruction(entry_block.getFirstNonPHIOrDbg());
366
367 if (!first_entry_instruction)
368 return false;
369
370 if (!result_global->hasInitializer()) {
371 LLDB_LOG(log, "Couldn't find initializer for unused variable")do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Couldn't find initializer for unused variable");
} while (0)
;
372
373 m_error_stream.Format("Internal error [IRForTarget]: Result variable "
374 "({0}) has no writes and no initializer\n",
375 result_name);
376
377 return false;
378 }
379
380 Constant *initializer = result_global->getInitializer();
381
382 StoreInst *synthesized_store =
383 new StoreInst(initializer, new_result_global, first_entry_instruction);
384
385 LLDB_LOG(log, "Synthesized result store \"{0}\"\n",do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Synthesized result store \"{0}\"\n", PrintValue(
synthesized_store)); } while (0)
386 PrintValue(synthesized_store))do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Synthesized result store \"{0}\"\n", PrintValue(
synthesized_store)); } while (0)
;
387 } else {
388 result_global->replaceAllUsesWith(new_result_global);
389 }
390
391 if (!m_decl_map->AddPersistentVariable(
392 result_decl, m_result_name, m_result_type, true, m_result_is_pointer))
393 return false;
394
395 result_global->eraseFromParent();
396
397 return true;
398}
399
400bool IRForTarget::RewriteObjCConstString(llvm::GlobalVariable *ns_str,
401 llvm::GlobalVariable *cstr) {
402 lldb_private::Log *log(
403 lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS(1u << 8)));
404
405 Type *ns_str_ty = ns_str->getType();
406
407 Type *i8_ptr_ty = Type::getInt8PtrTy(m_module->getContext());
408 Type *i32_ty = Type::getInt32Ty(m_module->getContext());
409 Type *i8_ty = Type::getInt8Ty(m_module->getContext());
410
411 if (!m_CFStringCreateWithBytes) {
412 lldb::addr_t CFStringCreateWithBytes_addr;
413
414 static lldb_private::ConstString g_CFStringCreateWithBytes_str(
415 "CFStringCreateWithBytes");
416
417 bool missing_weak = false;
418 CFStringCreateWithBytes_addr =
419 m_execution_unit.FindSymbol(g_CFStringCreateWithBytes_str,
420 missing_weak);
421 if (CFStringCreateWithBytes_addr == LLDB_INVALID_ADDRESS0xffffffffffffffffULL || missing_weak) {
422 LLDB_LOG(log, "Couldn't find CFStringCreateWithBytes in the target")do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Couldn't find CFStringCreateWithBytes in the target"
); } while (0)
;
423
424 m_error_stream.Printf("Error [IRForTarget]: Rewriting an Objective-C "
425 "constant string requires "
426 "CFStringCreateWithBytes\n");
427
428 return false;
429 }
430
431 LLDB_LOG(log, "Found CFStringCreateWithBytes at {0}",do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Found CFStringCreateWithBytes at {0}", CFStringCreateWithBytes_addr
); } while (0)
432 CFStringCreateWithBytes_addr)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Found CFStringCreateWithBytes at {0}", CFStringCreateWithBytes_addr
); } while (0)
;
433
434 // Build the function type:
435 //
436 // CFStringRef CFStringCreateWithBytes (
437 // CFAllocatorRef alloc,
438 // const UInt8 *bytes,
439 // CFIndex numBytes,
440 // CFStringEncoding encoding,
441 // Boolean isExternalRepresentation
442 // );
443 //
444 // We make the following substitutions:
445 //
446 // CFStringRef -> i8*
447 // CFAllocatorRef -> i8*
448 // UInt8 * -> i8*
449 // CFIndex -> long (i32 or i64, as appropriate; we ask the module for its
450 // pointer size for now) CFStringEncoding -> i32 Boolean -> i8
451
452 Type *arg_type_array[5];
453
454 arg_type_array[0] = i8_ptr_ty;
455 arg_type_array[1] = i8_ptr_ty;
456 arg_type_array[2] = m_intptr_ty;
457 arg_type_array[3] = i32_ty;
458 arg_type_array[4] = i8_ty;
459
460 ArrayRef<Type *> CFSCWB_arg_types(arg_type_array, 5);
461
462 llvm::FunctionType *CFSCWB_ty =
463 FunctionType::get(ns_str_ty, CFSCWB_arg_types, false);
464
465 // Build the constant containing the pointer to the function
466 PointerType *CFSCWB_ptr_ty = PointerType::getUnqual(CFSCWB_ty);
467 Constant *CFSCWB_addr_int =
468 ConstantInt::get(m_intptr_ty, CFStringCreateWithBytes_addr, false);
469 m_CFStringCreateWithBytes = {
470 CFSCWB_ty, ConstantExpr::getIntToPtr(CFSCWB_addr_int, CFSCWB_ptr_ty)};
471 }
472
473 ConstantDataSequential *string_array = nullptr;
474
475 if (cstr)
476 string_array = dyn_cast<ConstantDataSequential>(cstr->getInitializer());
477
478 Constant *alloc_arg = Constant::getNullValue(i8_ptr_ty);
479 Constant *bytes_arg = cstr ? ConstantExpr::getBitCast(cstr, i8_ptr_ty)
480 : Constant::getNullValue(i8_ptr_ty);
481 Constant *numBytes_arg = ConstantInt::get(
482 m_intptr_ty, cstr ? (string_array->getNumElements() - 1) * string_array->getElementByteSize() : 0, false);
483 int encoding_flags = 0;
484 switch (cstr ? string_array->getElementByteSize() : 1) {
485 case 1:
486 encoding_flags = 0x08000100; /* 0x08000100 is kCFStringEncodingUTF8 */
487 break;
488 case 2:
489 encoding_flags = 0x0100; /* 0x0100 is kCFStringEncodingUTF16 */
490 break;
491 case 4:
492 encoding_flags = 0x0c000100; /* 0x0c000100 is kCFStringEncodingUTF32 */
493 break;
494 default:
495 encoding_flags = 0x0600; /* fall back to 0x0600, kCFStringEncodingASCII */
496 LLDB_LOG(log, "Encountered an Objective-C constant string with unusual "do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Encountered an Objective-C constant string with unusual "
"element size {0}", string_array->getElementByteSize()); }
while (0)
497 "element size {0}",do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Encountered an Objective-C constant string with unusual "
"element size {0}", string_array->getElementByteSize()); }
while (0)
498 string_array->getElementByteSize())do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Encountered an Objective-C constant string with unusual "
"element size {0}", string_array->getElementByteSize()); }
while (0)
;
499 }
500 Constant *encoding_arg = ConstantInt::get(i32_ty, encoding_flags, false);
501 Constant *isExternal_arg =
502 ConstantInt::get(i8_ty, 0x0, false); /* 0x0 is false */
503
504 Value *argument_array[5];
505
506 argument_array[0] = alloc_arg;
507 argument_array[1] = bytes_arg;
508 argument_array[2] = numBytes_arg;
509 argument_array[3] = encoding_arg;
510 argument_array[4] = isExternal_arg;
511
512 ArrayRef<Value *> CFSCWB_arguments(argument_array, 5);
513
514 FunctionValueCache CFSCWB_Caller(
515 [this, &CFSCWB_arguments](llvm::Function *function) -> llvm::Value * {
516 return CallInst::Create(
517 m_CFStringCreateWithBytes, CFSCWB_arguments,
518 "CFStringCreateWithBytes",
519 llvm::cast<Instruction>(
520 m_entry_instruction_finder.GetValue(function)));
521 });
522
523 if (!UnfoldConstant(ns_str, nullptr, CFSCWB_Caller, m_entry_instruction_finder,
524 m_error_stream)) {
525 LLDB_LOG(log, "Couldn't replace the NSString with the result of the call")do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Couldn't replace the NSString with the result of the call"
); } while (0)
;
526
527 m_error_stream.Printf("error [IRForTarget internal]: Couldn't replace an "
528 "Objective-C constant string with a dynamic "
529 "string\n");
530
531 return false;
532 }
533
534 ns_str->eraseFromParent();
535
536 return true;
537}
538
539bool IRForTarget::RewriteObjCConstStrings() {
540 lldb_private::Log *log(
541 lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS(1u << 8)));
542
543 ValueSymbolTable &value_symbol_table = m_module->getValueSymbolTable();
544
545 for (StringMapEntry<llvm::Value *> &value_symbol : value_symbol_table) {
546 llvm::StringRef value_name = value_symbol.first();
547
548 if (value_name.contains("_unnamed_cfstring_")) {
549 Value *nsstring_value = value_symbol.second;
550
551 GlobalVariable *nsstring_global =
552 dyn_cast<GlobalVariable>(nsstring_value);
553
554 if (!nsstring_global) {
555 LLDB_LOG(log, "NSString variable is not a GlobalVariable")do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "NSString variable is not a GlobalVariable"); } while
(0)
;
556
557 m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C "
558 "constant string is not a global variable\n");
559
560 return false;
561 }
562
563 if (!nsstring_global->hasInitializer()) {
564 LLDB_LOG(log, "NSString variable does not have an initializer")do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "NSString variable does not have an initializer")
; } while (0)
;
565
566 m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C "
567 "constant string does not have an initializer\n");
568
569 return false;
570 }
571
572 ConstantStruct *nsstring_struct =
573 dyn_cast<ConstantStruct>(nsstring_global->getInitializer());
574
575 if (!nsstring_struct) {
576 LLDB_LOG(log,do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "NSString variable's initializer is not a ConstantStruct"
); } while (0)
577 "NSString variable's initializer is not a ConstantStruct")do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "NSString variable's initializer is not a ConstantStruct"
); } while (0)
;
578
579 m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C "
580 "constant string is not a structure constant\n");
581
582 return false;
583 }
584
585 // We expect the following structure:
586 //
587 // struct {
588 // int *isa;
589 // int flags;
590 // char *str;
591 // long length;
592 // };
593
594 if (nsstring_struct->getNumOperands() != 4) {
595
596 LLDB_LOG(log,do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "NSString variable's initializer structure has an "
"unexpected number of members. Should be 4, is {0}", nsstring_struct
->getNumOperands()); } while (0)
597 "NSString variable's initializer structure has an "do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "NSString variable's initializer structure has an "
"unexpected number of members. Should be 4, is {0}", nsstring_struct
->getNumOperands()); } while (0)
598 "unexpected number of members. Should be 4, is {0}",do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "NSString variable's initializer structure has an "
"unexpected number of members. Should be 4, is {0}", nsstring_struct
->getNumOperands()); } while (0)
599 nsstring_struct->getNumOperands())do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "NSString variable's initializer structure has an "
"unexpected number of members. Should be 4, is {0}", nsstring_struct
->getNumOperands()); } while (0)
;
600
601 m_error_stream.Printf("Internal error [IRForTarget]: The struct for an "
602 "Objective-C constant string is not as "
603 "expected\n");
604
605 return false;
606 }
607
608 Constant *nsstring_member = nsstring_struct->getOperand(2);
609
610 if (!nsstring_member) {
611 LLDB_LOG(log, "NSString initializer's str element was empty")do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "NSString initializer's str element was empty"); }
while (0)
;
612
613 m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C "
614 "constant string does not have a string "
615 "initializer\n");
616
617 return false;
618 }
619
620 ConstantExpr *nsstring_expr = dyn_cast<ConstantExpr>(nsstring_member);
621
622 if (!nsstring_expr) {
623 LLDB_LOG(log,do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "NSString initializer's str element is not a ConstantExpr"
); } while (0)
624 "NSString initializer's str element is not a ConstantExpr")do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "NSString initializer's str element is not a ConstantExpr"
); } while (0)
;
625
626 m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C "
627 "constant string's string initializer is not "
628 "constant\n");
629
630 return false;
631 }
632
633 GlobalVariable *cstr_global = nullptr;
634
635 if (nsstring_expr->getOpcode() == Instruction::GetElementPtr) {
636 Constant *nsstring_cstr = nsstring_expr->getOperand(0);
637 cstr_global = dyn_cast<GlobalVariable>(nsstring_cstr);
638 } else if (nsstring_expr->getOpcode() == Instruction::BitCast) {
639 Constant *nsstring_cstr = nsstring_expr->getOperand(0);
640 cstr_global = dyn_cast<GlobalVariable>(nsstring_cstr);
641 }
642
643 if (!cstr_global) {
644 LLDB_LOG(log,do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "NSString initializer's str element is not a GlobalVariable"
); } while (0)
645 "NSString initializer's str element is not a GlobalVariable")do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "NSString initializer's str element is not a GlobalVariable"
); } while (0)
;
646
647 m_error_stream.Printf("Internal error [IRForTarget]: Unhandled"
648 "constant string initializer\n");
649
650 return false;
651 }
652
653 if (!cstr_global->hasInitializer()) {
654 LLDB_LOG(log, "NSString initializer's str element does not have an "do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "NSString initializer's str element does not have an "
"initializer"); } while (0)
655 "initializer")do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "NSString initializer's str element does not have an "
"initializer"); } while (0)
;
656
657 m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C "
658 "constant string's string initializer doesn't "
659 "point to initialized data\n");
660
661 return false;
662 }
663
664 /*
665 if (!cstr_array)
666 {
667 if (log)
668 log->PutCString("NSString initializer's str element is not a
669 ConstantArray");
670
671 if (m_error_stream)
672 m_error_stream.Printf("Internal error [IRForTarget]: An
673 Objective-C constant string's string initializer doesn't point to an
674 array\n");
675
676 return false;
677 }
678
679 if (!cstr_array->isCString())
680 {
681 if (log)
682 log->PutCString("NSString initializer's str element is not a C
683 string array");
684
685 if (m_error_stream)
686 m_error_stream.Printf("Internal error [IRForTarget]: An
687 Objective-C constant string's string initializer doesn't point to a C
688 string\n");
689
690 return false;
691 }
692 */
693
694 ConstantDataArray *cstr_array =
695 dyn_cast<ConstantDataArray>(cstr_global->getInitializer());
696
697 if (cstr_array)
698 LLDB_LOG(log, "Found NSString constant {0}, which contains \"{1}\"",do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Found NSString constant {0}, which contains \"{1}\""
, value_name, cstr_array->getAsString()); } while (0)
699 value_name, cstr_array->getAsString())do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Found NSString constant {0}, which contains \"{1}\""
, value_name, cstr_array->getAsString()); } while (0)
;
700 else
701 LLDB_LOG(log, "Found NSString constant {0}, which contains \"\"",do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Found NSString constant {0}, which contains \"\""
, value_name); } while (0)
702 value_name)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Found NSString constant {0}, which contains \"\""
, value_name); } while (0)
;
703
704 if (!cstr_array)
705 cstr_global = nullptr;
706
707 if (!RewriteObjCConstString(nsstring_global, cstr_global)) {
708 LLDB_LOG(log, "Error rewriting the constant string")do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Error rewriting the constant string"); } while (
0)
;
709
710 // We don't print an error message here because RewriteObjCConstString
711 // has done so for us.
712
713 return false;
714 }
715 }
716 }
717
718 for (StringMapEntry<llvm::Value *> &value_symbol : value_symbol_table) {
719 llvm::StringRef value_name = value_symbol.first();
720
721 if (value_name == "__CFConstantStringClassReference") {
722 GlobalVariable *gv = dyn_cast<GlobalVariable>(value_symbol.second);
723
724 if (!gv) {
725 LLDB_LOG(log,do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "__CFConstantStringClassReference is not a global variable"
); } while (0)
726 "__CFConstantStringClassReference is not a global variable")do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "__CFConstantStringClassReference is not a global variable"
); } while (0)
;
727
728 m_error_stream.Printf("Internal error [IRForTarget]: Found a "
729 "CFConstantStringClassReference, but it is not a "
730 "global object\n");
731
732 return false;
733 }
734
735 gv->eraseFromParent();
736
737 break;
738 }
739 }
740
741 return true;
742}
743
744static bool IsObjCSelectorRef(Value *value) {
745 GlobalVariable *global_variable = dyn_cast<GlobalVariable>(value);
746
747 return !(!global_variable || !global_variable->hasName() ||
748 !global_variable->getName().startswith("OBJC_SELECTOR_REFERENCES_"));
749}
750
751// This function does not report errors; its callers are responsible.
752bool IRForTarget::RewriteObjCSelector(Instruction *selector_load) {
753 lldb_private::Log *log(
754 lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS(1u << 8)));
755
756 LoadInst *load = dyn_cast<LoadInst>(selector_load);
15
Assuming 'selector_load' is a 'LoadInst'
757
758 if (!load
15.1
'load' is non-null
15.1
'load' is non-null
)
16
Taking false branch
759 return false;
760
761 // Unpack the message name from the selector. In LLVM IR, an objc_msgSend
762 // gets represented as
763 //
764 // %tmp = load i8** @"OBJC_SELECTOR_REFERENCES_" ; <i8*> %call = call
765 // i8* (i8*, i8*, ...)* @objc_msgSend(i8* %obj, i8* %tmp, ...) ; <i8*>
766 //
767 // where %obj is the object pointer and %tmp is the selector.
768 //
769 // @"OBJC_SELECTOR_REFERENCES_" is a pointer to a character array called
770 // @"\01L_OBJC_llvm_moduleETH_VAR_NAllvm_moduleE_".
771 // @"\01L_OBJC_llvm_moduleETH_VAR_NAllvm_moduleE_" contains the string.
772
773 // Find the pointer's initializer (a ConstantExpr with opcode GetElementPtr)
774 // and get the string from its target
775
776 GlobalVariable *_objc_selector_references_ =
777 dyn_cast<GlobalVariable>(load->getPointerOperand());
17
Assuming the object is a 'GlobalVariable'
778
779 if (!_objc_selector_references_
17.1
'_objc_selector_references_' is non-null
17.1
'_objc_selector_references_' is non-null
||
22
Taking false branch
780 !_objc_selector_references_->hasInitializer())
18
Calling 'GlobalVariable::hasInitializer'
21
Returning from 'GlobalVariable::hasInitializer'
781 return false;
782
783 Constant *osr_initializer = _objc_selector_references_->getInitializer();
784
785 ConstantExpr *osr_initializer_expr = dyn_cast<ConstantExpr>(osr_initializer);
23
Assuming 'osr_initializer' is a 'ConstantExpr'
786
787 if (!osr_initializer_expr
23.1
'osr_initializer_expr' is non-null
23.1
'osr_initializer_expr' is non-null
||
25
Taking false branch
788 osr_initializer_expr->getOpcode() != Instruction::GetElementPtr)
24
Assuming the condition is false
789 return false;
790
791 Value *osr_initializer_base = osr_initializer_expr->getOperand(0);
792
793 if (!osr_initializer_base
25.1
'osr_initializer_base' is non-null
25.1
'osr_initializer_base' is non-null
)
26
Taking false branch
794 return false;
795
796 // Find the string's initializer (a ConstantArray) and get the string from it
797
798 GlobalVariable *_objc_meth_var_name_ =
799 dyn_cast<GlobalVariable>(osr_initializer_base);
27
Assuming 'osr_initializer_base' is a 'GlobalVariable'
800
801 if (!_objc_meth_var_name_
27.1
'_objc_meth_var_name_' is non-null
27.1
'_objc_meth_var_name_' is non-null
|| !_objc_meth_var_name_->hasInitializer())
28
Calling 'GlobalVariable::hasInitializer'
31
Returning from 'GlobalVariable::hasInitializer'
32
Taking false branch
802 return false;
803
804 Constant *omvn_initializer = _objc_meth_var_name_->getInitializer();
805
806 ConstantDataArray *omvn_initializer_array =
34
'omvn_initializer_array' initialized to a null pointer value
807 dyn_cast<ConstantDataArray>(omvn_initializer);
33
Assuming 'omvn_initializer' is not a 'ConstantDataArray'
808
809 if (!omvn_initializer_array->isString())
35
Called C++ object pointer is null
810 return false;
811
812 std::string omvn_initializer_string =
813 std::string(omvn_initializer_array->getAsString());
814
815 LLDB_LOG(log, "Found Objective-C selector reference \"{0}\"",do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Found Objective-C selector reference \"{0}\"", omvn_initializer_string
); } while (0)
816 omvn_initializer_string)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Found Objective-C selector reference \"{0}\"", omvn_initializer_string
); } while (0)
;
817
818 // Construct a call to sel_registerName
819
820 if (!m_sel_registerName) {
821 lldb::addr_t sel_registerName_addr;
822
823 bool missing_weak = false;
824 static lldb_private::ConstString g_sel_registerName_str("sel_registerName");
825 sel_registerName_addr = m_execution_unit.FindSymbol(g_sel_registerName_str,
826 missing_weak);
827 if (sel_registerName_addr == LLDB_INVALID_ADDRESS0xffffffffffffffffULL || missing_weak)
828 return false;
829
830 LLDB_LOG(log, "Found sel_registerName at {0}", sel_registerName_addr)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Found sel_registerName at {0}", sel_registerName_addr
); } while (0)
;
831
832 // Build the function type: struct objc_selector
833 // *sel_registerName(uint8_t*)
834
835 // The below code would be "more correct," but in actuality what's required
836 // is uint8_t*
837 // Type *sel_type = StructType::get(m_module->getContext());
838 // Type *sel_ptr_type = PointerType::getUnqual(sel_type);
839 Type *sel_ptr_type = Type::getInt8PtrTy(m_module->getContext());
840
841 Type *type_array[1];
842
843 type_array[0] = llvm::Type::getInt8PtrTy(m_module->getContext());
844
845 ArrayRef<Type *> srN_arg_types(type_array, 1);
846
847 llvm::FunctionType *srN_type =
848 FunctionType::get(sel_ptr_type, srN_arg_types, false);
849
850 // Build the constant containing the pointer to the function
851 PointerType *srN_ptr_ty = PointerType::getUnqual(srN_type);
852 Constant *srN_addr_int =
853 ConstantInt::get(m_intptr_ty, sel_registerName_addr, false);
854 m_sel_registerName = {srN_type,
855 ConstantExpr::getIntToPtr(srN_addr_int, srN_ptr_ty)};
856 }
857
858 Value *argument_array[1];
859
860 Constant *omvn_pointer = ConstantExpr::getBitCast(
861 _objc_meth_var_name_, Type::getInt8PtrTy(m_module->getContext()));
862
863 argument_array[0] = omvn_pointer;
864
865 ArrayRef<Value *> srN_arguments(argument_array, 1);
866
867 CallInst *srN_call = CallInst::Create(m_sel_registerName, srN_arguments,
868 "sel_registerName", selector_load);
869
870 // Replace the load with the call in all users
871
872 selector_load->replaceAllUsesWith(srN_call);
873
874 selector_load->eraseFromParent();
875
876 return true;
877}
878
879bool IRForTarget::RewriteObjCSelectors(BasicBlock &basic_block) {
880 lldb_private::Log *log(
881 lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS(1u << 8)));
882
883 InstrList selector_loads;
884
885 for (Instruction &inst : basic_block) {
886 if (LoadInst *load = dyn_cast<LoadInst>(&inst))
887 if (IsObjCSelectorRef(load->getPointerOperand()))
888 selector_loads.push_back(&inst);
889 }
890
891 for (Instruction *inst : selector_loads) {
13
Assuming '__begin1' is not equal to '__end1'
892 if (!RewriteObjCSelector(inst)) {
14
Calling 'IRForTarget::RewriteObjCSelector'
893 m_error_stream.Printf("Internal error [IRForTarget]: Couldn't change a "
894 "static reference to an Objective-C selector to a "
895 "dynamic reference\n");
896
897 LLDB_LOG(log, "Couldn't rewrite a reference to an Objective-C selector")do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Couldn't rewrite a reference to an Objective-C selector"
); } while (0)
;
898
899 return false;
900 }
901 }
902
903 return true;
904}
905
906static bool IsObjCClassReference(Value *value) {
907 GlobalVariable *global_variable = dyn_cast<GlobalVariable>(value);
908
909 return !(!global_variable || !global_variable->hasName() ||
910 !global_variable->getName().startswith("OBJC_CLASS_REFERENCES_"));
911}
912
913// This function does not report errors; its callers are responsible.
914bool IRForTarget::RewriteObjCClassReference(Instruction *class_load) {
915 lldb_private::Log *log(
916 lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS(1u << 8)));
917
918 LoadInst *load = dyn_cast<LoadInst>(class_load);
919
920 if (!load)
921 return false;
922
923 // Unpack the class name from the reference. In LLVM IR, a reference to an
924 // Objective-C class gets represented as
925 //
926 // %tmp = load %struct._objc_class*,
927 // %struct._objc_class** @OBJC_CLASS_REFERENCES_, align 4
928 //
929 // @"OBJC_CLASS_REFERENCES_ is a bitcast of a character array called
930 // @OBJC_CLASS_NAME_. @OBJC_CLASS_NAME contains the string.
931
932 // Find the pointer's initializer (a ConstantExpr with opcode BitCast) and
933 // get the string from its target
934
935 GlobalVariable *_objc_class_references_ =
936 dyn_cast<GlobalVariable>(load->getPointerOperand());
937
938 if (!_objc_class_references_ ||
939 !_objc_class_references_->hasInitializer())
940 return false;
941
942 Constant *ocr_initializer = _objc_class_references_->getInitializer();
943
944 ConstantExpr *ocr_initializer_expr = dyn_cast<ConstantExpr>(ocr_initializer);
945
946 if (!ocr_initializer_expr ||
947 ocr_initializer_expr->getOpcode() != Instruction::BitCast)
948 return false;
949
950 Value *ocr_initializer_base = ocr_initializer_expr->getOperand(0);
951
952 if (!ocr_initializer_base)
953 return false;
954
955 // Find the string's initializer (a ConstantArray) and get the string from it
956
957 GlobalVariable *_objc_class_name_ =
958 dyn_cast<GlobalVariable>(ocr_initializer_base);
959
960 if (!_objc_class_name_ || !_objc_class_name_->hasInitializer())
961 return false;
962
963 Constant *ocn_initializer = _objc_class_name_->getInitializer();
964
965 ConstantDataArray *ocn_initializer_array =
966 dyn_cast<ConstantDataArray>(ocn_initializer);
967
968 if (!ocn_initializer_array->isString())
969 return false;
970
971 std::string ocn_initializer_string =
972 std::string(ocn_initializer_array->getAsString());
973
974 LLDB_LOG(log, "Found Objective-C class reference \"{0}\"",do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Found Objective-C class reference \"{0}\"", ocn_initializer_string
); } while (0)
975 ocn_initializer_string)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Found Objective-C class reference \"{0}\"", ocn_initializer_string
); } while (0)
;
976
977 // Construct a call to objc_getClass
978
979 if (!m_objc_getClass) {
980 lldb::addr_t objc_getClass_addr;
981
982 bool missing_weak = false;
983 static lldb_private::ConstString g_objc_getClass_str("objc_getClass");
984 objc_getClass_addr = m_execution_unit.FindSymbol(g_objc_getClass_str,
985 missing_weak);
986 if (objc_getClass_addr == LLDB_INVALID_ADDRESS0xffffffffffffffffULL || missing_weak)
987 return false;
988
989 LLDB_LOG(log, "Found objc_getClass at {0}", objc_getClass_addr)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Found objc_getClass at {0}", objc_getClass_addr)
; } while (0)
;
990
991 // Build the function type: %struct._objc_class *objc_getClass(i8*)
992
993 Type *class_type = load->getType();
994 Type *type_array[1];
995 type_array[0] = llvm::Type::getInt8PtrTy(m_module->getContext());
996
997 ArrayRef<Type *> ogC_arg_types(type_array, 1);
998
999 llvm::FunctionType *ogC_type =
1000 FunctionType::get(class_type, ogC_arg_types, false);
1001
1002 // Build the constant containing the pointer to the function
1003 PointerType *ogC_ptr_ty = PointerType::getUnqual(ogC_type);
1004 Constant *ogC_addr_int =
1005 ConstantInt::get(m_intptr_ty, objc_getClass_addr, false);
1006 m_objc_getClass = {ogC_type,
1007 ConstantExpr::getIntToPtr(ogC_addr_int, ogC_ptr_ty)};
1008 }
1009
1010 Value *argument_array[1];
1011
1012 Constant *ocn_pointer = ConstantExpr::getBitCast(
1013 _objc_class_name_, Type::getInt8PtrTy(m_module->getContext()));
1014
1015 argument_array[0] = ocn_pointer;
1016
1017 ArrayRef<Value *> ogC_arguments(argument_array, 1);
1018
1019 CallInst *ogC_call = CallInst::Create(m_objc_getClass, ogC_arguments,
1020 "objc_getClass", class_load);
1021
1022 // Replace the load with the call in all users
1023
1024 class_load->replaceAllUsesWith(ogC_call);
1025
1026 class_load->eraseFromParent();
1027
1028 return true;
1029}
1030
1031bool IRForTarget::RewriteObjCClassReferences(BasicBlock &basic_block) {
1032 lldb_private::Log *log(
1033 lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS(1u << 8)));
1034
1035 InstrList class_loads;
1036
1037 for (Instruction &inst : basic_block) {
1038 if (LoadInst *load = dyn_cast<LoadInst>(&inst))
1039 if (IsObjCClassReference(load->getPointerOperand()))
1040 class_loads.push_back(&inst);
1041 }
1042
1043 for (Instruction *inst : class_loads) {
1044 if (!RewriteObjCClassReference(inst)) {
1045 m_error_stream.Printf("Internal error [IRForTarget]: Couldn't change a "
1046 "static reference to an Objective-C class to a "
1047 "dynamic reference\n");
1048
1049 LLDB_LOG(log, "Couldn't rewrite a reference to an Objective-C class")do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Couldn't rewrite a reference to an Objective-C class"
); } while (0)
;
1050
1051 return false;
1052 }
1053 }
1054
1055 return true;
1056}
1057
1058// This function does not report errors; its callers are responsible.
1059bool IRForTarget::RewritePersistentAlloc(llvm::Instruction *persistent_alloc) {
1060 lldb_private::Log *log(
1061 lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS(1u << 8)));
1062
1063 AllocaInst *alloc = dyn_cast<AllocaInst>(persistent_alloc);
1064
1065 MDNode *alloc_md = alloc->getMetadata("clang.decl.ptr");
1066
1067 if (!alloc_md || !alloc_md->getNumOperands())
1068 return false;
1069
1070 ConstantInt *constant_int =
1071 mdconst::dyn_extract<ConstantInt>(alloc_md->getOperand(0));
1072
1073 if (!constant_int)
1074 return false;
1075
1076 // We attempt to register this as a new persistent variable with the DeclMap.
1077
1078 uintptr_t ptr = constant_int->getZExtValue();
1079
1080 clang::VarDecl *decl = reinterpret_cast<clang::VarDecl *>(ptr);
1081
1082 lldb_private::TypeFromParser result_decl_type(
1083 m_decl_map->GetTypeSystem()->GetType(decl->getType()));
1084
1085 StringRef decl_name(decl->getName());
1086 lldb_private::ConstString persistent_variable_name(decl_name.data(),
1087 decl_name.size());
1088 if (!m_decl_map->AddPersistentVariable(decl, persistent_variable_name,
1089 result_decl_type, false, false))
1090 return false;
1091
1092 GlobalVariable *persistent_global = new GlobalVariable(
1093 (*m_module), alloc->getType(), false, /* not constant */
1094 GlobalValue::ExternalLinkage, nullptr, /* no initializer */
1095 alloc->getName().str());
1096
1097 // What we're going to do here is make believe this was a regular old
1098 // external variable. That means we need to make the metadata valid.
1099
1100 NamedMDNode *named_metadata =
1101 m_module->getOrInsertNamedMetadata("clang.global.decl.ptrs");
1102
1103 llvm::Metadata *values[2];
1104 values[0] = ConstantAsMetadata::get(persistent_global);
1105 values[1] = ConstantAsMetadata::get(constant_int);
1106
1107 ArrayRef<llvm::Metadata *> value_ref(values, 2);
1108
1109 MDNode *persistent_global_md = MDNode::get(m_module->getContext(), value_ref);
1110 named_metadata->addOperand(persistent_global_md);
1111
1112 // Now, since the variable is a pointer variable, we will drop in a load of
1113 // that pointer variable.
1114
1115 LoadInst *persistent_load =
1116 new LoadInst(persistent_global->getType()->getPointerElementType(),
1117 persistent_global, "", alloc);
1118
1119 LLDB_LOG(log, "Replacing \"{0}\" with \"{1}\"", PrintValue(alloc),do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Replacing \"{0}\" with \"{1}\"", PrintValue(alloc
), PrintValue(persistent_load)); } while (0)
1120 PrintValue(persistent_load))do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Replacing \"{0}\" with \"{1}\"", PrintValue(alloc
), PrintValue(persistent_load)); } while (0)
;
1121
1122 alloc->replaceAllUsesWith(persistent_load);
1123 alloc->eraseFromParent();
1124
1125 return true;
1126}
1127
1128bool IRForTarget::RewritePersistentAllocs(llvm::BasicBlock &basic_block) {
1129 if (!m_resolve_vars)
1130 return true;
1131
1132 lldb_private::Log *log(
1133 lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS(1u << 8)));
1134
1135 InstrList pvar_allocs;
1136
1137 for (Instruction &inst : basic_block) {
1138
1139 if (AllocaInst *alloc = dyn_cast<AllocaInst>(&inst)) {
1140 llvm::StringRef alloc_name = alloc->getName();
1141
1142 if (alloc_name.startswith("$") && !alloc_name.startswith("$__lldb")) {
1143 if (alloc_name.find_first_of("0123456789") == 1) {
1144 LLDB_LOG(log, "Rejecting a numeric persistent variable.")do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Rejecting a numeric persistent variable."); } while
(0)
;
1145
1146 m_error_stream.Printf("Error [IRForTarget]: Names starting with $0, "
1147 "$1, ... are reserved for use as result "
1148 "names\n");
1149
1150 return false;
1151 }
1152
1153 pvar_allocs.push_back(alloc);
1154 }
1155 }
1156 }
1157
1158 for (Instruction *inst : pvar_allocs) {
1159 if (!RewritePersistentAlloc(inst)) {
1160 m_error_stream.Printf("Internal error [IRForTarget]: Couldn't rewrite "
1161 "the creation of a persistent variable\n");
1162
1163 LLDB_LOG(log, "Couldn't rewrite the creation of a persistent variable")do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Couldn't rewrite the creation of a persistent variable"
); } while (0)
;
1164
1165 return false;
1166 }
1167 }
1168
1169 return true;
1170}
1171
1172// This function does not report errors; its callers are responsible.
1173bool IRForTarget::MaybeHandleVariable(Value *llvm_value_ptr) {
1174 lldb_private::Log *log(
1175 lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS(1u << 8)));
1176
1177 LLDB_LOG(log, "MaybeHandleVariable ({0})", PrintValue(llvm_value_ptr))do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "MaybeHandleVariable ({0})", PrintValue(llvm_value_ptr
)); } while (0)
;
1178
1179 if (ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(llvm_value_ptr)) {
1180 switch (constant_expr->getOpcode()) {
1181 default:
1182 break;
1183 case Instruction::GetElementPtr:
1184 case Instruction::BitCast:
1185 Value *s = constant_expr->getOperand(0);
1186 if (!MaybeHandleVariable(s))
1187 return false;
1188 }
1189 } else if (GlobalVariable *global_variable =
1190 dyn_cast<GlobalVariable>(llvm_value_ptr)) {
1191 if (!GlobalValue::isExternalLinkage(global_variable->getLinkage()))
1192 return true;
1193
1194 clang::NamedDecl *named_decl = DeclForGlobal(global_variable);
1195
1196 if (!named_decl) {
1197 if (IsObjCSelectorRef(llvm_value_ptr))
1198 return true;
1199
1200 if (!global_variable->hasExternalLinkage())
1201 return true;
1202
1203 LLDB_LOG(log, "Found global variable \"{0}\" without metadata",do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Found global variable \"{0}\" without metadata",
global_variable->getName()); } while (0)
1204 global_variable->getName())do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Found global variable \"{0}\" without metadata",
global_variable->getName()); } while (0)
;
1205
1206 return false;
1207 }
1208
1209 llvm::StringRef name(named_decl->getName());
1210
1211 clang::ValueDecl *value_decl = dyn_cast<clang::ValueDecl>(named_decl);
1212 if (value_decl == nullptr)
1213 return false;
1214
1215 lldb_private::CompilerType compiler_type =
1216 m_decl_map->GetTypeSystem()->GetType(value_decl->getType());
1217
1218 const Type *value_type = nullptr;
1219
1220 if (name.startswith("$")) {
1221 // The $__lldb_expr_result name indicates the return value has allocated
1222 // as a static variable. Per the comment at
1223 // ASTResultSynthesizer::SynthesizeBodyResult, accesses to this static
1224 // variable need to be redirected to the result of dereferencing a
1225 // pointer that is passed in as one of the arguments.
1226 //
1227 // Consequently, when reporting the size of the type, we report a pointer
1228 // type pointing to the type of $__lldb_expr_result, not the type itself.
1229 //
1230 // We also do this for any user-declared persistent variables.
1231 compiler_type = compiler_type.GetPointerType();
1232 value_type = PointerType::get(global_variable->getType(), 0);
1233 } else {
1234 value_type = global_variable->getType();
1235 }
1236
1237 auto *target = m_execution_unit.GetTarget().get();
1238 llvm::Optional<uint64_t> value_size = compiler_type.GetByteSize(target);
1239 if (!value_size)
1240 return false;
1241 llvm::Optional<size_t> opt_alignment =
1242 compiler_type.GetTypeBitAlign(target);
1243 if (!opt_alignment)
1244 return false;
1245 lldb::offset_t value_alignment = (*opt_alignment + 7ull) / 8ull;
1246
1247 LLDB_LOG(log,do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Type of \"{0}\" is [clang \"{1}\", llvm \"{2}\"] [size {3}, "
"align {4}]", name, lldb_private::ClangUtil::GetQualType(compiler_type
).getAsString(), PrintType(value_type), *value_size, value_alignment
); } while (0)
1248 "Type of \"{0}\" is [clang \"{1}\", llvm \"{2}\"] [size {3}, "do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Type of \"{0}\" is [clang \"{1}\", llvm \"{2}\"] [size {3}, "
"align {4}]", name, lldb_private::ClangUtil::GetQualType(compiler_type
).getAsString(), PrintType(value_type), *value_size, value_alignment
); } while (0)
1249 "align {4}]",do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Type of \"{0}\" is [clang \"{1}\", llvm \"{2}\"] [size {3}, "
"align {4}]", name, lldb_private::ClangUtil::GetQualType(compiler_type
).getAsString(), PrintType(value_type), *value_size, value_alignment
); } while (0)
1250 name,do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Type of \"{0}\" is [clang \"{1}\", llvm \"{2}\"] [size {3}, "
"align {4}]", name, lldb_private::ClangUtil::GetQualType(compiler_type
).getAsString(), PrintType(value_type), *value_size, value_alignment
); } while (0)
1251 lldb_private::ClangUtil::GetQualType(compiler_type).getAsString(),do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Type of \"{0}\" is [clang \"{1}\", llvm \"{2}\"] [size {3}, "
"align {4}]", name, lldb_private::ClangUtil::GetQualType(compiler_type
).getAsString(), PrintType(value_type), *value_size, value_alignment
); } while (0)
1252 PrintType(value_type), *value_size, value_alignment)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Type of \"{0}\" is [clang \"{1}\", llvm \"{2}\"] [size {3}, "
"align {4}]", name, lldb_private::ClangUtil::GetQualType(compiler_type
).getAsString(), PrintType(value_type), *value_size, value_alignment
); } while (0)
;
1253
1254 if (named_decl)
1255 m_decl_map->AddValueToStruct(named_decl, lldb_private::ConstString(name),
1256 llvm_value_ptr, *value_size,
1257 value_alignment);
1258 } else if (dyn_cast<llvm::Function>(llvm_value_ptr)) {
1259 LLDB_LOG(log, "Function pointers aren't handled right now")do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Function pointers aren't handled right now"); } while
(0)
;
1260
1261 return false;
1262 }
1263
1264 return true;
1265}
1266
1267// This function does not report errors; its callers are responsible.
1268bool IRForTarget::HandleSymbol(Value *symbol) {
1269 lldb_private::Log *log(
1270 lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS(1u << 8)));
1271
1272 lldb_private::ConstString name(symbol->getName().str().c_str());
1273
1274 lldb::addr_t symbol_addr =
1275 m_decl_map->GetSymbolAddress(name, lldb::eSymbolTypeAny);
1276
1277 if (symbol_addr == LLDB_INVALID_ADDRESS0xffffffffffffffffULL) {
1278 LLDB_LOG(log, "Symbol \"{0}\" had no address", name)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Symbol \"{0}\" had no address", name); } while (
0)
;
1279
1280 return false;
1281 }
1282
1283 LLDB_LOG(log, "Found \"{0}\" at {1}", name, symbol_addr)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Found \"{0}\" at {1}", name, symbol_addr); } while
(0)
;
1284
1285 Type *symbol_type = symbol->getType();
1286
1287 Constant *symbol_addr_int = ConstantInt::get(m_intptr_ty, symbol_addr, false);
1288
1289 Value *symbol_addr_ptr =
1290 ConstantExpr::getIntToPtr(symbol_addr_int, symbol_type);
1291
1292 LLDB_LOG(log, "Replacing {0} with {1}", PrintValue(symbol),do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Replacing {0} with {1}", PrintValue(symbol), PrintValue
(symbol_addr_ptr)); } while (0)
1293 PrintValue(symbol_addr_ptr))do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Replacing {0} with {1}", PrintValue(symbol), PrintValue
(symbol_addr_ptr)); } while (0)
;
1294
1295 symbol->replaceAllUsesWith(symbol_addr_ptr);
1296
1297 return true;
1298}
1299
1300bool IRForTarget::MaybeHandleCallArguments(CallInst *Old) {
1301 lldb_private::Log *log(
1302 lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS(1u << 8)));
1303
1304 LLDB_LOG(log, "MaybeHandleCallArguments({0})", PrintValue(Old))do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "MaybeHandleCallArguments({0})", PrintValue(Old))
; } while (0)
;
1305
1306 for (unsigned op_index = 0, num_ops = Old->getNumArgOperands();
1307 op_index < num_ops; ++op_index)
1308 // conservatively believe that this is a store
1309 if (!MaybeHandleVariable(Old->getArgOperand(op_index))) {
1310 m_error_stream.Printf("Internal error [IRForTarget]: Couldn't rewrite "
1311 "one of the arguments of a function call.\n");
1312
1313 return false;
1314 }
1315
1316 return true;
1317}
1318
1319bool IRForTarget::HandleObjCClass(Value *classlist_reference) {
1320 lldb_private::Log *log(
1321 lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS(1u << 8)));
1322
1323 GlobalVariable *global_variable =
1324 dyn_cast<GlobalVariable>(classlist_reference);
1325
1326 if (!global_variable)
1327 return false;
1328
1329 Constant *initializer = global_variable->getInitializer();
1330
1331 if (!initializer)
1332 return false;
1333
1334 if (!initializer->hasName())
1335 return false;
1336
1337 StringRef name(initializer->getName());
1338 lldb_private::ConstString name_cstr(name.str().c_str());
1339 lldb::addr_t class_ptr =
1340 m_decl_map->GetSymbolAddress(name_cstr, lldb::eSymbolTypeObjCClass);
1341
1342 LLDB_LOG(log, "Found reference to Objective-C class {0} ({1})", name,do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Found reference to Objective-C class {0} ({1})",
name, (unsigned long long)class_ptr); } while (0)
1343 (unsigned long long)class_ptr)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Found reference to Objective-C class {0} ({1})",
name, (unsigned long long)class_ptr); } while (0)
;
1344
1345 if (class_ptr == LLDB_INVALID_ADDRESS0xffffffffffffffffULL)
1346 return false;
1347
1348 if (global_variable->use_empty())
1349 return false;
1350
1351 SmallVector<LoadInst *, 2> load_instructions;
1352
1353 for (llvm::User *u : global_variable->users()) {
1354 if (LoadInst *load_instruction = dyn_cast<LoadInst>(u))
1355 load_instructions.push_back(load_instruction);
1356 }
1357
1358 if (load_instructions.empty())
1359 return false;
1360
1361 Constant *class_addr = ConstantInt::get(m_intptr_ty, (uint64_t)class_ptr);
1362
1363 for (LoadInst *load_instruction : load_instructions) {
1364 Constant *class_bitcast =
1365 ConstantExpr::getIntToPtr(class_addr, load_instruction->getType());
1366
1367 load_instruction->replaceAllUsesWith(class_bitcast);
1368
1369 load_instruction->eraseFromParent();
1370 }
1371
1372 return true;
1373}
1374
1375bool IRForTarget::RemoveCXAAtExit(BasicBlock &basic_block) {
1376 std::vector<CallInst *> calls_to_remove;
1377
1378 for (Instruction &inst : basic_block) {
1379 CallInst *call = dyn_cast<CallInst>(&inst);
1380
1381 // MaybeHandleCallArguments handles error reporting; we are silent here
1382 if (!call)
1383 continue;
1384
1385 bool remove = false;
1386
1387 llvm::Function *func = call->getCalledFunction();
1388
1389 if (func && func->getName() == "__cxa_atexit")
1390 remove = true;
1391
1392 llvm::Value *val = call->getCalledOperand();
1393
1394 if (val && val->getName() == "__cxa_atexit")
1395 remove = true;
1396
1397 if (remove)
1398 calls_to_remove.push_back(call);
1399 }
1400
1401 for (CallInst *ci : calls_to_remove)
1402 ci->eraseFromParent();
1403
1404 return true;
1405}
1406
1407bool IRForTarget::ResolveCalls(BasicBlock &basic_block) {
1408 // Prepare the current basic block for execution in the remote process
1409
1410 for (Instruction &inst : basic_block) {
1411 CallInst *call = dyn_cast<CallInst>(&inst);
1412
1413 // MaybeHandleCallArguments handles error reporting; we are silent here
1414 if (call && !MaybeHandleCallArguments(call))
1415 return false;
1416 }
1417
1418 return true;
1419}
1420
1421bool IRForTarget::ResolveExternals(Function &llvm_function) {
1422 lldb_private::Log *log(
1423 lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS(1u << 8)));
1424
1425 for (GlobalVariable &global_var : m_module->globals()) {
1426 llvm::StringRef global_name = global_var.getName();
1427
1428 LLDB_LOG(log, "Examining {0}, DeclForGlobalValue returns {1}", global_name,do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Examining {0}, DeclForGlobalValue returns {1}", global_name
, static_cast<void *>(DeclForGlobal(&global_var)));
} while (0)
1429 static_cast<void *>(DeclForGlobal(&global_var)))do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Examining {0}, DeclForGlobalValue returns {1}", global_name
, static_cast<void *>(DeclForGlobal(&global_var)));
} while (0)
;
1430
1431 if (global_name.startswith("OBJC_IVAR")) {
1432 if (!HandleSymbol(&global_var)) {
1433 m_error_stream.Format("Error [IRForTarget]: Couldn't find Objective-C "
1434 "indirect ivar symbol {0}\n",
1435 global_name);
1436
1437 return false;
1438 }
1439 } else if (global_name.contains("OBJC_CLASSLIST_REFERENCES_$")) {
1440 if (!HandleObjCClass(&global_var)) {
1441 m_error_stream.Printf("Error [IRForTarget]: Couldn't resolve the class "
1442 "for an Objective-C static method call\n");
1443
1444 return false;
1445 }
1446 } else if (global_name.contains("OBJC_CLASSLIST_SUP_REFS_$")) {
1447 if (!HandleObjCClass(&global_var)) {
1448 m_error_stream.Printf("Error [IRForTarget]: Couldn't resolve the class "
1449 "for an Objective-C static method call\n");
1450
1451 return false;
1452 }
1453 } else if (DeclForGlobal(&global_var)) {
1454 if (!MaybeHandleVariable(&global_var)) {
1455 m_error_stream.Format("Internal error [IRForTarget]: Couldn't rewrite "
1456 "external variable {0}\n",
1457 global_name);
1458
1459 return false;
1460 }
1461 }
1462 }
1463
1464 return true;
1465}
1466
1467static bool isGuardVariableRef(Value *V) {
1468 Constant *Old = dyn_cast<Constant>(V);
1469
1470 if (!Old)
1471 return false;
1472
1473 if (auto CE = dyn_cast<ConstantExpr>(V)) {
1474 if (CE->getOpcode() != Instruction::BitCast)
1475 return false;
1476
1477 Old = CE->getOperand(0);
1478 }
1479
1480 GlobalVariable *GV = dyn_cast<GlobalVariable>(Old);
1481
1482 if (!GV || !GV->hasName() || !isGuardVariableSymbol(GV->getName()))
1483 return false;
1484
1485 return true;
1486}
1487
1488void IRForTarget::TurnGuardLoadIntoZero(llvm::Instruction *guard_load) {
1489 Constant *zero(Constant::getNullValue(guard_load->getType()));
1490 guard_load->replaceAllUsesWith(zero);
1491 guard_load->eraseFromParent();
1492}
1493
1494static void ExciseGuardStore(Instruction *guard_store) {
1495 guard_store->eraseFromParent();
1496}
1497
1498bool IRForTarget::RemoveGuards(BasicBlock &basic_block) {
1499 // Eliminate any reference to guard variables found.
1500
1501 InstrList guard_loads;
1502 InstrList guard_stores;
1503
1504 for (Instruction &inst : basic_block) {
1505
1506 if (LoadInst *load = dyn_cast<LoadInst>(&inst))
1507 if (isGuardVariableRef(load->getPointerOperand()))
1508 guard_loads.push_back(&inst);
1509
1510 if (StoreInst *store = dyn_cast<StoreInst>(&inst))
1511 if (isGuardVariableRef(store->getPointerOperand()))
1512 guard_stores.push_back(&inst);
1513 }
1514
1515 for (Instruction *inst : guard_loads)
1516 TurnGuardLoadIntoZero(inst);
1517
1518 for (Instruction *inst : guard_stores)
1519 ExciseGuardStore(inst);
1520
1521 return true;
1522}
1523
1524// This function does not report errors; its callers are responsible.
1525bool IRForTarget::UnfoldConstant(Constant *old_constant,
1526 llvm::Function *llvm_function,
1527 FunctionValueCache &value_maker,
1528 FunctionValueCache &entry_instruction_finder,
1529 lldb_private::Stream &error_stream) {
1530 SmallVector<User *, 16> users;
1531
1532 // We do this because the use list might change, invalidating our iterator.
1533 // Much better to keep a work list ourselves.
1534 for (llvm::User *u : old_constant->users())
1535 users.push_back(u);
1536
1537 for (size_t i = 0; i < users.size(); ++i) {
1538 User *user = users[i];
1539
1540 if (Constant *constant = dyn_cast<Constant>(user)) {
1541 // synthesize a new non-constant equivalent of the constant
1542
1543 if (ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(constant)) {
1544 switch (constant_expr->getOpcode()) {
1545 default:
1546 error_stream.Printf("error [IRForTarget internal]: Unhandled "
1547 "constant expression type: \"%s\"",
1548 PrintValue(constant_expr).c_str());
1549 return false;
1550 case Instruction::BitCast: {
1551 FunctionValueCache bit_cast_maker(
1552 [&value_maker, &entry_instruction_finder, old_constant,
1553 constant_expr](llvm::Function *function) -> llvm::Value * {
1554 // UnaryExpr
1555 // OperandList[0] is value
1556
1557 if (constant_expr->getOperand(0) != old_constant)
1558 return constant_expr;
1559
1560 return new BitCastInst(
1561 value_maker.GetValue(function), constant_expr->getType(),
1562 "", llvm::cast<Instruction>(
1563 entry_instruction_finder.GetValue(function)));
1564 });
1565
1566 if (!UnfoldConstant(constant_expr, llvm_function, bit_cast_maker,
1567 entry_instruction_finder, error_stream))
1568 return false;
1569 } break;
1570 case Instruction::GetElementPtr: {
1571 // GetElementPtrConstantExpr
1572 // OperandList[0] is base
1573 // OperandList[1]... are indices
1574
1575 FunctionValueCache get_element_pointer_maker(
1576 [&value_maker, &entry_instruction_finder, old_constant,
1577 constant_expr](llvm::Function *function) -> llvm::Value * {
1578 auto *gep = cast<llvm::GEPOperator>(constant_expr);
1579 Value *ptr = gep->getPointerOperand();
1580
1581 if (ptr == old_constant)
1582 ptr = value_maker.GetValue(function);
1583
1584 std::vector<Value *> index_vector;
1585 for (Value *operand : gep->indices()) {
1586 if (operand == old_constant)
1587 operand = value_maker.GetValue(function);
1588
1589 index_vector.push_back(operand);
1590 }
1591
1592 ArrayRef<Value *> indices(index_vector);
1593
1594 return GetElementPtrInst::Create(
1595 gep->getSourceElementType(), ptr, indices, "",
1596 llvm::cast<Instruction>(
1597 entry_instruction_finder.GetValue(function)));
1598 });
1599
1600 if (!UnfoldConstant(constant_expr, llvm_function,
1601 get_element_pointer_maker,
1602 entry_instruction_finder, error_stream))
1603 return false;
1604 } break;
1605 }
1606 } else {
1607 error_stream.Printf(
1608 "error [IRForTarget internal]: Unhandled constant type: \"%s\"",
1609 PrintValue(constant).c_str());
1610 return false;
1611 }
1612 } else {
1613 if (Instruction *inst = llvm::dyn_cast<Instruction>(user)) {
1614 if (llvm_function && inst->getParent()->getParent() != llvm_function) {
1615 error_stream.PutCString("error: Capturing non-local variables in "
1616 "expressions is unsupported.\n");
1617 return false;
1618 }
1619 inst->replaceUsesOfWith(
1620 old_constant, value_maker.GetValue(inst->getParent()->getParent()));
1621 } else {
1622 error_stream.Printf(
1623 "error [IRForTarget internal]: Unhandled non-constant type: \"%s\"",
1624 PrintValue(user).c_str());
1625 return false;
1626 }
1627 }
1628 }
1629
1630 if (!isa<GlobalValue>(old_constant)) {
1631 old_constant->destroyConstant();
1632 }
1633
1634 return true;
1635}
1636
1637bool IRForTarget::ReplaceVariables(Function &llvm_function) {
1638 if (!m_resolve_vars)
1639 return true;
1640
1641 lldb_private::Log *log(
1642 lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS(1u << 8)));
1643
1644 m_decl_map->DoStructLayout();
1645
1646 LLDB_LOG(log, "Element arrangement:")do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Element arrangement:"); } while (0)
;
1647
1648 uint32_t num_elements;
1649 uint32_t element_index;
1650
1651 size_t size;
1652 lldb::offset_t alignment;
1653
1654 if (!m_decl_map->GetStructInfo(num_elements, size, alignment))
1655 return false;
1656
1657 Function::arg_iterator iter(llvm_function.arg_begin());
1658
1659 if (iter == llvm_function.arg_end()) {
1660 m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes no "
1661 "arguments (should take at least a struct pointer)");
1662
1663 return false;
1664 }
1665
1666 Argument *argument = &*iter;
1667
1668 if (argument->getName().equals("this")) {
1669 ++iter;
1670
1671 if (iter == llvm_function.arg_end()) {
1672 m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes only "
1673 "'this' argument (should take a struct pointer "
1674 "too)");
1675
1676 return false;
1677 }
1678
1679 argument = &*iter;
1680 } else if (argument->getName().equals("self")) {
1681 ++iter;
1682
1683 if (iter == llvm_function.arg_end()) {
1684 m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes only "
1685 "'self' argument (should take '_cmd' and a struct "
1686 "pointer too)");
1687
1688 return false;
1689 }
1690
1691 if (!iter->getName().equals("_cmd")) {
1692 m_error_stream.Format("Internal error [IRForTarget]: Wrapper takes '{0}' "
1693 "after 'self' argument (should take '_cmd')",
1694 iter->getName());
1695
1696 return false;
1697 }
1698
1699 ++iter;
1700
1701 if (iter == llvm_function.arg_end()) {
1702 m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes only "
1703 "'self' and '_cmd' arguments (should take a struct "
1704 "pointer too)");
1705
1706 return false;
1707 }
1708
1709 argument = &*iter;
1710 }
1711
1712 if (!argument->getName().equals("$__lldb_arg")) {
1713 m_error_stream.Format("Internal error [IRForTarget]: Wrapper takes an "
1714 "argument named '{0}' instead of the struct pointer",
1715 argument->getName());
1716
1717 return false;
1718 }
1719
1720 LLDB_LOG(log, "Arg: \"{0}\"", PrintValue(argument))do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Arg: \"{0}\"", PrintValue(argument)); } while (0
)
;
1721
1722 BasicBlock &entry_block(llvm_function.getEntryBlock());
1723 Instruction *FirstEntryInstruction(entry_block.getFirstNonPHIOrDbg());
1724
1725 if (!FirstEntryInstruction) {
1726 m_error_stream.Printf("Internal error [IRForTarget]: Couldn't find the "
1727 "first instruction in the wrapper for use in "
1728 "rewriting");
1729
1730 return false;
1731 }
1732
1733 LLVMContext &context(m_module->getContext());
1734 IntegerType *offset_type(Type::getInt32Ty(context));
1735
1736 if (!offset_type) {
1737 m_error_stream.Printf(
1738 "Internal error [IRForTarget]: Couldn't produce an offset type");
1739
1740 return false;
1741 }
1742
1743 for (element_index = 0; element_index < num_elements; ++element_index) {
1744 const clang::NamedDecl *decl = nullptr;
1745 Value *value = nullptr;
1746 lldb::offset_t offset;
1747 lldb_private::ConstString name;
1748
1749 if (!m_decl_map->GetStructElement(decl, value, offset, name,
1750 element_index)) {
1751 m_error_stream.Printf(
1752 "Internal error [IRForTarget]: Structure information is incomplete");
1753
1754 return false;
1755 }
1756
1757 LLDB_LOG(log, " \"{0}\" (\"{1}\") placed at {2}", name,do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, " \"{0}\" (\"{1}\") placed at {2}", name, decl->
getNameAsString(), offset); } while (0)
1758 decl->getNameAsString(), offset)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, " \"{0}\" (\"{1}\") placed at {2}", name, decl->
getNameAsString(), offset); } while (0)
;
1759
1760 if (value) {
1761 LLDB_LOG(log, " Replacing [{0}]", PrintValue(value))do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, " Replacing [{0}]", PrintValue(value)); } while
(0)
;
1762
1763 FunctionValueCache body_result_maker(
1764 [this, name, offset_type, offset, argument,
1765 value](llvm::Function *function) -> llvm::Value * {
1766 // Per the comment at ASTResultSynthesizer::SynthesizeBodyResult,
1767 // in cases where the result variable is an rvalue, we have to
1768 // synthesize a dereference of the appropriate structure entry in
1769 // order to produce the static variable that the AST thinks it is
1770 // accessing.
1771
1772 llvm::Instruction *entry_instruction = llvm::cast<Instruction>(
1773 m_entry_instruction_finder.GetValue(function));
1774
1775 ConstantInt *offset_int(
1776 ConstantInt::get(offset_type, offset, true));
1777 GetElementPtrInst *get_element_ptr = GetElementPtrInst::Create(
1778 argument->getType()->getPointerElementType(), argument,
1779 offset_int, "", entry_instruction);
1780
1781 if (name == m_result_name && !m_result_is_pointer) {
1782 BitCastInst *bit_cast = new BitCastInst(
1783 get_element_ptr, value->getType()->getPointerTo(), "",
1784 entry_instruction);
1785
1786 LoadInst *load =
1787 new LoadInst(bit_cast->getType()->getPointerElementType(),
1788 bit_cast, "", entry_instruction);
1789
1790 return load;
1791 } else {
1792 BitCastInst *bit_cast = new BitCastInst(
1793 get_element_ptr, value->getType(), "", entry_instruction);
1794
1795 return bit_cast;
1796 }
1797 });
1798
1799 if (Constant *constant = dyn_cast<Constant>(value)) {
1800 if (!UnfoldConstant(constant, &llvm_function, body_result_maker,
1801 m_entry_instruction_finder, m_error_stream)) {
1802 return false;
1803 }
1804 } else if (Instruction *instruction = dyn_cast<Instruction>(value)) {
1805 if (instruction->getParent()->getParent() != &llvm_function) {
1806 m_error_stream.PutCString("error: Capturing non-local variables in "
1807 "expressions is unsupported.\n");
1808 return false;
1809 }
1810 value->replaceAllUsesWith(
1811 body_result_maker.GetValue(instruction->getParent()->getParent()));
1812 } else {
1813 LLDB_LOG(log, "Unhandled non-constant type: \"{0}\"",do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Unhandled non-constant type: \"{0}\"", PrintValue
(value)); } while (0)
1814 PrintValue(value))do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Unhandled non-constant type: \"{0}\"", PrintValue
(value)); } while (0)
;
1815 return false;
1816 }
1817
1818 if (GlobalVariable *var = dyn_cast<GlobalVariable>(value))
1819 var->eraseFromParent();
1820 }
1821 }
1822
1823 LLDB_LOG(log, "Total structure [align {0}, size {1}]", (int64_t)alignment,do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Total structure [align {0}, size {1}]", (int64_t
)alignment, (uint64_t)size); } while (0)
1824 (uint64_t)size)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Total structure [align {0}, size {1}]", (int64_t
)alignment, (uint64_t)size); } while (0)
;
1825
1826 return true;
1827}
1828
1829bool IRForTarget::runOnModule(Module &llvm_module) {
1830 lldb_private::Log *log(
1831 lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS(1u << 8)));
1832
1833 m_module = &llvm_module;
1834 m_target_data = std::make_unique<DataLayout>(m_module);
1835 m_intptr_ty = llvm::Type::getIntNTy(m_module->getContext(),
1836 m_target_data->getPointerSizeInBits());
1837
1838 if (log) {
1
Assuming 'log' is null
2
Taking false branch
1839 std::string s;
1840 raw_string_ostream oss(s);
1841
1842 m_module->print(oss, nullptr);
1843
1844 oss.flush();
1845
1846 LLDB_LOG(log, "Module as passed in to IRForTarget: \n\"{0}\"", s)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Module as passed in to IRForTarget: \n\"{0}\"", s
); } while (0)
;
1847 }
1848
1849 Function *const main_function =
1850 m_func_name.IsEmpty() ? nullptr
3
'?' condition is false
1851 : m_module->getFunction(m_func_name.GetStringRef());
1852
1853 if (!m_func_name.IsEmpty() && !main_function) {
4
Assuming 'main_function' is non-null
5
Taking false branch
1854 LLDB_LOG(log, "Couldn't find \"{0}()\" in the module", m_func_name)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Couldn't find \"{0}()\" in the module", m_func_name
); } while (0)
;
1855
1856 m_error_stream.Format("Internal error [IRForTarget]: Couldn't find wrapper "
1857 "'{0}' in the module",
1858 m_func_name);
1859
1860 return false;
1861 }
1862
1863 if (main_function
5.1
'main_function' is non-null
5.1
'main_function' is non-null
) {
6
Taking true branch
1864 if (!FixFunctionLinkage(*main_function)) {
7
Taking false branch
1865 LLDB_LOG(log, "Couldn't fix the linkage for the function")do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Couldn't fix the linkage for the function"); } while
(0)
;
1866
1867 return false;
1868 }
1869 }
1870
1871 llvm::Type *int8_ty = Type::getInt8Ty(m_module->getContext());
1872
1873 m_reloc_placeholder = new llvm::GlobalVariable(
1874 (*m_module), int8_ty, false /* IsConstant */,
1875 GlobalVariable::InternalLinkage, Constant::getNullValue(int8_ty),
1876 "reloc_placeholder", nullptr /* InsertBefore */,
1877 GlobalVariable::NotThreadLocal /* ThreadLocal */, 0 /* AddressSpace */);
1878
1879 ////////////////////////////////////////////////////////////
1880 // Replace $__lldb_expr_result with a persistent variable
1881 //
1882
1883 if (main_function
7.1
'main_function' is non-null
7.1
'main_function' is non-null
) {
8
Taking true branch
1884 if (!CreateResultVariable(*main_function)) {
9
Assuming the condition is false
10
Taking false branch
1885 LLDB_LOG(log, "CreateResultVariable() failed")do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "CreateResultVariable() failed"); } while (0)
;
1886
1887 // CreateResultVariable() reports its own errors, so we don't do so here
1888
1889 return false;
1890 }
1891 }
1892
1893 if (log
10.1
'log' is null
10.1
'log' is null
&& log->GetVerbose()) {
1894 std::string s;
1895 raw_string_ostream oss(s);
1896
1897 m_module->print(oss, nullptr);
1898
1899 oss.flush();
1900
1901 LLDB_LOG(log, "Module after creating the result variable: \n\"{0}\"", s)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Module after creating the result variable: \n\"{0}\""
, s); } while (0)
;
1902 }
1903
1904 for (llvm::Function &function : *m_module) {
1905 for (BasicBlock &bb : function) {
1906 if (!RemoveGuards(bb)) {
1907 LLDB_LOG(log, "RemoveGuards() failed")do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "RemoveGuards() failed"); } while (0)
;
1908
1909 // RemoveGuards() reports its own errors, so we don't do so here
1910
1911 return false;
1912 }
1913
1914 if (!RewritePersistentAllocs(bb)) {
1915 LLDB_LOG(log, "RewritePersistentAllocs() failed")do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "RewritePersistentAllocs() failed"); } while (0)
;
1916
1917 // RewritePersistentAllocs() reports its own errors, so we don't do so
1918 // here
1919
1920 return false;
1921 }
1922
1923 if (!RemoveCXAAtExit(bb)) {
1924 LLDB_LOG(log, "RemoveCXAAtExit() failed")do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "RemoveCXAAtExit() failed"); } while (0)
;
1925
1926 // RemoveCXAAtExit() reports its own errors, so we don't do so here
1927
1928 return false;
1929 }
1930 }
1931 }
1932
1933 ///////////////////////////////////////////////////////////////////////////////
1934 // Fix all Objective-C constant strings to use NSStringWithCString:encoding:
1935 //
1936
1937 if (!RewriteObjCConstStrings()) {
11
Taking false branch
1938 LLDB_LOG(log, "RewriteObjCConstStrings() failed")do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "RewriteObjCConstStrings() failed"); } while (0)
;
1939
1940 // RewriteObjCConstStrings() reports its own errors, so we don't do so here
1941
1942 return false;
1943 }
1944
1945 for (llvm::Function &function : *m_module) {
1946 for (llvm::BasicBlock &bb : function) {
1947 if (!RewriteObjCSelectors(bb)) {
12
Calling 'IRForTarget::RewriteObjCSelectors'
1948 LLDB_LOG(log, "RewriteObjCSelectors() failed")do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "RewriteObjCSelectors() failed"); } while (0)
;
1949
1950 // RewriteObjCSelectors() reports its own errors, so we don't do so
1951 // here
1952
1953 return false;
1954 }
1955
1956 if (!RewriteObjCClassReferences(bb)) {
1957 LLDB_LOG(log, "RewriteObjCClassReferences() failed")do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "RewriteObjCClassReferences() failed"); } while (
0)
;
1958
1959 // RewriteObjCClasses() reports its own errors, so we don't do so here
1960
1961 return false;
1962 }
1963 }
1964 }
1965
1966 for (llvm::Function &function : *m_module) {
1967 for (BasicBlock &bb : function) {
1968 if (!ResolveCalls(bb)) {
1969 LLDB_LOG(log, "ResolveCalls() failed")do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "ResolveCalls() failed"); } while (0)
;
1970
1971 // ResolveCalls() reports its own errors, so we don't do so here
1972
1973 return false;
1974 }
1975 }
1976 }
1977
1978 ////////////////////////////////////////////////////////////////////////
1979 // Run function-level passes that only make sense on the main function
1980 //
1981
1982 if (main_function) {
1983 if (!ResolveExternals(*main_function)) {
1984 LLDB_LOG(log, "ResolveExternals() failed")do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "ResolveExternals() failed"); } while (0)
;
1985
1986 // ResolveExternals() reports its own errors, so we don't do so here
1987
1988 return false;
1989 }
1990
1991 if (!ReplaceVariables(*main_function)) {
1992 LLDB_LOG(log, "ReplaceVariables() failed")do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "ReplaceVariables() failed"); } while (0)
;
1993
1994 // ReplaceVariables() reports its own errors, so we don't do so here
1995
1996 return false;
1997 }
1998 }
1999
2000 if (log && log->GetVerbose()) {
2001 std::string s;
2002 raw_string_ostream oss(s);
2003
2004 m_module->print(oss, nullptr);
2005
2006 oss.flush();
2007
2008 LLDB_LOG(log, "Module after preparing for execution: \n\"{0}\"", s)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp"
, __func__, "Module after preparing for execution: \n\"{0}\""
, s); } while (0)
;
2009 }
2010
2011 return true;
2012}

/usr/src/gnu/usr.bin/clang/liblldbPluginExpressionParser/../../../llvm/llvm/include/llvm/IR/GlobalVariable.h

1//===-- llvm/GlobalVariable.h - GlobalVariable class ------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains the declaration of the GlobalVariable class, which
10// represents a single global variable (or constant) in the VM.
11//
12// Global variables are constant pointers that refer to hunks of space that are
13// allocated by either the VM, or by the linker in a static compiler. A global
14// variable may have an initial value, which is copied into the executables .data
15// area. Global Constants are required to have initializers.
16//
17//===----------------------------------------------------------------------===//
18
19#ifndef LLVM_IR_GLOBALVARIABLE_H
20#define LLVM_IR_GLOBALVARIABLE_H
21
22#include "llvm/ADT/Twine.h"
23#include "llvm/ADT/ilist_node.h"
24#include "llvm/IR/Attributes.h"
25#include "llvm/IR/GlobalObject.h"
26#include "llvm/IR/OperandTraits.h"
27#include "llvm/IR/Value.h"
28#include <cassert>
29#include <cstddef>
30
31namespace llvm {
32
33class Constant;
34class Module;
35
36template <typename ValueSubClass> class SymbolTableListTraits;
37class DIGlobalVariable;
38class DIGlobalVariableExpression;
39
40class GlobalVariable : public GlobalObject, public ilist_node<GlobalVariable> {
41 friend class SymbolTableListTraits<GlobalVariable>;
42
43 AttributeSet Attrs;
44 bool isConstantGlobal : 1; // Is this a global constant?
45 bool isExternallyInitializedConstant : 1; // Is this a global whose value
46 // can change from its initial
47 // value before global
48 // initializers are run?
49
50public:
51 /// GlobalVariable ctor - If a parent module is specified, the global is
52 /// automatically inserted into the end of the specified modules global list.
53 GlobalVariable(Type *Ty, bool isConstant, LinkageTypes Linkage,
54 Constant *Initializer = nullptr, const Twine &Name = "",
55 ThreadLocalMode = NotThreadLocal, unsigned AddressSpace = 0,
56 bool isExternallyInitialized = false);
57 /// GlobalVariable ctor - This creates a global and inserts it before the
58 /// specified other global.
59 GlobalVariable(Module &M, Type *Ty, bool isConstant, LinkageTypes Linkage,
60 Constant *Initializer, const Twine &Name = "",
61 GlobalVariable *InsertBefore = nullptr,
62 ThreadLocalMode = NotThreadLocal,
63 Optional<unsigned> AddressSpace = None,
64 bool isExternallyInitialized = false);
65 GlobalVariable(const GlobalVariable &) = delete;
66 GlobalVariable &operator=(const GlobalVariable &) = delete;
67
68 ~GlobalVariable() {
69 dropAllReferences();
70 }
71
72 // allocate space for exactly one operand
73 void *operator new(size_t s) {
74 return User::operator new(s, 1);
75 }
76
77 // delete space for exactly one operand as created in the corresponding new operator
78 void operator delete(void *ptr){
79 assert(ptr != nullptr && "must not be nullptr")((void)0);
80 User *Obj = static_cast<User *>(ptr);
81 // Number of operands can be set to 0 after construction and initialization. Make sure
82 // that number of operands is reset to 1, as this is needed in User::operator delete
83 Obj->setGlobalVariableNumOperands(1);
84 User::operator delete(Obj);
85 }
86
87 /// Provide fast operand accessors
88 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value)public: inline Value *getOperand(unsigned) const; inline void
setOperand(unsigned, Value*); inline op_iterator op_begin();
inline const_op_iterator op_begin() const; inline op_iterator
op_end(); inline const_op_iterator op_end() const; protected
: template <int> inline Use &Op(); template <int
> inline const Use &Op() const; public: inline unsigned
getNumOperands() const
;
89
90 /// Definitions have initializers, declarations don't.
91 ///
92 inline bool hasInitializer() const { return !isDeclaration(); }
19
Assuming the condition is true
20
Returning the value 1, which participates in a condition later
29
Assuming the condition is true
30
Returning the value 1, which participates in a condition later
93
94 /// hasDefinitiveInitializer - Whether the global variable has an initializer,
95 /// and any other instances of the global (this can happen due to weak
96 /// linkage) are guaranteed to have the same initializer.
97 ///
98 /// Note that if you want to transform a global, you must use
99 /// hasUniqueInitializer() instead, because of the *_odr linkage type.
100 ///
101 /// Example:
102 ///
103 /// @a = global SomeType* null - Initializer is both definitive and unique.
104 ///
105 /// @b = global weak SomeType* null - Initializer is neither definitive nor
106 /// unique.
107 ///
108 /// @c = global weak_odr SomeType* null - Initializer is definitive, but not
109 /// unique.
110 inline bool hasDefinitiveInitializer() const {
111 return hasInitializer() &&
112 // The initializer of a global variable may change to something arbitrary
113 // at link time.
114 !isInterposable() &&
115 // The initializer of a global variable with the externally_initialized
116 // marker may change at runtime before C++ initializers are evaluated.
117 !isExternallyInitialized();
118 }
119
120 /// hasUniqueInitializer - Whether the global variable has an initializer, and
121 /// any changes made to the initializer will turn up in the final executable.
122 inline bool hasUniqueInitializer() const {
123 return
124 // We need to be sure this is the definition that will actually be used
125 isStrongDefinitionForLinker() &&
126 // It is not safe to modify initializers of global variables with the
127 // external_initializer marker since the value may be changed at runtime
128 // before C++ initializers are evaluated.
129 !isExternallyInitialized();
130 }
131
132 /// getInitializer - Return the initializer for this global variable. It is
133 /// illegal to call this method if the global is external, because we cannot
134 /// tell what the value is initialized to!
135 ///
136 inline const Constant *getInitializer() const {
137 assert(hasInitializer() && "GV doesn't have initializer!")((void)0);
138 return static_cast<Constant*>(Op<0>().get());
139 }
140 inline Constant *getInitializer() {
141 assert(hasInitializer() && "GV doesn't have initializer!")((void)0);
142 return static_cast<Constant*>(Op<0>().get());
143 }
144 /// setInitializer - Sets the initializer for this global variable, removing
145 /// any existing initializer if InitVal==NULL. If this GV has type T*, the
146 /// initializer must have type T.
147 void setInitializer(Constant *InitVal);
148
149 /// If the value is a global constant, its value is immutable throughout the
150 /// runtime execution of the program. Assigning a value into the constant
151 /// leads to undefined behavior.
152 ///
153 bool isConstant() const { return isConstantGlobal; }
154 void setConstant(bool Val) { isConstantGlobal = Val; }
155
156 bool isExternallyInitialized() const {
157 return isExternallyInitializedConstant;
158 }
159 void setExternallyInitialized(bool Val) {
160 isExternallyInitializedConstant = Val;
161 }
162
163 /// copyAttributesFrom - copy all additional attributes (those not needed to
164 /// create a GlobalVariable) from the GlobalVariable Src to this one.
165 void copyAttributesFrom(const GlobalVariable *Src);
166
167 /// removeFromParent - This method unlinks 'this' from the containing module,
168 /// but does not delete it.
169 ///
170 void removeFromParent();
171
172 /// eraseFromParent - This method unlinks 'this' from the containing module
173 /// and deletes it.
174 ///
175 void eraseFromParent();
176
177 /// Drop all references in preparation to destroy the GlobalVariable. This
178 /// drops not only the reference to the initializer but also to any metadata.
179 void dropAllReferences();
180
181 /// Attach a DIGlobalVariableExpression.
182 void addDebugInfo(DIGlobalVariableExpression *GV);
183
184 /// Fill the vector with all debug info attachements.
185 void getDebugInfo(SmallVectorImpl<DIGlobalVariableExpression *> &GVs) const;
186
187 /// Add attribute to this global.
188 void addAttribute(Attribute::AttrKind Kind) {
189 Attrs = Attrs.addAttribute(getContext(), Kind);
190 }
191
192 /// Add attribute to this global.
193 void addAttribute(StringRef Kind, StringRef Val = StringRef()) {
194 Attrs = Attrs.addAttribute(getContext(), Kind, Val);
195 }
196
197 /// Return true if the attribute exists.
198 bool hasAttribute(Attribute::AttrKind Kind) const {
199 return Attrs.hasAttribute(Kind);
200 }
201
202 /// Return true if the attribute exists.
203 bool hasAttribute(StringRef Kind) const {
204 return Attrs.hasAttribute(Kind);
205 }
206
207 /// Return true if any attributes exist.
208 bool hasAttributes() const {
209 return Attrs.hasAttributes();
210 }
211
212 /// Return the attribute object.
213 Attribute getAttribute(Attribute::AttrKind Kind) const {
214 return Attrs.getAttribute(Kind);
215 }
216
217 /// Return the attribute object.
218 Attribute getAttribute(StringRef Kind) const {
219 return Attrs.getAttribute(Kind);
220 }
221
222 /// Return the attribute set for this global
223 AttributeSet getAttributes() const {
224 return Attrs;
225 }
226
227 /// Return attribute set as list with index.
228 /// FIXME: This may not be required once ValueEnumerators
229 /// in bitcode-writer can enumerate attribute-set.
230 AttributeList getAttributesAsList(unsigned index) const {
231 if (!hasAttributes())
232 return AttributeList();
233 std::pair<unsigned, AttributeSet> AS[1] = {{index, Attrs}};
234 return AttributeList::get(getContext(), AS);
235 }
236
237 /// Set attribute list for this global
238 void setAttributes(AttributeSet A) {
239 Attrs = A;
240 }
241
242 /// Check if section name is present
243 bool hasImplicitSection() const {
244 return getAttributes().hasAttribute("bss-section") ||
245 getAttributes().hasAttribute("data-section") ||
246 getAttributes().hasAttribute("relro-section") ||
247 getAttributes().hasAttribute("rodata-section");
248 }
249
250 // Methods for support type inquiry through isa, cast, and dyn_cast:
251 static bool classof(const Value *V) {
252 return V->getValueID() == Value::GlobalVariableVal;
253 }
254};
255
256template <>
257struct OperandTraits<GlobalVariable> :
258 public OptionalOperandTraits<GlobalVariable> {
259};
260
261DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GlobalVariable, Value)GlobalVariable::op_iterator GlobalVariable::op_begin() { return
OperandTraits<GlobalVariable>::op_begin(this); } GlobalVariable
::const_op_iterator GlobalVariable::op_begin() const { return
OperandTraits<GlobalVariable>::op_begin(const_cast<
GlobalVariable*>(this)); } GlobalVariable::op_iterator GlobalVariable
::op_end() { return OperandTraits<GlobalVariable>::op_end
(this); } GlobalVariable::const_op_iterator GlobalVariable::op_end
() const { return OperandTraits<GlobalVariable>::op_end
(const_cast<GlobalVariable*>(this)); } Value *GlobalVariable
::getOperand(unsigned i_nocapture) const { ((void)0); return cast_or_null
<Value>( OperandTraits<GlobalVariable>::op_begin(
const_cast<GlobalVariable*>(this))[i_nocapture].get());
} void GlobalVariable::setOperand(unsigned i_nocapture, Value
*Val_nocapture) { ((void)0); OperandTraits<GlobalVariable
>::op_begin(this)[i_nocapture] = Val_nocapture; } unsigned
GlobalVariable::getNumOperands() const { return OperandTraits
<GlobalVariable>::operands(this); } template <int Idx_nocapture
> Use &GlobalVariable::Op() { return this->OpFrom<
Idx_nocapture>(this); } template <int Idx_nocapture>
const Use &GlobalVariable::Op() const { return this->
OpFrom<Idx_nocapture>(this); }
262
263} // end namespace llvm
264
265#endif // LLVM_IR_GLOBALVARIABLE_H