File: | llvm/lib/Target/AMDGPU/AMDGPUPrintfRuntimeBinding.cpp |
Warning: | line 443, column 44 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //=== AMDGPUPrintfRuntimeBinding.cpp - OpenCL printf implementation -------===// | ||||||
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 | // \file | ||||||
9 | // | ||||||
10 | // The pass bind printfs to a kernel arg pointer that will be bound to a buffer | ||||||
11 | // later by the runtime. | ||||||
12 | // | ||||||
13 | // This pass traverses the functions in the module and converts | ||||||
14 | // each call to printf to a sequence of operations that | ||||||
15 | // store the following into the printf buffer: | ||||||
16 | // - format string (passed as a module's metadata unique ID) | ||||||
17 | // - bitwise copies of printf arguments | ||||||
18 | // The backend passes will need to store metadata in the kernel | ||||||
19 | //===----------------------------------------------------------------------===// | ||||||
20 | |||||||
21 | #include "AMDGPU.h" | ||||||
22 | #include "llvm/ADT/SmallString.h" | ||||||
23 | #include "llvm/ADT/StringExtras.h" | ||||||
24 | #include "llvm/ADT/Triple.h" | ||||||
25 | #include "llvm/Analysis/InstructionSimplify.h" | ||||||
26 | #include "llvm/Analysis/TargetLibraryInfo.h" | ||||||
27 | #include "llvm/CodeGen/Passes.h" | ||||||
28 | #include "llvm/IR/Constants.h" | ||||||
29 | #include "llvm/IR/DataLayout.h" | ||||||
30 | #include "llvm/IR/Dominators.h" | ||||||
31 | #include "llvm/IR/GlobalVariable.h" | ||||||
32 | #include "llvm/IR/IRBuilder.h" | ||||||
33 | #include "llvm/IR/Instructions.h" | ||||||
34 | #include "llvm/IR/Module.h" | ||||||
35 | #include "llvm/IR/Type.h" | ||||||
36 | #include "llvm/InitializePasses.h" | ||||||
37 | #include "llvm/Support/CommandLine.h" | ||||||
38 | #include "llvm/Support/Debug.h" | ||||||
39 | #include "llvm/Support/raw_ostream.h" | ||||||
40 | #include "llvm/Transforms/Utils/BasicBlockUtils.h" | ||||||
41 | using namespace llvm; | ||||||
42 | |||||||
43 | #define DEBUG_TYPE"printfToRuntime" "printfToRuntime" | ||||||
44 | #define DWORD_ALIGN4 4 | ||||||
45 | |||||||
46 | namespace { | ||||||
47 | class LLVM_LIBRARY_VISIBILITY__attribute__ ((visibility("hidden"))) AMDGPUPrintfRuntimeBinding final | ||||||
48 | : public ModulePass { | ||||||
49 | |||||||
50 | public: | ||||||
51 | static char ID; | ||||||
52 | |||||||
53 | explicit AMDGPUPrintfRuntimeBinding(); | ||||||
54 | |||||||
55 | private: | ||||||
56 | bool runOnModule(Module &M) override; | ||||||
57 | void getConversionSpecifiers(SmallVectorImpl<char> &OpConvSpecifiers, | ||||||
58 | StringRef fmt, size_t num_ops) const; | ||||||
59 | |||||||
60 | bool shouldPrintAsStr(char Specifier, Type *OpType) const; | ||||||
61 | bool | ||||||
62 | lowerPrintfForGpu(Module &M, | ||||||
63 | function_ref<const TargetLibraryInfo &(Function &)> GetTLI); | ||||||
64 | |||||||
65 | void getAnalysisUsage(AnalysisUsage &AU) const override { | ||||||
66 | AU.addRequired<TargetLibraryInfoWrapperPass>(); | ||||||
67 | AU.addRequired<DominatorTreeWrapperPass>(); | ||||||
68 | } | ||||||
69 | |||||||
70 | Value *simplify(Instruction *I, const TargetLibraryInfo *TLI) { | ||||||
71 | return SimplifyInstruction(I, {*TD, TLI, DT}); | ||||||
72 | } | ||||||
73 | |||||||
74 | const DataLayout *TD; | ||||||
75 | const DominatorTree *DT; | ||||||
76 | SmallVector<CallInst *, 32> Printfs; | ||||||
77 | }; | ||||||
78 | } // namespace | ||||||
79 | |||||||
80 | char AMDGPUPrintfRuntimeBinding::ID = 0; | ||||||
81 | |||||||
82 | INITIALIZE_PASS_BEGIN(AMDGPUPrintfRuntimeBinding,static void *initializeAMDGPUPrintfRuntimeBindingPassOnce(PassRegistry &Registry) { | ||||||
83 | "amdgpu-printf-runtime-binding", "AMDGPU Printf lowering",static void *initializeAMDGPUPrintfRuntimeBindingPassOnce(PassRegistry &Registry) { | ||||||
84 | false, false)static void *initializeAMDGPUPrintfRuntimeBindingPassOnce(PassRegistry &Registry) { | ||||||
85 | INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)initializeTargetLibraryInfoWrapperPassPass(Registry); | ||||||
86 | INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)initializeDominatorTreeWrapperPassPass(Registry); | ||||||
87 | INITIALIZE_PASS_END(AMDGPUPrintfRuntimeBinding, "amdgpu-printf-runtime-binding",PassInfo *PI = new PassInfo( "AMDGPU Printf lowering", "amdgpu-printf-runtime-binding" , &AMDGPUPrintfRuntimeBinding::ID, PassInfo::NormalCtor_t (callDefaultCtor<AMDGPUPrintfRuntimeBinding>), false, false ); Registry.registerPass(*PI, true); return PI; } static llvm ::once_flag InitializeAMDGPUPrintfRuntimeBindingPassFlag; void llvm::initializeAMDGPUPrintfRuntimeBindingPass(PassRegistry & Registry) { llvm::call_once(InitializeAMDGPUPrintfRuntimeBindingPassFlag , initializeAMDGPUPrintfRuntimeBindingPassOnce, std::ref(Registry )); } | ||||||
88 | "AMDGPU Printf lowering", false, false)PassInfo *PI = new PassInfo( "AMDGPU Printf lowering", "amdgpu-printf-runtime-binding" , &AMDGPUPrintfRuntimeBinding::ID, PassInfo::NormalCtor_t (callDefaultCtor<AMDGPUPrintfRuntimeBinding>), false, false ); Registry.registerPass(*PI, true); return PI; } static llvm ::once_flag InitializeAMDGPUPrintfRuntimeBindingPassFlag; void llvm::initializeAMDGPUPrintfRuntimeBindingPass(PassRegistry & Registry) { llvm::call_once(InitializeAMDGPUPrintfRuntimeBindingPassFlag , initializeAMDGPUPrintfRuntimeBindingPassOnce, std::ref(Registry )); } | ||||||
89 | |||||||
90 | char &llvm::AMDGPUPrintfRuntimeBindingID = AMDGPUPrintfRuntimeBinding::ID; | ||||||
91 | |||||||
92 | namespace llvm { | ||||||
93 | ModulePass *createAMDGPUPrintfRuntimeBinding() { | ||||||
94 | return new AMDGPUPrintfRuntimeBinding(); | ||||||
95 | } | ||||||
96 | } // namespace llvm | ||||||
97 | |||||||
98 | AMDGPUPrintfRuntimeBinding::AMDGPUPrintfRuntimeBinding() | ||||||
99 | : ModulePass(ID), TD(nullptr), DT(nullptr) { | ||||||
100 | initializeAMDGPUPrintfRuntimeBindingPass(*PassRegistry::getPassRegistry()); | ||||||
101 | } | ||||||
102 | |||||||
103 | void AMDGPUPrintfRuntimeBinding::getConversionSpecifiers( | ||||||
104 | SmallVectorImpl<char> &OpConvSpecifiers, StringRef Fmt, | ||||||
105 | size_t NumOps) const { | ||||||
106 | // not all format characters are collected. | ||||||
107 | // At this time the format characters of interest | ||||||
108 | // are %p and %s, which use to know if we | ||||||
109 | // are either storing a literal string or a | ||||||
110 | // pointer to the printf buffer. | ||||||
111 | static const char ConvSpecifiers[] = "cdieEfgGaosuxXp"; | ||||||
112 | size_t CurFmtSpecifierIdx = 0; | ||||||
113 | size_t PrevFmtSpecifierIdx = 0; | ||||||
114 | |||||||
115 | while ((CurFmtSpecifierIdx = Fmt.find_first_of( | ||||||
116 | ConvSpecifiers, CurFmtSpecifierIdx)) != StringRef::npos) { | ||||||
117 | bool ArgDump = false; | ||||||
118 | StringRef CurFmt = Fmt.substr(PrevFmtSpecifierIdx, | ||||||
119 | CurFmtSpecifierIdx - PrevFmtSpecifierIdx); | ||||||
120 | size_t pTag = CurFmt.find_last_of("%"); | ||||||
121 | if (pTag != StringRef::npos) { | ||||||
122 | ArgDump = true; | ||||||
123 | while (pTag && CurFmt[--pTag] == '%') { | ||||||
124 | ArgDump = !ArgDump; | ||||||
125 | } | ||||||
126 | } | ||||||
127 | |||||||
128 | if (ArgDump) | ||||||
129 | OpConvSpecifiers.push_back(Fmt[CurFmtSpecifierIdx]); | ||||||
130 | |||||||
131 | PrevFmtSpecifierIdx = ++CurFmtSpecifierIdx; | ||||||
132 | } | ||||||
133 | } | ||||||
134 | |||||||
135 | bool AMDGPUPrintfRuntimeBinding::shouldPrintAsStr(char Specifier, | ||||||
136 | Type *OpType) const { | ||||||
137 | if (Specifier != 's') | ||||||
138 | return false; | ||||||
139 | const PointerType *PT = dyn_cast<PointerType>(OpType); | ||||||
140 | if (!PT
| ||||||
141 | return false; | ||||||
142 | Type *ElemType = PT->getContainedType(0); | ||||||
143 | if (ElemType->getTypeID() != Type::IntegerTyID) | ||||||
144 | return false; | ||||||
145 | IntegerType *ElemIType = cast<IntegerType>(ElemType); | ||||||
146 | return ElemIType->getBitWidth() == 8; | ||||||
147 | } | ||||||
148 | |||||||
149 | bool AMDGPUPrintfRuntimeBinding::lowerPrintfForGpu( | ||||||
150 | Module &M, function_ref<const TargetLibraryInfo &(Function &)> GetTLI) { | ||||||
151 | LLVMContext &Ctx = M.getContext(); | ||||||
152 | IRBuilder<> Builder(Ctx); | ||||||
153 | Type *I32Ty = Type::getInt32Ty(Ctx); | ||||||
154 | unsigned UniqID = 0; | ||||||
155 | // NB: This is important for this string size to be divizable by 4 | ||||||
156 | const char NonLiteralStr[4] = "???"; | ||||||
157 | |||||||
158 | for (auto CI : Printfs) { | ||||||
| |||||||
159 | unsigned NumOps = CI->getNumArgOperands(); | ||||||
160 | |||||||
161 | SmallString<16> OpConvSpecifiers; | ||||||
162 | Value *Op = CI->getArgOperand(0); | ||||||
163 | |||||||
164 | if (auto LI = dyn_cast<LoadInst>(Op)) { | ||||||
165 | Op = LI->getPointerOperand(); | ||||||
166 | for (auto Use : Op->users()) { | ||||||
167 | if (auto SI = dyn_cast<StoreInst>(Use)) { | ||||||
168 | Op = SI->getValueOperand(); | ||||||
169 | break; | ||||||
170 | } | ||||||
171 | } | ||||||
172 | } | ||||||
173 | |||||||
174 | if (auto I = dyn_cast<Instruction>(Op)) { | ||||||
175 | Value *Op_simplified = simplify(I, &GetTLI(*I->getFunction())); | ||||||
176 | if (Op_simplified) | ||||||
177 | Op = Op_simplified; | ||||||
178 | } | ||||||
179 | |||||||
180 | ConstantExpr *ConstExpr = dyn_cast<ConstantExpr>(Op); | ||||||
181 | |||||||
182 | if (ConstExpr) { | ||||||
183 | GlobalVariable *GVar = dyn_cast<GlobalVariable>(ConstExpr->getOperand(0)); | ||||||
184 | |||||||
185 | StringRef Str("unknown"); | ||||||
186 | if (GVar && GVar->hasInitializer()) { | ||||||
187 | auto Init = GVar->getInitializer(); | ||||||
188 | if (auto CA = dyn_cast<ConstantDataArray>(Init)) { | ||||||
189 | if (CA->isString()) | ||||||
190 | Str = CA->getAsCString(); | ||||||
191 | } else if (isa<ConstantAggregateZero>(Init)) { | ||||||
192 | Str = ""; | ||||||
193 | } | ||||||
194 | // | ||||||
195 | // we need this call to ascertain | ||||||
196 | // that we are printing a string | ||||||
197 | // or a pointer. It takes out the | ||||||
198 | // specifiers and fills up the first | ||||||
199 | // arg | ||||||
200 | getConversionSpecifiers(OpConvSpecifiers, Str, NumOps - 1); | ||||||
201 | } | ||||||
202 | // Add metadata for the string | ||||||
203 | std::string AStreamHolder; | ||||||
204 | raw_string_ostream Sizes(AStreamHolder); | ||||||
205 | int Sum = DWORD_ALIGN4; | ||||||
206 | Sizes << CI->getNumArgOperands() - 1; | ||||||
207 | Sizes << ':'; | ||||||
208 | for (unsigned ArgCount = 1; ArgCount < CI->getNumArgOperands() && | ||||||
209 | ArgCount <= OpConvSpecifiers.size(); | ||||||
210 | ArgCount++) { | ||||||
211 | Value *Arg = CI->getArgOperand(ArgCount); | ||||||
212 | Type *ArgType = Arg->getType(); | ||||||
213 | unsigned ArgSize = TD->getTypeAllocSizeInBits(ArgType); | ||||||
214 | ArgSize = ArgSize / 8; | ||||||
215 | // | ||||||
216 | // ArgSize by design should be a multiple of DWORD_ALIGN, | ||||||
217 | // expand the arguments that do not follow this rule. | ||||||
218 | // | ||||||
219 | if (ArgSize % DWORD_ALIGN4 != 0) { | ||||||
220 | llvm::Type *ResType = llvm::Type::getInt32Ty(Ctx); | ||||||
221 | VectorType *LLVMVecType = llvm::dyn_cast<llvm::VectorType>(ArgType); | ||||||
222 | int NumElem = LLVMVecType ? LLVMVecType->getNumElements() : 1; | ||||||
223 | if (LLVMVecType && NumElem > 1) | ||||||
224 | ResType = llvm::VectorType::get(ResType, NumElem); | ||||||
225 | Builder.SetInsertPoint(CI); | ||||||
226 | Builder.SetCurrentDebugLocation(CI->getDebugLoc()); | ||||||
227 | if (OpConvSpecifiers[ArgCount - 1] == 'x' || | ||||||
228 | OpConvSpecifiers[ArgCount - 1] == 'X' || | ||||||
229 | OpConvSpecifiers[ArgCount - 1] == 'u' || | ||||||
230 | OpConvSpecifiers[ArgCount - 1] == 'o') | ||||||
231 | Arg = Builder.CreateZExt(Arg, ResType); | ||||||
232 | else | ||||||
233 | Arg = Builder.CreateSExt(Arg, ResType); | ||||||
234 | ArgType = Arg->getType(); | ||||||
235 | ArgSize = TD->getTypeAllocSizeInBits(ArgType); | ||||||
236 | ArgSize = ArgSize / 8; | ||||||
237 | CI->setOperand(ArgCount, Arg); | ||||||
238 | } | ||||||
239 | if (OpConvSpecifiers[ArgCount - 1] == 'f') { | ||||||
240 | ConstantFP *FpCons = dyn_cast<ConstantFP>(Arg); | ||||||
241 | if (FpCons) | ||||||
242 | ArgSize = 4; | ||||||
243 | else { | ||||||
244 | FPExtInst *FpExt = dyn_cast<FPExtInst>(Arg); | ||||||
245 | if (FpExt && FpExt->getType()->isDoubleTy() && | ||||||
246 | FpExt->getOperand(0)->getType()->isFloatTy()) | ||||||
247 | ArgSize = 4; | ||||||
248 | } | ||||||
249 | } | ||||||
250 | if (shouldPrintAsStr(OpConvSpecifiers[ArgCount - 1], ArgType)) { | ||||||
251 | if (ConstantExpr *ConstExpr = dyn_cast<ConstantExpr>(Arg)) { | ||||||
252 | GlobalVariable *GV = | ||||||
253 | dyn_cast<GlobalVariable>(ConstExpr->getOperand(0)); | ||||||
254 | if (GV && GV->hasInitializer()) { | ||||||
255 | Constant *Init = GV->getInitializer(); | ||||||
256 | ConstantDataArray *CA = dyn_cast<ConstantDataArray>(Init); | ||||||
257 | if (Init->isZeroValue() || CA->isString()) { | ||||||
258 | size_t SizeStr = Init->isZeroValue() | ||||||
259 | ? 1 | ||||||
260 | : (strlen(CA->getAsCString().data()) + 1); | ||||||
261 | size_t Rem = SizeStr % DWORD_ALIGN4; | ||||||
262 | size_t NSizeStr = 0; | ||||||
263 | LLVM_DEBUG(dbgs() << "Printf string original size = " << SizeStrdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("printfToRuntime")) { dbgs() << "Printf string original size = " << SizeStr << '\n'; } } while (false) | ||||||
264 | << '\n')do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("printfToRuntime")) { dbgs() << "Printf string original size = " << SizeStr << '\n'; } } while (false); | ||||||
265 | if (Rem) { | ||||||
266 | NSizeStr = SizeStr + (DWORD_ALIGN4 - Rem); | ||||||
267 | } else { | ||||||
268 | NSizeStr = SizeStr; | ||||||
269 | } | ||||||
270 | ArgSize = NSizeStr; | ||||||
271 | } | ||||||
272 | } else { | ||||||
273 | ArgSize = sizeof(NonLiteralStr); | ||||||
274 | } | ||||||
275 | } else { | ||||||
276 | ArgSize = sizeof(NonLiteralStr); | ||||||
277 | } | ||||||
278 | } | ||||||
279 | LLVM_DEBUG(dbgs() << "Printf ArgSize (in buffer) = " << ArgSizedo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("printfToRuntime")) { dbgs() << "Printf ArgSize (in buffer) = " << ArgSize << " for type: " << *ArgType << '\n'; } } while (false) | ||||||
280 | << " for type: " << *ArgType << '\n')do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("printfToRuntime")) { dbgs() << "Printf ArgSize (in buffer) = " << ArgSize << " for type: " << *ArgType << '\n'; } } while (false); | ||||||
281 | Sizes << ArgSize << ':'; | ||||||
282 | Sum += ArgSize; | ||||||
283 | } | ||||||
284 | LLVM_DEBUG(dbgs() << "Printf format string in source = " << Str.str()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("printfToRuntime")) { dbgs() << "Printf format string in source = " << Str.str() << '\n'; } } while (false) | ||||||
285 | << '\n')do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("printfToRuntime")) { dbgs() << "Printf format string in source = " << Str.str() << '\n'; } } while (false); | ||||||
286 | for (size_t I = 0; I < Str.size(); ++I) { | ||||||
287 | // Rest of the C escape sequences (e.g. \') are handled correctly | ||||||
288 | // by the MDParser | ||||||
289 | switch (Str[I]) { | ||||||
290 | case '\a': | ||||||
291 | Sizes << "\\a"; | ||||||
292 | break; | ||||||
293 | case '\b': | ||||||
294 | Sizes << "\\b"; | ||||||
295 | break; | ||||||
296 | case '\f': | ||||||
297 | Sizes << "\\f"; | ||||||
298 | break; | ||||||
299 | case '\n': | ||||||
300 | Sizes << "\\n"; | ||||||
301 | break; | ||||||
302 | case '\r': | ||||||
303 | Sizes << "\\r"; | ||||||
304 | break; | ||||||
305 | case '\v': | ||||||
306 | Sizes << "\\v"; | ||||||
307 | break; | ||||||
308 | case ':': | ||||||
309 | // ':' cannot be scanned by Flex, as it is defined as a delimiter | ||||||
310 | // Replace it with it's octal representation \72 | ||||||
311 | Sizes << "\\72"; | ||||||
312 | break; | ||||||
313 | default: | ||||||
314 | Sizes << Str[I]; | ||||||
315 | break; | ||||||
316 | } | ||||||
317 | } | ||||||
318 | |||||||
319 | // Insert the printf_alloc call | ||||||
320 | Builder.SetInsertPoint(CI); | ||||||
321 | Builder.SetCurrentDebugLocation(CI->getDebugLoc()); | ||||||
322 | |||||||
323 | AttributeList Attr = AttributeList::get(Ctx, AttributeList::FunctionIndex, | ||||||
324 | Attribute::NoUnwind); | ||||||
325 | |||||||
326 | Type *SizetTy = Type::getInt32Ty(Ctx); | ||||||
327 | |||||||
328 | Type *Tys_alloc[1] = {SizetTy}; | ||||||
329 | Type *I8Ptr = PointerType::get(Type::getInt8Ty(Ctx), 1); | ||||||
330 | FunctionType *FTy_alloc = FunctionType::get(I8Ptr, Tys_alloc, false); | ||||||
331 | FunctionCallee PrintfAllocFn = | ||||||
332 | M.getOrInsertFunction(StringRef("__printf_alloc"), FTy_alloc, Attr); | ||||||
333 | |||||||
334 | LLVM_DEBUG(dbgs() << "Printf metadata = " << Sizes.str() << '\n')do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("printfToRuntime")) { dbgs() << "Printf metadata = " << Sizes.str() << '\n'; } } while (false); | ||||||
335 | std::string fmtstr = itostr(++UniqID) + ":" + Sizes.str().c_str(); | ||||||
336 | MDString *fmtStrArray = MDString::get(Ctx, fmtstr); | ||||||
337 | |||||||
338 | // Instead of creating global variables, the | ||||||
339 | // printf format strings are extracted | ||||||
340 | // and passed as metadata. This avoids | ||||||
341 | // polluting llvm's symbol tables in this module. | ||||||
342 | // Metadata is going to be extracted | ||||||
343 | // by the backend passes and inserted | ||||||
344 | // into the OpenCL binary as appropriate. | ||||||
345 | StringRef amd("llvm.printf.fmts"); | ||||||
346 | NamedMDNode *metaD = M.getOrInsertNamedMetadata(amd); | ||||||
347 | MDNode *myMD = MDNode::get(Ctx, fmtStrArray); | ||||||
348 | metaD->addOperand(myMD); | ||||||
349 | Value *sumC = ConstantInt::get(SizetTy, Sum, false); | ||||||
350 | SmallVector<Value *, 1> alloc_args; | ||||||
351 | alloc_args.push_back(sumC); | ||||||
352 | CallInst *pcall = | ||||||
353 | CallInst::Create(PrintfAllocFn, alloc_args, "printf_alloc_fn", CI); | ||||||
354 | |||||||
355 | // | ||||||
356 | // Insert code to split basicblock with a | ||||||
357 | // piece of hammock code. | ||||||
358 | // basicblock splits after buffer overflow check | ||||||
359 | // | ||||||
360 | ConstantPointerNull *zeroIntPtr = | ||||||
361 | ConstantPointerNull::get(PointerType::get(Type::getInt8Ty(Ctx), 1)); | ||||||
362 | ICmpInst *cmp = | ||||||
363 | dyn_cast<ICmpInst>(Builder.CreateICmpNE(pcall, zeroIntPtr, "")); | ||||||
364 | if (!CI->use_empty()) { | ||||||
365 | Value *result = | ||||||
366 | Builder.CreateSExt(Builder.CreateNot(cmp), I32Ty, "printf_res"); | ||||||
367 | CI->replaceAllUsesWith(result); | ||||||
368 | } | ||||||
369 | SplitBlock(CI->getParent(), cmp); | ||||||
370 | Instruction *Brnch = | ||||||
371 | SplitBlockAndInsertIfThen(cmp, cmp->getNextNode(), false); | ||||||
372 | |||||||
373 | Builder.SetInsertPoint(Brnch); | ||||||
374 | |||||||
375 | // store unique printf id in the buffer | ||||||
376 | // | ||||||
377 | SmallVector<Value *, 1> ZeroIdxList; | ||||||
378 | ConstantInt *zeroInt = | ||||||
379 | ConstantInt::get(Ctx, APInt(32, StringRef("0"), 10)); | ||||||
380 | ZeroIdxList.push_back(zeroInt); | ||||||
381 | |||||||
382 | GetElementPtrInst *BufferIdx = | ||||||
383 | dyn_cast<GetElementPtrInst>(GetElementPtrInst::Create( | ||||||
384 | nullptr, pcall, ZeroIdxList, "PrintBuffID", Brnch)); | ||||||
385 | |||||||
386 | Type *idPointer = PointerType::get(I32Ty, AMDGPUAS::GLOBAL_ADDRESS); | ||||||
387 | Value *id_gep_cast = | ||||||
388 | new BitCastInst(BufferIdx, idPointer, "PrintBuffIdCast", Brnch); | ||||||
389 | |||||||
390 | StoreInst *stbuff = | ||||||
391 | new StoreInst(ConstantInt::get(I32Ty, UniqID), id_gep_cast); | ||||||
392 | stbuff->insertBefore(Brnch); // to Remove unused variable warning | ||||||
393 | |||||||
394 | SmallVector<Value *, 2> FourthIdxList; | ||||||
395 | ConstantInt *fourInt = | ||||||
396 | ConstantInt::get(Ctx, APInt(32, StringRef("4"), 10)); | ||||||
397 | |||||||
398 | FourthIdxList.push_back(fourInt); // 1st 4 bytes hold the printf_id | ||||||
399 | // the following GEP is the buffer pointer | ||||||
400 | BufferIdx = cast<GetElementPtrInst>(GetElementPtrInst::Create( | ||||||
401 | nullptr, pcall, FourthIdxList, "PrintBuffGep", Brnch)); | ||||||
402 | |||||||
403 | Type *Int32Ty = Type::getInt32Ty(Ctx); | ||||||
404 | Type *Int64Ty = Type::getInt64Ty(Ctx); | ||||||
405 | for (unsigned ArgCount = 1; ArgCount < CI->getNumArgOperands() && | ||||||
406 | ArgCount <= OpConvSpecifiers.size(); | ||||||
407 | ArgCount++) { | ||||||
408 | Value *Arg = CI->getArgOperand(ArgCount); | ||||||
409 | Type *ArgType = Arg->getType(); | ||||||
410 | SmallVector<Value *, 32> WhatToStore; | ||||||
411 | if (ArgType->isFPOrFPVectorTy() && | ||||||
412 | (ArgType->getTypeID() != Type::VectorTyID)) { | ||||||
413 | Type *IType = (ArgType->isFloatTy()) ? Int32Ty : Int64Ty; | ||||||
414 | if (OpConvSpecifiers[ArgCount - 1] == 'f') { | ||||||
415 | ConstantFP *fpCons = dyn_cast<ConstantFP>(Arg); | ||||||
416 | if (fpCons) { | ||||||
417 | APFloat Val(fpCons->getValueAPF()); | ||||||
418 | bool Lost = false; | ||||||
419 | Val.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven, | ||||||
420 | &Lost); | ||||||
421 | Arg = ConstantFP::get(Ctx, Val); | ||||||
422 | IType = Int32Ty; | ||||||
423 | } else { | ||||||
424 | FPExtInst *FpExt = dyn_cast<FPExtInst>(Arg); | ||||||
425 | if (FpExt && FpExt->getType()->isDoubleTy() && | ||||||
426 | FpExt->getOperand(0)->getType()->isFloatTy()) { | ||||||
427 | Arg = FpExt->getOperand(0); | ||||||
428 | IType = Int32Ty; | ||||||
429 | } | ||||||
430 | } | ||||||
431 | } | ||||||
432 | Arg = new BitCastInst(Arg, IType, "PrintArgFP", Brnch); | ||||||
433 | WhatToStore.push_back(Arg); | ||||||
434 | } else if (ArgType->getTypeID() == Type::PointerTyID) { | ||||||
435 | if (shouldPrintAsStr(OpConvSpecifiers[ArgCount - 1], ArgType)) { | ||||||
436 | const char *S = NonLiteralStr; | ||||||
437 | if (ConstantExpr *ConstExpr
| ||||||
438 | GlobalVariable *GV = | ||||||
439 | dyn_cast<GlobalVariable>(ConstExpr->getOperand(0)); | ||||||
440 | if (GV && GV->hasInitializer()) { | ||||||
441 | Constant *Init = GV->getInitializer(); | ||||||
442 | ConstantDataArray *CA = dyn_cast<ConstantDataArray>(Init); | ||||||
443 | if (Init->isZeroValue() || CA->isString()) { | ||||||
| |||||||
444 | S = Init->isZeroValue() ? "" : CA->getAsCString().data(); | ||||||
445 | } | ||||||
446 | } | ||||||
447 | } | ||||||
448 | size_t SizeStr = strlen(S) + 1; | ||||||
449 | size_t Rem = SizeStr % DWORD_ALIGN4; | ||||||
450 | size_t NSizeStr = 0; | ||||||
451 | if (Rem) { | ||||||
452 | NSizeStr = SizeStr + (DWORD_ALIGN4 - Rem); | ||||||
453 | } else { | ||||||
454 | NSizeStr = SizeStr; | ||||||
455 | } | ||||||
456 | if (S[0]) { | ||||||
457 | char *MyNewStr = new char[NSizeStr](); | ||||||
458 | strcpy(MyNewStr, S); | ||||||
459 | int NumInts = NSizeStr / 4; | ||||||
460 | int CharC = 0; | ||||||
461 | while (NumInts) { | ||||||
462 | int ANum = *(int *)(MyNewStr + CharC); | ||||||
463 | CharC += 4; | ||||||
464 | NumInts--; | ||||||
465 | Value *ANumV = ConstantInt::get(Int32Ty, ANum, false); | ||||||
466 | WhatToStore.push_back(ANumV); | ||||||
467 | } | ||||||
468 | delete[] MyNewStr; | ||||||
469 | } else { | ||||||
470 | // Empty string, give a hint to RT it is no NULL | ||||||
471 | Value *ANumV = ConstantInt::get(Int32Ty, 0xFFFFFF00, false); | ||||||
472 | WhatToStore.push_back(ANumV); | ||||||
473 | } | ||||||
474 | } else { | ||||||
475 | uint64_t Size = TD->getTypeAllocSizeInBits(ArgType); | ||||||
476 | assert((Size == 32 || Size == 64) && "unsupported size")(((Size == 32 || Size == 64) && "unsupported size") ? static_cast<void> (0) : __assert_fail ("(Size == 32 || Size == 64) && \"unsupported size\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/AMDGPU/AMDGPUPrintfRuntimeBinding.cpp" , 476, __PRETTY_FUNCTION__)); | ||||||
477 | Type *DstType = (Size == 32) ? Int32Ty : Int64Ty; | ||||||
478 | Arg = new PtrToIntInst(Arg, DstType, "PrintArgPtr", Brnch); | ||||||
479 | WhatToStore.push_back(Arg); | ||||||
480 | } | ||||||
481 | } else if (ArgType->getTypeID() == Type::VectorTyID) { | ||||||
482 | Type *IType = NULL__null; | ||||||
483 | uint32_t EleCount = cast<VectorType>(ArgType)->getNumElements(); | ||||||
484 | uint32_t EleSize = ArgType->getScalarSizeInBits(); | ||||||
485 | uint32_t TotalSize = EleCount * EleSize; | ||||||
486 | if (EleCount == 3) { | ||||||
487 | IntegerType *Int32Ty = Type::getInt32Ty(ArgType->getContext()); | ||||||
488 | Constant *Indices[4] = { | ||||||
489 | ConstantInt::get(Int32Ty, 0), ConstantInt::get(Int32Ty, 1), | ||||||
490 | ConstantInt::get(Int32Ty, 2), ConstantInt::get(Int32Ty, 2)}; | ||||||
491 | Constant *Mask = ConstantVector::get(Indices); | ||||||
492 | ShuffleVectorInst *Shuffle = new ShuffleVectorInst(Arg, Arg, Mask); | ||||||
493 | Shuffle->insertBefore(Brnch); | ||||||
494 | Arg = Shuffle; | ||||||
495 | ArgType = Arg->getType(); | ||||||
496 | TotalSize += EleSize; | ||||||
497 | } | ||||||
498 | switch (EleSize) { | ||||||
499 | default: | ||||||
500 | EleCount = TotalSize / 64; | ||||||
501 | IType = dyn_cast<Type>(Type::getInt64Ty(ArgType->getContext())); | ||||||
502 | break; | ||||||
503 | case 8: | ||||||
504 | if (EleCount >= 8) { | ||||||
505 | EleCount = TotalSize / 64; | ||||||
506 | IType = dyn_cast<Type>(Type::getInt64Ty(ArgType->getContext())); | ||||||
507 | } else if (EleCount >= 3) { | ||||||
508 | EleCount = 1; | ||||||
509 | IType = dyn_cast<Type>(Type::getInt32Ty(ArgType->getContext())); | ||||||
510 | } else { | ||||||
511 | EleCount = 1; | ||||||
512 | IType = dyn_cast<Type>(Type::getInt16Ty(ArgType->getContext())); | ||||||
513 | } | ||||||
514 | break; | ||||||
515 | case 16: | ||||||
516 | if (EleCount >= 3) { | ||||||
517 | EleCount = TotalSize / 64; | ||||||
518 | IType = dyn_cast<Type>(Type::getInt64Ty(ArgType->getContext())); | ||||||
519 | } else { | ||||||
520 | EleCount = 1; | ||||||
521 | IType = dyn_cast<Type>(Type::getInt32Ty(ArgType->getContext())); | ||||||
522 | } | ||||||
523 | break; | ||||||
524 | } | ||||||
525 | if (EleCount > 1) { | ||||||
526 | IType = dyn_cast<Type>(VectorType::get(IType, EleCount)); | ||||||
527 | } | ||||||
528 | Arg = new BitCastInst(Arg, IType, "PrintArgVect", Brnch); | ||||||
529 | WhatToStore.push_back(Arg); | ||||||
530 | } else { | ||||||
531 | WhatToStore.push_back(Arg); | ||||||
532 | } | ||||||
533 | for (unsigned I = 0, E = WhatToStore.size(); I != E; ++I) { | ||||||
534 | Value *TheBtCast = WhatToStore[I]; | ||||||
535 | unsigned ArgSize = | ||||||
536 | TD->getTypeAllocSizeInBits(TheBtCast->getType()) / 8; | ||||||
537 | SmallVector<Value *, 1> BuffOffset; | ||||||
538 | BuffOffset.push_back(ConstantInt::get(I32Ty, ArgSize)); | ||||||
539 | |||||||
540 | Type *ArgPointer = PointerType::get(TheBtCast->getType(), 1); | ||||||
541 | Value *CastedGEP = | ||||||
542 | new BitCastInst(BufferIdx, ArgPointer, "PrintBuffPtrCast", Brnch); | ||||||
543 | StoreInst *StBuff = new StoreInst(TheBtCast, CastedGEP, Brnch); | ||||||
544 | LLVM_DEBUG(dbgs() << "inserting store to printf buffer:\n"do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("printfToRuntime")) { dbgs() << "inserting store to printf buffer:\n" << *StBuff << '\n'; } } while (false) | ||||||
545 | << *StBuff << '\n')do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("printfToRuntime")) { dbgs() << "inserting store to printf buffer:\n" << *StBuff << '\n'; } } while (false); | ||||||
546 | (void)StBuff; | ||||||
547 | if (I + 1 == E && ArgCount + 1 == CI->getNumArgOperands()) | ||||||
548 | break; | ||||||
549 | BufferIdx = dyn_cast<GetElementPtrInst>(GetElementPtrInst::Create( | ||||||
550 | nullptr, BufferIdx, BuffOffset, "PrintBuffNextPtr", Brnch)); | ||||||
551 | LLVM_DEBUG(dbgs() << "inserting gep to the printf buffer:\n"do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("printfToRuntime")) { dbgs() << "inserting gep to the printf buffer:\n" << *BufferIdx << '\n'; } } while (false) | ||||||
552 | << *BufferIdx << '\n')do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("printfToRuntime")) { dbgs() << "inserting gep to the printf buffer:\n" << *BufferIdx << '\n'; } } while (false); | ||||||
553 | } | ||||||
554 | } | ||||||
555 | } | ||||||
556 | } | ||||||
557 | |||||||
558 | // erase the printf calls | ||||||
559 | for (auto CI : Printfs) | ||||||
560 | CI->eraseFromParent(); | ||||||
561 | |||||||
562 | Printfs.clear(); | ||||||
563 | return true; | ||||||
564 | } | ||||||
565 | |||||||
566 | bool AMDGPUPrintfRuntimeBinding::runOnModule(Module &M) { | ||||||
567 | Triple TT(M.getTargetTriple()); | ||||||
568 | if (TT.getArch() == Triple::r600) | ||||||
569 | return false; | ||||||
570 | |||||||
571 | auto PrintfFunction = M.getFunction("printf"); | ||||||
572 | if (!PrintfFunction) | ||||||
573 | return false; | ||||||
574 | |||||||
575 | for (auto &U : PrintfFunction->uses()) { | ||||||
576 | if (auto *CI = dyn_cast<CallInst>(U.getUser())) { | ||||||
577 | if (CI->isCallee(&U)) | ||||||
578 | Printfs.push_back(CI); | ||||||
579 | } | ||||||
580 | } | ||||||
581 | |||||||
582 | if (Printfs.empty()) | ||||||
583 | return false; | ||||||
584 | |||||||
585 | if (auto HostcallFunction = M.getFunction("__ockl_hostcall_internal")) { | ||||||
586 | for (auto &U : HostcallFunction->uses()) { | ||||||
587 | if (auto *CI = dyn_cast<CallInst>(U.getUser())) { | ||||||
588 | M.getContext().emitError( | ||||||
589 | CI, "Cannot use both printf and hostcall in the same module"); | ||||||
590 | } | ||||||
591 | } | ||||||
592 | } | ||||||
593 | |||||||
594 | TD = &M.getDataLayout(); | ||||||
595 | auto DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>(); | ||||||
596 | DT = DTWP ? &DTWP->getDomTree() : nullptr; | ||||||
597 | auto GetTLI = [this](Function &F) -> TargetLibraryInfo & { | ||||||
598 | return this->getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F); | ||||||
599 | }; | ||||||
600 | |||||||
601 | return lowerPrintfForGpu(M, GetTLI); | ||||||
602 | } |
1 | //===- llvm/Type.h - Classes for handling data types ------------*- 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 Type class. For more "Type" |
10 | // stuff, look in DerivedTypes.h. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef LLVM_IR_TYPE_H |
15 | #define LLVM_IR_TYPE_H |
16 | |
17 | #include "llvm/ADT/APFloat.h" |
18 | #include "llvm/ADT/ArrayRef.h" |
19 | #include "llvm/ADT/SmallPtrSet.h" |
20 | #include "llvm/Support/CBindingWrapping.h" |
21 | #include "llvm/Support/Casting.h" |
22 | #include "llvm/Support/Compiler.h" |
23 | #include "llvm/Support/ErrorHandling.h" |
24 | #include "llvm/Support/TypeSize.h" |
25 | #include <cassert> |
26 | #include <cstdint> |
27 | #include <iterator> |
28 | |
29 | namespace llvm { |
30 | |
31 | template<class GraphType> struct GraphTraits; |
32 | class IntegerType; |
33 | class LLVMContext; |
34 | class PointerType; |
35 | class raw_ostream; |
36 | class StringRef; |
37 | |
38 | /// The instances of the Type class are immutable: once they are created, |
39 | /// they are never changed. Also note that only one instance of a particular |
40 | /// type is ever created. Thus seeing if two types are equal is a matter of |
41 | /// doing a trivial pointer comparison. To enforce that no two equal instances |
42 | /// are created, Type instances can only be created via static factory methods |
43 | /// in class Type and in derived classes. Once allocated, Types are never |
44 | /// free'd. |
45 | /// |
46 | class Type { |
47 | public: |
48 | //===--------------------------------------------------------------------===// |
49 | /// Definitions of all of the base types for the Type system. Based on this |
50 | /// value, you can cast to a class defined in DerivedTypes.h. |
51 | /// Note: If you add an element to this, you need to add an element to the |
52 | /// Type::getPrimitiveType function, or else things will break! |
53 | /// Also update LLVMTypeKind and LLVMGetTypeKind () in the C binding. |
54 | /// |
55 | enum TypeID { |
56 | // PrimitiveTypes - make sure LastPrimitiveTyID stays up to date. |
57 | VoidTyID = 0, ///< 0: type with no size |
58 | HalfTyID, ///< 1: 16-bit floating point type |
59 | FloatTyID, ///< 2: 32-bit floating point type |
60 | DoubleTyID, ///< 3: 64-bit floating point type |
61 | X86_FP80TyID, ///< 4: 80-bit floating point type (X87) |
62 | FP128TyID, ///< 5: 128-bit floating point type (112-bit mantissa) |
63 | PPC_FP128TyID, ///< 6: 128-bit floating point type (two 64-bits, PowerPC) |
64 | LabelTyID, ///< 7: Labels |
65 | MetadataTyID, ///< 8: Metadata |
66 | X86_MMXTyID, ///< 9: MMX vectors (64 bits, X86 specific) |
67 | TokenTyID, ///< 10: Tokens |
68 | |
69 | // Derived types... see DerivedTypes.h file. |
70 | // Make sure FirstDerivedTyID stays up to date! |
71 | IntegerTyID, ///< 11: Arbitrary bit width integers |
72 | FunctionTyID, ///< 12: Functions |
73 | StructTyID, ///< 13: Structures |
74 | ArrayTyID, ///< 14: Arrays |
75 | PointerTyID, ///< 15: Pointers |
76 | VectorTyID ///< 16: SIMD 'packed' format, or other vector type |
77 | }; |
78 | |
79 | private: |
80 | /// This refers to the LLVMContext in which this type was uniqued. |
81 | LLVMContext &Context; |
82 | |
83 | TypeID ID : 8; // The current base type of this type. |
84 | unsigned SubclassData : 24; // Space for subclasses to store data. |
85 | // Note that this should be synchronized with |
86 | // MAX_INT_BITS value in IntegerType class. |
87 | |
88 | protected: |
89 | friend class LLVMContextImpl; |
90 | |
91 | explicit Type(LLVMContext &C, TypeID tid) |
92 | : Context(C), ID(tid), SubclassData(0) {} |
93 | ~Type() = default; |
94 | |
95 | unsigned getSubclassData() const { return SubclassData; } |
96 | |
97 | void setSubclassData(unsigned val) { |
98 | SubclassData = val; |
99 | // Ensure we don't have any accidental truncation. |
100 | assert(getSubclassData() == val && "Subclass data too large for field")((getSubclassData() == val && "Subclass data too large for field" ) ? static_cast<void> (0) : __assert_fail ("getSubclassData() == val && \"Subclass data too large for field\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/include/llvm/IR/Type.h" , 100, __PRETTY_FUNCTION__)); |
101 | } |
102 | |
103 | /// Keeps track of how many Type*'s there are in the ContainedTys list. |
104 | unsigned NumContainedTys = 0; |
105 | |
106 | /// A pointer to the array of Types contained by this Type. For example, this |
107 | /// includes the arguments of a function type, the elements of a structure, |
108 | /// the pointee of a pointer, the element type of an array, etc. This pointer |
109 | /// may be 0 for types that don't contain other types (Integer, Double, |
110 | /// Float). |
111 | Type * const *ContainedTys = nullptr; |
112 | |
113 | static bool isSequentialType(TypeID TyID) { |
114 | return TyID == ArrayTyID || TyID == VectorTyID; |
115 | } |
116 | |
117 | public: |
118 | /// Print the current type. |
119 | /// Omit the type details if \p NoDetails == true. |
120 | /// E.g., let %st = type { i32, i16 } |
121 | /// When \p NoDetails is true, we only print %st. |
122 | /// Put differently, \p NoDetails prints the type as if |
123 | /// inlined with the operands when printing an instruction. |
124 | void print(raw_ostream &O, bool IsForDebug = false, |
125 | bool NoDetails = false) const; |
126 | |
127 | void dump() const; |
128 | |
129 | /// Return the LLVMContext in which this type was uniqued. |
130 | LLVMContext &getContext() const { return Context; } |
131 | |
132 | //===--------------------------------------------------------------------===// |
133 | // Accessors for working with types. |
134 | // |
135 | |
136 | /// Return the type id for the type. This will return one of the TypeID enum |
137 | /// elements defined above. |
138 | TypeID getTypeID() const { return ID; } |
139 | |
140 | /// Return true if this is 'void'. |
141 | bool isVoidTy() const { return getTypeID() == VoidTyID; } |
142 | |
143 | /// Return true if this is 'half', a 16-bit IEEE fp type. |
144 | bool isHalfTy() const { return getTypeID() == HalfTyID; } |
145 | |
146 | /// Return true if this is 'float', a 32-bit IEEE fp type. |
147 | bool isFloatTy() const { return getTypeID() == FloatTyID; } |
148 | |
149 | /// Return true if this is 'double', a 64-bit IEEE fp type. |
150 | bool isDoubleTy() const { return getTypeID() == DoubleTyID; } |
151 | |
152 | /// Return true if this is x86 long double. |
153 | bool isX86_FP80Ty() const { return getTypeID() == X86_FP80TyID; } |
154 | |
155 | /// Return true if this is 'fp128'. |
156 | bool isFP128Ty() const { return getTypeID() == FP128TyID; } |
157 | |
158 | /// Return true if this is powerpc long double. |
159 | bool isPPC_FP128Ty() const { return getTypeID() == PPC_FP128TyID; } |
160 | |
161 | /// Return true if this is one of the six floating-point types |
162 | bool isFloatingPointTy() const { |
163 | return getTypeID() == HalfTyID || getTypeID() == FloatTyID || |
164 | getTypeID() == DoubleTyID || |
165 | getTypeID() == X86_FP80TyID || getTypeID() == FP128TyID || |
166 | getTypeID() == PPC_FP128TyID; |
167 | } |
168 | |
169 | const fltSemantics &getFltSemantics() const { |
170 | switch (getTypeID()) { |
171 | case HalfTyID: return APFloat::IEEEhalf(); |
172 | case FloatTyID: return APFloat::IEEEsingle(); |
173 | case DoubleTyID: return APFloat::IEEEdouble(); |
174 | case X86_FP80TyID: return APFloat::x87DoubleExtended(); |
175 | case FP128TyID: return APFloat::IEEEquad(); |
176 | case PPC_FP128TyID: return APFloat::PPCDoubleDouble(); |
177 | default: llvm_unreachable("Invalid floating type")::llvm::llvm_unreachable_internal("Invalid floating type", "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/include/llvm/IR/Type.h" , 177); |
178 | } |
179 | } |
180 | |
181 | /// Return true if this is X86 MMX. |
182 | bool isX86_MMXTy() const { return getTypeID() == X86_MMXTyID; } |
183 | |
184 | /// Return true if this is a FP type or a vector of FP. |
185 | bool isFPOrFPVectorTy() const { return getScalarType()->isFloatingPointTy(); } |
186 | |
187 | /// Return true if this is 'label'. |
188 | bool isLabelTy() const { return getTypeID() == LabelTyID; } |
189 | |
190 | /// Return true if this is 'metadata'. |
191 | bool isMetadataTy() const { return getTypeID() == MetadataTyID; } |
192 | |
193 | /// Return true if this is 'token'. |
194 | bool isTokenTy() const { return getTypeID() == TokenTyID; } |
195 | |
196 | /// True if this is an instance of IntegerType. |
197 | bool isIntegerTy() const { return getTypeID() == IntegerTyID; } |
198 | |
199 | /// Return true if this is an IntegerType of the given width. |
200 | bool isIntegerTy(unsigned Bitwidth) const; |
201 | |
202 | /// Return true if this is an integer type or a vector of integer types. |
203 | bool isIntOrIntVectorTy() const { return getScalarType()->isIntegerTy(); } |
204 | |
205 | /// Return true if this is an integer type or a vector of integer types of |
206 | /// the given width. |
207 | bool isIntOrIntVectorTy(unsigned BitWidth) const { |
208 | return getScalarType()->isIntegerTy(BitWidth); |
209 | } |
210 | |
211 | /// Return true if this is an integer type or a pointer type. |
212 | bool isIntOrPtrTy() const { return isIntegerTy() || isPointerTy(); } |
213 | |
214 | /// True if this is an instance of FunctionType. |
215 | bool isFunctionTy() const { return getTypeID() == FunctionTyID; } |
216 | |
217 | /// True if this is an instance of StructType. |
218 | bool isStructTy() const { return getTypeID() == StructTyID; } |
219 | |
220 | /// True if this is an instance of ArrayType. |
221 | bool isArrayTy() const { return getTypeID() == ArrayTyID; } |
222 | |
223 | /// True if this is an instance of PointerType. |
224 | bool isPointerTy() const { return getTypeID() == PointerTyID; } |
225 | |
226 | /// Return true if this is a pointer type or a vector of pointer types. |
227 | bool isPtrOrPtrVectorTy() const { return getScalarType()->isPointerTy(); } |
228 | |
229 | /// True if this is an instance of VectorType. |
230 | bool isVectorTy() const { return getTypeID() == VectorTyID; } |
231 | |
232 | /// Return true if this type could be converted with a lossless BitCast to |
233 | /// type 'Ty'. For example, i8* to i32*. BitCasts are valid for types of the |
234 | /// same size only where no re-interpretation of the bits is done. |
235 | /// Determine if this type could be losslessly bitcast to Ty |
236 | bool canLosslesslyBitCastTo(Type *Ty) const; |
237 | |
238 | /// Return true if this type is empty, that is, it has no elements or all of |
239 | /// its elements are empty. |
240 | bool isEmptyTy() const; |
241 | |
242 | /// Return true if the type is "first class", meaning it is a valid type for a |
243 | /// Value. |
244 | bool isFirstClassType() const { |
245 | return getTypeID() != FunctionTyID && getTypeID() != VoidTyID; |
246 | } |
247 | |
248 | /// Return true if the type is a valid type for a register in codegen. This |
249 | /// includes all first-class types except struct and array types. |
250 | bool isSingleValueType() const { |
251 | return isFloatingPointTy() || isX86_MMXTy() || isIntegerTy() || |
252 | isPointerTy() || isVectorTy(); |
253 | } |
254 | |
255 | /// Return true if the type is an aggregate type. This means it is valid as |
256 | /// the first operand of an insertvalue or extractvalue instruction. This |
257 | /// includes struct and array types, but does not include vector types. |
258 | bool isAggregateType() const { |
259 | return getTypeID() == StructTyID || getTypeID() == ArrayTyID; |
260 | } |
261 | |
262 | /// Return true if it makes sense to take the size of this type. To get the |
263 | /// actual size for a particular target, it is reasonable to use the |
264 | /// DataLayout subsystem to do this. |
265 | bool isSized(SmallPtrSetImpl<Type*> *Visited = nullptr) const { |
266 | // If it's a primitive, it is always sized. |
267 | if (getTypeID() == IntegerTyID || isFloatingPointTy() || |
268 | getTypeID() == PointerTyID || |
269 | getTypeID() == X86_MMXTyID) |
270 | return true; |
271 | // If it is not something that can have a size (e.g. a function or label), |
272 | // it doesn't have a size. |
273 | if (getTypeID() != StructTyID && getTypeID() != ArrayTyID && |
274 | getTypeID() != VectorTyID) |
275 | return false; |
276 | // Otherwise we have to try harder to decide. |
277 | return isSizedDerivedType(Visited); |
278 | } |
279 | |
280 | /// Return the basic size of this type if it is a primitive type. These are |
281 | /// fixed by LLVM and are not target-dependent. |
282 | /// This will return zero if the type does not have a size or is not a |
283 | /// primitive type. |
284 | /// |
285 | /// If this is a scalable vector type, the scalable property will be set and |
286 | /// the runtime size will be a positive integer multiple of the base size. |
287 | /// |
288 | /// Note that this may not reflect the size of memory allocated for an |
289 | /// instance of the type or the number of bytes that are written when an |
290 | /// instance of the type is stored to memory. The DataLayout class provides |
291 | /// additional query functions to provide this information. |
292 | /// |
293 | TypeSize getPrimitiveSizeInBits() const LLVM_READONLY__attribute__((__pure__)); |
294 | |
295 | /// If this is a vector type, return the getPrimitiveSizeInBits value for the |
296 | /// element type. Otherwise return the getPrimitiveSizeInBits value for this |
297 | /// type. |
298 | unsigned getScalarSizeInBits() const LLVM_READONLY__attribute__((__pure__)); |
299 | |
300 | /// Return the width of the mantissa of this type. This is only valid on |
301 | /// floating-point types. If the FP type does not have a stable mantissa (e.g. |
302 | /// ppc long double), this method returns -1. |
303 | int getFPMantissaWidth() const; |
304 | |
305 | /// If this is a vector type, return the element type, otherwise return |
306 | /// 'this'. |
307 | Type *getScalarType() const { |
308 | if (isVectorTy()) |
309 | return getVectorElementType(); |
310 | return const_cast<Type*>(this); |
311 | } |
312 | |
313 | //===--------------------------------------------------------------------===// |
314 | // Type Iteration support. |
315 | // |
316 | using subtype_iterator = Type * const *; |
317 | |
318 | subtype_iterator subtype_begin() const { return ContainedTys; } |
319 | subtype_iterator subtype_end() const { return &ContainedTys[NumContainedTys];} |
320 | ArrayRef<Type*> subtypes() const { |
321 | return makeArrayRef(subtype_begin(), subtype_end()); |
322 | } |
323 | |
324 | using subtype_reverse_iterator = std::reverse_iterator<subtype_iterator>; |
325 | |
326 | subtype_reverse_iterator subtype_rbegin() const { |
327 | return subtype_reverse_iterator(subtype_end()); |
328 | } |
329 | subtype_reverse_iterator subtype_rend() const { |
330 | return subtype_reverse_iterator(subtype_begin()); |
331 | } |
332 | |
333 | /// This method is used to implement the type iterator (defined at the end of |
334 | /// the file). For derived types, this returns the types 'contained' in the |
335 | /// derived type. |
336 | Type *getContainedType(unsigned i) const { |
337 | assert(i < NumContainedTys && "Index out of range!")((i < NumContainedTys && "Index out of range!") ? static_cast <void> (0) : __assert_fail ("i < NumContainedTys && \"Index out of range!\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/include/llvm/IR/Type.h" , 337, __PRETTY_FUNCTION__)); |
338 | return ContainedTys[i]; |
339 | } |
340 | |
341 | /// Return the number of types in the derived type. |
342 | unsigned getNumContainedTypes() const { return NumContainedTys; } |
343 | |
344 | //===--------------------------------------------------------------------===// |
345 | // Helper methods corresponding to subclass methods. This forces a cast to |
346 | // the specified subclass and calls its accessor. "getVectorNumElements" (for |
347 | // example) is shorthand for cast<VectorType>(Ty)->getNumElements(). This is |
348 | // only intended to cover the core methods that are frequently used, helper |
349 | // methods should not be added here. |
350 | |
351 | inline unsigned getIntegerBitWidth() const; |
352 | |
353 | inline Type *getFunctionParamType(unsigned i) const; |
354 | inline unsigned getFunctionNumParams() const; |
355 | inline bool isFunctionVarArg() const; |
356 | |
357 | inline StringRef getStructName() const; |
358 | inline unsigned getStructNumElements() const; |
359 | inline Type *getStructElementType(unsigned N) const; |
360 | |
361 | inline Type *getSequentialElementType() const { |
362 | assert(isSequentialType(getTypeID()) && "Not a sequential type!")((isSequentialType(getTypeID()) && "Not a sequential type!" ) ? static_cast<void> (0) : __assert_fail ("isSequentialType(getTypeID()) && \"Not a sequential type!\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/include/llvm/IR/Type.h" , 362, __PRETTY_FUNCTION__)); |
363 | return ContainedTys[0]; |
364 | } |
365 | |
366 | inline uint64_t getArrayNumElements() const; |
367 | |
368 | Type *getArrayElementType() const { |
369 | assert(getTypeID() == ArrayTyID)((getTypeID() == ArrayTyID) ? static_cast<void> (0) : __assert_fail ("getTypeID() == ArrayTyID", "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/include/llvm/IR/Type.h" , 369, __PRETTY_FUNCTION__)); |
370 | return ContainedTys[0]; |
371 | } |
372 | |
373 | inline bool getVectorIsScalable() const; |
374 | inline unsigned getVectorNumElements() const; |
375 | inline ElementCount getVectorElementCount() const; |
376 | Type *getVectorElementType() const { |
377 | assert(getTypeID() == VectorTyID)((getTypeID() == VectorTyID) ? static_cast<void> (0) : __assert_fail ("getTypeID() == VectorTyID", "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/include/llvm/IR/Type.h" , 377, __PRETTY_FUNCTION__)); |
378 | return ContainedTys[0]; |
379 | } |
380 | |
381 | Type *getPointerElementType() const { |
382 | assert(getTypeID() == PointerTyID)((getTypeID() == PointerTyID) ? static_cast<void> (0) : __assert_fail ("getTypeID() == PointerTyID", "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/include/llvm/IR/Type.h" , 382, __PRETTY_FUNCTION__)); |
383 | return ContainedTys[0]; |
384 | } |
385 | |
386 | /// Given an integer or vector type, change the lane bitwidth to NewBitwidth, |
387 | /// whilst keeping the old number of lanes. |
388 | inline Type *getWithNewBitWidth(unsigned NewBitWidth) const; |
389 | |
390 | /// Given scalar/vector integer type, returns a type with elements twice as |
391 | /// wide as in the original type. For vectors, preserves element count. |
392 | inline Type *getExtendedType() const; |
393 | |
394 | /// Get the address space of this pointer or pointer vector type. |
395 | inline unsigned getPointerAddressSpace() const; |
396 | |
397 | //===--------------------------------------------------------------------===// |
398 | // Static members exported by the Type class itself. Useful for getting |
399 | // instances of Type. |
400 | // |
401 | |
402 | /// Return a type based on an identifier. |
403 | static Type *getPrimitiveType(LLVMContext &C, TypeID IDNumber); |
404 | |
405 | //===--------------------------------------------------------------------===// |
406 | // These are the builtin types that are always available. |
407 | // |
408 | static Type *getVoidTy(LLVMContext &C); |
409 | static Type *getLabelTy(LLVMContext &C); |
410 | static Type *getHalfTy(LLVMContext &C); |
411 | static Type *getFloatTy(LLVMContext &C); |
412 | static Type *getDoubleTy(LLVMContext &C); |
413 | static Type *getMetadataTy(LLVMContext &C); |
414 | static Type *getX86_FP80Ty(LLVMContext &C); |
415 | static Type *getFP128Ty(LLVMContext &C); |
416 | static Type *getPPC_FP128Ty(LLVMContext &C); |
417 | static Type *getX86_MMXTy(LLVMContext &C); |
418 | static Type *getTokenTy(LLVMContext &C); |
419 | static IntegerType *getIntNTy(LLVMContext &C, unsigned N); |
420 | static IntegerType *getInt1Ty(LLVMContext &C); |
421 | static IntegerType *getInt8Ty(LLVMContext &C); |
422 | static IntegerType *getInt16Ty(LLVMContext &C); |
423 | static IntegerType *getInt32Ty(LLVMContext &C); |
424 | static IntegerType *getInt64Ty(LLVMContext &C); |
425 | static IntegerType *getInt128Ty(LLVMContext &C); |
426 | template <typename ScalarTy> static Type *getScalarTy(LLVMContext &C) { |
427 | int noOfBits = sizeof(ScalarTy) * CHAR_BIT8; |
428 | if (std::is_integral<ScalarTy>::value) { |
429 | return (Type*) Type::getIntNTy(C, noOfBits); |
430 | } else if (std::is_floating_point<ScalarTy>::value) { |
431 | switch (noOfBits) { |
432 | case 32: |
433 | return Type::getFloatTy(C); |
434 | case 64: |
435 | return Type::getDoubleTy(C); |
436 | } |
437 | } |
438 | llvm_unreachable("Unsupported type in Type::getScalarTy")::llvm::llvm_unreachable_internal("Unsupported type in Type::getScalarTy" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/include/llvm/IR/Type.h" , 438); |
439 | } |
440 | |
441 | //===--------------------------------------------------------------------===// |
442 | // Convenience methods for getting pointer types with one of the above builtin |
443 | // types as pointee. |
444 | // |
445 | static PointerType *getHalfPtrTy(LLVMContext &C, unsigned AS = 0); |
446 | static PointerType *getFloatPtrTy(LLVMContext &C, unsigned AS = 0); |
447 | static PointerType *getDoublePtrTy(LLVMContext &C, unsigned AS = 0); |
448 | static PointerType *getX86_FP80PtrTy(LLVMContext &C, unsigned AS = 0); |
449 | static PointerType *getFP128PtrTy(LLVMContext &C, unsigned AS = 0); |
450 | static PointerType *getPPC_FP128PtrTy(LLVMContext &C, unsigned AS = 0); |
451 | static PointerType *getX86_MMXPtrTy(LLVMContext &C, unsigned AS = 0); |
452 | static PointerType *getIntNPtrTy(LLVMContext &C, unsigned N, unsigned AS = 0); |
453 | static PointerType *getInt1PtrTy(LLVMContext &C, unsigned AS = 0); |
454 | static PointerType *getInt8PtrTy(LLVMContext &C, unsigned AS = 0); |
455 | static PointerType *getInt16PtrTy(LLVMContext &C, unsigned AS = 0); |
456 | static PointerType *getInt32PtrTy(LLVMContext &C, unsigned AS = 0); |
457 | static PointerType *getInt64PtrTy(LLVMContext &C, unsigned AS = 0); |
458 | |
459 | /// Return a pointer to the current type. This is equivalent to |
460 | /// PointerType::get(Foo, AddrSpace). |
461 | PointerType *getPointerTo(unsigned AddrSpace = 0) const; |
462 | |
463 | private: |
464 | /// Derived types like structures and arrays are sized iff all of the members |
465 | /// of the type are sized as well. Since asking for their size is relatively |
466 | /// uncommon, move this operation out-of-line. |
467 | bool isSizedDerivedType(SmallPtrSetImpl<Type*> *Visited = nullptr) const; |
468 | }; |
469 | |
470 | // Printing of types. |
471 | inline raw_ostream &operator<<(raw_ostream &OS, const Type &T) { |
472 | T.print(OS); |
473 | return OS; |
474 | } |
475 | |
476 | // allow isa<PointerType>(x) to work without DerivedTypes.h included. |
477 | template <> struct isa_impl<PointerType, Type> { |
478 | static inline bool doit(const Type &Ty) { |
479 | return Ty.getTypeID() == Type::PointerTyID; |
480 | } |
481 | }; |
482 | |
483 | // Create wrappers for C Binding types (see CBindingWrapping.h). |
484 | DEFINE_ISA_CONVERSION_FUNCTIONS(Type, LLVMTypeRef)inline Type *unwrap(LLVMTypeRef P) { return reinterpret_cast< Type*>(P); } inline LLVMTypeRef wrap(const Type *P) { return reinterpret_cast<LLVMTypeRef>(const_cast<Type*>( P)); } template<typename T> inline T *unwrap(LLVMTypeRef P) { return cast<T>(unwrap(P)); } |
485 | |
486 | /* Specialized opaque type conversions. |
487 | */ |
488 | inline Type **unwrap(LLVMTypeRef* Tys) { |
489 | return reinterpret_cast<Type**>(Tys); |
490 | } |
491 | |
492 | inline LLVMTypeRef *wrap(Type **Tys) { |
493 | return reinterpret_cast<LLVMTypeRef*>(const_cast<Type**>(Tys)); |
494 | } |
495 | |
496 | } // end namespace llvm |
497 | |
498 | #endif // LLVM_IR_TYPE_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/PointerUnion.h" |
23 | #include "llvm/ADT/Twine.h" |
24 | #include "llvm/ADT/ilist_node.h" |
25 | #include "llvm/IR/Attributes.h" |
26 | #include "llvm/IR/GlobalObject.h" |
27 | #include "llvm/IR/OperandTraits.h" |
28 | #include "llvm/IR/Value.h" |
29 | #include <cassert> |
30 | #include <cstddef> |
31 | |
32 | namespace llvm { |
33 | |
34 | class Constant; |
35 | class Module; |
36 | |
37 | template <typename ValueSubClass> class SymbolTableListTraits; |
38 | class DIGlobalVariable; |
39 | class DIGlobalVariableExpression; |
40 | |
41 | class GlobalVariable : public GlobalObject, public ilist_node<GlobalVariable> { |
42 | friend class SymbolTableListTraits<GlobalVariable>; |
43 | |
44 | AttributeSet Attrs; |
45 | bool isConstantGlobal : 1; // Is this a global constant? |
46 | bool isExternallyInitializedConstant : 1; // Is this a global whose value |
47 | // can change from its initial |
48 | // value before global |
49 | // initializers are run? |
50 | |
51 | public: |
52 | /// GlobalVariable ctor - If a parent module is specified, the global is |
53 | /// automatically inserted into the end of the specified modules global list. |
54 | GlobalVariable(Type *Ty, bool isConstant, LinkageTypes Linkage, |
55 | Constant *Initializer = nullptr, const Twine &Name = "", |
56 | ThreadLocalMode = NotThreadLocal, unsigned AddressSpace = 0, |
57 | bool isExternallyInitialized = false); |
58 | /// GlobalVariable ctor - This creates a global and inserts it before the |
59 | /// specified other global. |
60 | GlobalVariable(Module &M, Type *Ty, bool isConstant, |
61 | LinkageTypes Linkage, Constant *Initializer, |
62 | const Twine &Name = "", GlobalVariable *InsertBefore = nullptr, |
63 | ThreadLocalMode = NotThreadLocal, unsigned AddressSpace = 0, |
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")((ptr != nullptr && "must not be nullptr") ? static_cast <void> (0) : __assert_fail ("ptr != nullptr && \"must not be nullptr\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/include/llvm/IR/GlobalVariable.h" , 79, __PRETTY_FUNCTION__)); |
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(); } |
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!")((hasInitializer() && "GV doesn't have initializer!") ? static_cast<void> (0) : __assert_fail ("hasInitializer() && \"GV doesn't have initializer!\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/include/llvm/IR/GlobalVariable.h" , 137, __PRETTY_FUNCTION__)); |
138 | return static_cast<Constant*>(Op<0>().get()); |
139 | } |
140 | inline Constant *getInitializer() { |
141 | assert(hasInitializer() && "GV doesn't have initializer!")((hasInitializer() && "GV doesn't have initializer!") ? static_cast<void> (0) : __assert_fail ("hasInitializer() && \"GV doesn't have initializer!\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/include/llvm/IR/GlobalVariable.h" , 141, __PRETTY_FUNCTION__)); |
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 | |
256 | template <> |
257 | struct OperandTraits<GlobalVariable> : |
258 | public OptionalOperandTraits<GlobalVariable> { |
259 | }; |
260 | |
261 | DEFINE_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 { ((i_nocapture < OperandTraits<GlobalVariable>::operands(this) && "getOperand() out of range!") ? static_cast<void> (0) : __assert_fail ("i_nocapture < OperandTraits<GlobalVariable>::operands(this) && \"getOperand() out of range!\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/include/llvm/IR/GlobalVariable.h" , 261, __PRETTY_FUNCTION__)); 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) { (( i_nocapture < OperandTraits<GlobalVariable>::operands (this) && "setOperand() out of range!") ? static_cast <void> (0) : __assert_fail ("i_nocapture < OperandTraits<GlobalVariable>::operands(this) && \"setOperand() out of range!\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/include/llvm/IR/GlobalVariable.h" , 261, __PRETTY_FUNCTION__)); 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 |