LLVM: lib/Transforms/Utils/AMDGPUEmitPrintf.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
25
26using namespace llvm;
27
28#define DEBUG_TYPE "amdgpu-emit-printf"
29
31 auto Int64Ty = Builder.getInt64Ty();
33
35 switch (IntTy->getBitWidth()) {
36 case 32:
37 return Builder.CreateZExt(Arg, Int64Ty);
38 case 64:
39 return Arg;
40 }
41 }
42
44 return Builder.CreateBitCast(Arg, Int64Ty);
45 }
46
48 return Builder.CreatePtrToInt(Arg, Int64Ty);
49 }
50
52}
53
55 auto Int64Ty = Builder.getInt64Ty();
56 auto M = Builder.GetInsertBlock()->getModule();
57 auto Fn = M->getOrInsertFunction("__ockl_printf_begin", Int64Ty, Int64Ty);
58 return Builder.CreateCall(Fn, Version);
59}
60
64 bool IsLast) {
65 auto Int64Ty = Builder.getInt64Ty();
66 auto Int32Ty = Builder.getInt32Ty();
67 auto M = Builder.GetInsertBlock()->getModule();
68 auto Fn = M->getOrInsertFunction("__ockl_printf_append_args", Int64Ty,
69 Int64Ty, Int32Ty, Int64Ty, Int64Ty, Int64Ty,
70 Int64Ty, Int64Ty, Int64Ty, Int64Ty, Int32Ty);
71 auto IsLastValue = Builder.getInt32(IsLast);
72 auto NumArgsValue = Builder.getInt32(NumArgs);
73 return Builder.CreateCall(Fn, {Desc, NumArgsValue, Arg0, Arg1, Arg2, Arg3,
74 Arg4, Arg5, Arg6, IsLastValue});
75}
76
78 bool IsLast) {
80 auto Zero = Builder.getInt64(0);
81 return callAppendArgs(Builder, Desc, 1, Arg0, Zero, Zero, Zero, Zero, Zero,
82 Zero, IsLast);
83}
84
85
86
88 auto *Prev = Builder.GetInsertBlock();
89 Module *M = Prev->getModule();
90
91 auto CharZero = Builder.getInt8(0);
92 auto One = Builder.getInt64(1);
93 auto Zero = Builder.getInt64(0);
94 auto Int64Ty = Builder.getInt64Ty();
95
96
97
98
99
100
101
103 if (Prev->getTerminator()) {
105 "strlen.join");
107 } else {
109 Prev->getParent());
110 }
113 Prev->getParent(), Join);
115 M->getContext(), "strlen.while.done",
116 Prev->getParent(), Join);
117
118
119 Builder.SetInsertPoint(Prev);
120 auto CmpNull =
123
124
125 Builder.SetInsertPoint(While);
126
127 auto PtrPhi = Builder.CreatePHI(Str->getType(), 2);
128 PtrPhi->addIncoming(Str, Prev);
129 auto PtrNext = Builder.CreateGEP(Builder.getInt8Ty(), PtrPhi, One);
130 PtrPhi->addIncoming(PtrNext, While);
131
132
133 auto Data = Builder.CreateLoad(Builder.getInt8Ty(), PtrPhi);
134 auto Cmp = Builder.CreateICmpEQ(Data, CharZero);
135 Builder.CreateCondBr(Cmp, WhileDone, While);
136
137
138 Builder.SetInsertPoint(WhileDone, WhileDone->begin());
139 auto Begin = Builder.CreatePtrToInt(Str, Int64Ty);
140 auto End = Builder.CreatePtrToInt(PtrPhi, Int64Ty);
141 auto Len = Builder.CreateSub(End, Begin);
142 Len = Builder.CreateAdd(Len, One);
143
144
146 Builder.SetInsertPoint(Join, Join->begin());
147 auto LenPhi = Builder.CreatePHI(Len->getType(), 2);
148 LenPhi->addIncoming(Len, WhileDone);
149 LenPhi->addIncoming(Zero, Prev);
150
151 return LenPhi;
152}
153
156 auto Int64Ty = Builder.getInt64Ty();
157 auto IsLastInt32 = Builder.getInt32(isLast);
158 auto M = Builder.GetInsertBlock()->getModule();
159 auto Fn = M->getOrInsertFunction("__ockl_printf_append_string_n", Int64Ty,
160 Desc->getType(), Str->getType(),
161 Length->getType(), IsLastInt32->getType());
162 return Builder.CreateCall(Fn, {Desc, Str, Length, IsLastInt32});
163}
164
170
172 bool SpecIsCString, bool IsLast) {
175 }
176
177
178
180}
181
182
183
185 static const char ConvSpecifiers[] = "diouxXfFeEgGaAcspn";
186 size_t SpecPos = 0;
187
188 unsigned ArgIdx = 1;
189
190 while ((SpecPos = Str.find_first_of('%', SpecPos)) != StringRef::npos) {
191 if (Str[SpecPos + 1] == '%') {
192 SpecPos += 2;
193 continue;
194 }
195 auto SpecEnd = Str.find_first_of(ConvSpecifiers, SpecPos);
197 return;
198 auto Spec = Str.slice(SpecPos, SpecEnd + 1);
199 ArgIdx += Spec.count('*');
200 if (Str[SpecEnd] == 's') {
201 BV.set(ArgIdx);
202 }
203 SpecPos = SpecEnd + 1;
204 ++ArgIdx;
205 }
206}
207
208
218
219
220
221
226 Module *M = Builder.GetInsertBlock()->getModule();
227 Value *NonConstStrLen = nullptr;
228 Value *LenWithNull = nullptr;
229 Value *LenWithNullAligned = nullptr;
230 Value *TempAdd = nullptr;
231
232
233 size_t BufSize = 4;
234 if (isConstFmtStr)
235
236 BufSize += 8;
237 else {
239
240
241 TempAdd = Builder.CreateAdd(LenWithNull,
242 ConstantInt::get(LenWithNull->getType(), 7U));
243 NonConstStrLen = Builder.CreateAnd(
244 TempAdd, ConstantInt::get(LenWithNull->getType(), ~7U));
245
248 }
249
250 for (size_t i = 1; i < Args.size(); i++) {
251 if (SpecIsCString.test(i)) {
254 auto alignedLen = alignTo(ArgStr.size() + 1, 8);
256 ArgStr,
257 nullptr, nullptr, true));
258 BufSize += alignedLen;
259 } else {
261
262
263 TempAdd = Builder.CreateAdd(
264 LenWithNull, ConstantInt::get(LenWithNull->getType(), 7U));
265 LenWithNullAligned = Builder.CreateAnd(
266 TempAdd, ConstantInt::get(LenWithNull->getType(), ~7U));
267
268 if (NonConstStrLen) {
269 auto Val = Builder.CreateAdd(LenWithNullAligned, NonConstStrLen,
270 "cumulativeAdd");
271 NonConstStrLen = Val;
272 } else
273 NonConstStrLen = LenWithNullAligned;
274
277 }
278 } else {
279 int AllocSize = M->getDataLayout().getTypeAllocSize(Args[i]->getType());
280
281
282 BufSize += std::max(AllocSize, 8);
283 }
284 }
285
286
287 Value *SizeToReserve = ConstantInt::get(Builder.getInt64Ty(), BufSize, false);
289 if (NonConstStrLen)
290 SizeToReserve = Builder.CreateAdd(NonConstStrLen, SizeToReserve);
291
292 ArgSize = Builder.CreateTrunc(SizeToReserve, Builder.getInt32Ty());
294
295
296 AttributeList Attr = AttributeList::get(
297 Builder.getContext(), AttributeList::FunctionIndex, Attribute::NoUnwind);
298
299 Type *Tys_alloc[1] = {Builder.getInt32Ty()};
300 Type *PtrTy =
301 Builder.getPtrTy(M->getDataLayout().getDefaultGlobalsAddressSpace());
303 auto PrintfAllocFn =
304 M->getOrInsertFunction(StringRef("__printf_alloc"), FTy_alloc, Attr);
305
306 return Builder.CreateCall(PrintfAllocFn, Alloc_args, "printf_alloc_fn");
307}
308
309
312 std::string Str(SD->Str.str() + '\0');
313
314 DataExtractor Extractor(Str, true, 8);
316 while (Offset && Offset.tell() < Str.size()) {
318 uint64_t ReadNow = std::min(ReadSize, Str.size() - Offset.tell());
320 switch (ReadNow) {
321 default:
323 case 1:
324 ReadBytes = Extractor.getU8(Offset);
325 break;
326 case 2:
327 ReadBytes = Extractor.getU16(Offset);
328 break;
329 case 3:
330 ReadBytes = Extractor.getU24(Offset);
331 break;
332 case 4:
333 ReadBytes = Extractor.getU32(Offset);
334 break;
335 }
336 cantFail(Offset.takeError(), "failed to read bytes from constant array");
337
338 APInt IntVal(8 * ReadSize, ReadBytes);
339
340
341 if (ReadNow < ReadSize)
342 IntVal = IntVal.zext(8 * ReadSize);
343
344 Type *IntTy = Type::getIntNTy(Builder.getContext(), IntVal.getBitWidth());
345 WhatToStore.push_back(ConstantInt::get(IntTy, IntVal));
346 }
347
348 int Rem = (Str.size() % 8);
349 if (Rem > 0 && Rem <= 4)
350 WhatToStore.push_back(ConstantInt::get(Builder.getInt32Ty(), 0));
351}
352
354 const DataLayout &DL = Builder.GetInsertBlock()->getDataLayout();
355 auto Ty = Arg->getType();
356
358 if (IntTy->getBitWidth() < 64) {
359 return Builder.CreateZExt(Arg, Builder.getInt64Ty());
360 }
361 }
362
363 if (Ty->isFloatingPointTy()) {
364 if (DL.getTypeAllocSize(Ty) < 8) {
365 return Builder.CreateFPExt(Arg, Builder.getDoubleTy());
366 }
367 }
368
369 return Arg;
370}
371
372static void
376 bool IsConstFmtStr) {
377 Module *M = Builder.GetInsertBlock()->getModule();
379 auto StrIt = StringContents.begin();
380 size_t i = IsConstFmtStr ? 1 : 0;
381 for (; i < Args.size(); i++) {
383 if ((i == 0) || SpecIsCString.test(i)) {
384 if (StrIt->IsConst) {
386 StrIt++;
387 } else {
388
389
390
391
392
393 Builder.CreateMemCpy(PtrToStore, Align(1), Args[i],
394 Args[i]->getPointerAlignment(DL),
395 StrIt->RealSize);
396
397 PtrToStore =
398 Builder.CreateInBoundsGEP(Builder.getInt8Ty(), PtrToStore,
399 {StrIt->AlignedSize}, "PrintBuffNextPtr");
400 LLVM_DEBUG(dbgs() << "inserting gep to the printf buffer:"
401 << *PtrToStore << '\n');
402
403
404 StrIt++;
405 continue;
406 }
407 } else {
409 }
410
411 for (Value *toStore : WhatToStore) {
412 StoreInst *StBuff = Builder.CreateStore(toStore, PtrToStore);
413 LLVM_DEBUG(dbgs() << "inserting store to printf buffer:" << *StBuff
414 << '\n');
415 (void)StBuff;
416 PtrToStore = Builder.CreateConstInBoundsGEP1_32(
417 Builder.getInt8Ty(), PtrToStore,
418 M->getDataLayout().getTypeAllocSize(toStore->getType()),
419 "PrintBuffNextPtr");
420 LLVM_DEBUG(dbgs() << "inserting gep to the printf buffer:" << *PtrToStore
421 << '\n');
422 }
423 }
424}
425
427 bool IsBuffered) {
428 auto NumOps = Args.size();
430
431 auto Fmt = Args[0];
434
437
438 if (IsBuffered) {
440 Module *M = Builder.GetInsertBlock()->getModule();
442 auto Int8Ty = Builder.getInt8Ty();
443 auto Int32Ty = Builder.getInt32Ty();
444 bool IsConstFmtStr = !FmtStr.empty();
445
446 Value *ArgSize = nullptr;
449 SpecIsCString, StringContents, ArgSize);
450
451
452
455
456 auto *Cmp = cast(Builder.CreateICmpNE(Ptr, zeroIntPtr, ""));
457
459 Builder.GetInsertBlock()->getParent());
461 Ctx, "argpush.block", Builder.GetInsertBlock()->getParent());
462
464 Builder.SetInsertPoint(ArgPush);
465
466
467
468
469
470 auto ConstantTwo = Builder.getInt32(2);
471 auto ControlDWord = Builder.CreateShl(ArgSize, ConstantTwo);
472 if (IsConstFmtStr)
473 ControlDWord = Builder.CreateOr(ControlDWord, ConstantTwo);
474
475 Builder.CreateStore(ControlDWord, Ptr);
476
477 Ptr = Builder.CreateConstInBoundsGEP1_32(Int8Ty, Ptr, 4);
478
479
480
481 NamedMDNode *metaD = M->getOrInsertNamedMetadata("llvm.printf.fmts");
482 if (IsConstFmtStr) {
483 MD5 Hasher;
485 Hasher.update(FmtStr);
486 Hasher.final(Hash);
487
488
489
490 std::string MetadataStr =
492 FmtStr.str();
496
497 Builder.CreateStore(Builder.getInt64(Hash.low()), Ptr);
498 Ptr = Builder.CreateConstInBoundsGEP1_32(Int8Ty, Ptr, 8);
499 } else {
500
501
502
505 MDString::get(Ctx, "0:0:ffffffff,\"Non const format string\"");
508 }
509 }
510
511
513 IsConstFmtStr);
514
515
517 Builder.SetInsertPoint(End);
518 return Builder.CreateSExt(Builder.CreateNot(Cmp), Int32Ty, "printf_result");
519 }
520
523
524
525
526
527 for (unsigned int i = 1; i != NumOps; ++i) {
528 bool IsLast = i == NumOps - 1;
529 bool IsCString = SpecIsCString.test(i);
531 }
532
533 return Builder.CreateTrunc(Desc, Builder.getInt32Ty());
534}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static Value * appendString(IRBuilder<> &Builder, Value *Desc, Value *Arg, bool IsLast)
Definition AMDGPUEmitPrintf.cpp:165
static void callBufferedPrintfArgPush(IRBuilder<> &Builder, ArrayRef< Value * > Args, Value *PtrToStore, SparseBitVector< 8 > &SpecIsCString, SmallVectorImpl< StringData > &StringContents, bool IsConstFmtStr)
Definition AMDGPUEmitPrintf.cpp:373
static void processConstantStringArg(StringData *SD, IRBuilder<> &Builder, SmallVectorImpl< Value * > &WhatToStore)
Definition AMDGPUEmitPrintf.cpp:310
static Value * callBufferedPrintfStart(IRBuilder<> &Builder, ArrayRef< Value * > Args, Value *Fmt, bool isConstFmtStr, SparseBitVector< 8 > &SpecIsCString, SmallVectorImpl< StringData > &StringContents, Value *&ArgSize)
Definition AMDGPUEmitPrintf.cpp:222
static Value * callAppendArgs(IRBuilder<> &Builder, Value *Desc, int NumArgs, Value *Arg0, Value *Arg1, Value *Arg2, Value *Arg3, Value *Arg4, Value *Arg5, Value *Arg6, bool IsLast)
Definition AMDGPUEmitPrintf.cpp:61
static Value * callPrintfBegin(IRBuilder<> &Builder, Value *Version)
Definition AMDGPUEmitPrintf.cpp:54
static Value * fitArgInto64Bits(IRBuilder<> &Builder, Value *Arg)
Definition AMDGPUEmitPrintf.cpp:30
static void locateCStrings(SparseBitVector< 8 > &BV, StringRef Str)
Definition AMDGPUEmitPrintf.cpp:184
static Value * callAppendStringN(IRBuilder<> &Builder, Value *Desc, Value *Str, Value *Length, bool isLast)
Definition AMDGPUEmitPrintf.cpp:154
static Value * appendArg(IRBuilder<> &Builder, Value *Desc, Value *Arg, bool IsLast)
Definition AMDGPUEmitPrintf.cpp:77
static Value * processNonStringArg(Value *Arg, IRBuilder<> &Builder)
Definition AMDGPUEmitPrintf.cpp:353
static Value * processArg(IRBuilder<> &Builder, Value *Desc, Value *Arg, bool SpecIsCString, bool IsLast)
Definition AMDGPUEmitPrintf.cpp:171
static Value * getStrlenWithNull(IRBuilder<> &Builder, Value *Str)
Definition AMDGPUEmitPrintf.cpp:87
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Module.h This file contains the declarations for the Module class.
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
This file defines the SparseBitVector class.
static SymbolRef::Type getType(const Symbol *Sym)
Class for arbitrary precision integers.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
LLVM Basic Block Representation.
iterator begin()
Instruction iterator methods.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="", bool Before=false)
Split the basic block into two basic blocks at the specified instruction.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
static BranchInst * Create(BasicBlock *IfTrue, InsertPosition InsertBefore=nullptr)
A constant pointer value that points to null.
static LLVM_ABI ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
A parsed version of the target data layout string in and methods for querying it.
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
This is an important class for using LLVM in a threaded context.
LLVM_ABI void update(ArrayRef< uint8_t > Data)
Updates the hash for the byte stream provided.
LLVM_ABI void final(MD5Result &Result)
Finishes off the hash and puts the result in result.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
static LLVM_ABI MDString * get(LLVMContext &Context, StringRef Str)
A Module instance is used to store all the information related to an LLVM module.
LLVM_ABI unsigned getNumOperands() const
LLVM_ABI void addOperand(MDNode *M)
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
bool test(unsigned Idx) const
An instruction for storing to memory.
StringRef - Represent a constant reference to a string, i.e.
static constexpr size_t npos
std::string str() const
str - Get the contents as an std::string.
constexpr bool empty() const
empty - Check if the string is empty.
constexpr size_t size() const
size - Get the string size.
The instances of the Type class are immutable: once they are created, they are never changed.
@ DoubleTyID
64-bit floating point type
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty
LLVM_ABI bool getConstantStringInfo(const Value *V, StringRef &Str, bool TrimAtNul=true)
This function computes the length of a null-terminated C string pointed to by V.
std::string utohexstr(uint64_t X, bool LowerCase=false, unsigned Width=0)
LLVM_ABI Value * emitAMDGPUPrintfCall(IRBuilder<> &Builder, ArrayRef< Value * > Args, bool isBuffered)
Definition AMDGPUEmitPrintf.cpp:426
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool isa(const From &Val)
isa - Return true if the parameter to the template is an instance of one of the template type argu...
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
decltype(auto) cast(const From &Val)
cast - Return the argument parameter cast to the specified type.
bool IsConst
Definition AMDGPUEmitPrintf.cpp:213
Value * RealSize
Definition AMDGPUEmitPrintf.cpp:211
StringRef Str
Definition AMDGPUEmitPrintf.cpp:210
StringData(StringRef ST, Value *RS, Value *AS, bool IC)
Definition AMDGPUEmitPrintf.cpp:215
Value * AlignedSize
Definition AMDGPUEmitPrintf.cpp:212
This struct is a compact representation of a valid (non-zero power of two) alignment.