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