29#define DEBUG_TYPE "amdgpu-emit-printf"
32 auto Int64Ty = Builder.getInt64Ty();
36 switch (IntTy->getBitWidth()) {
38 return Builder.CreateZExt(Arg, Int64Ty);
45 return Builder.CreateBitCast(Arg, Int64Ty);
49 return Builder.CreatePtrToInt(Arg, Int64Ty);
56 auto Int64Ty = Builder.getInt64Ty();
57 auto M = Builder.getModule();
58 auto Fn = M->getOrInsertFunction(
"__ockl_printf_begin", Int64Ty, Int64Ty);
59 return Builder.CreateCall(Fn, Version);
66 auto Int64Ty = Builder.getInt64Ty();
67 auto Int32Ty = Builder.getInt32Ty();
68 auto M = Builder.getModule();
69 auto Fn = M->getOrInsertFunction(
"__ockl_printf_append_args", Int64Ty,
70 Int64Ty, Int32Ty, Int64Ty, Int64Ty, Int64Ty,
71 Int64Ty, Int64Ty, Int64Ty, Int64Ty, Int32Ty);
72 auto IsLastValue = Builder.getInt32(IsLast);
73 auto NumArgsValue = Builder.getInt32(NumArgs);
74 return Builder.CreateCall(Fn, {
Desc, NumArgsValue, Arg0, Arg1, Arg2, Arg3,
75 Arg4, Arg5, Arg6, IsLastValue});
81 auto Zero = Builder.getInt64(0);
89 auto *Prev = Builder.GetInsertBlock();
90 Module *M = Prev->getModule();
92 auto CharZero = Builder.getInt8(0);
93 auto One = Builder.getInt64(1);
94 auto Zero = Builder.getInt64(0);
95 auto Int64Ty = Builder.getInt64Ty();
104 if (Prev->hasTerminator()) {
114 Prev->getParent(), Join);
116 M->getContext(),
"strlen.while.done",
117 Prev->getParent(), Join);
120 Builder.SetInsertPoint(Prev);
123 Builder.CreateCondBr(CmpNull, Join, While);
126 Builder.SetInsertPoint(While);
128 auto PtrPhi = Builder.CreatePHI(Str->getType(), 2);
129 PtrPhi->addIncoming(Str, Prev);
130 auto PtrNext = Builder.CreateGEP(Builder.getInt8Ty(), PtrPhi, One);
131 PtrPhi->addIncoming(PtrNext, While);
134 auto Data = Builder.CreateLoad(Builder.getInt8Ty(), PtrPhi);
135 auto Cmp = Builder.CreateICmpEQ(
Data, CharZero);
136 Builder.CreateCondBr(Cmp, WhileDone, While);
139 Builder.SetInsertPoint(WhileDone->
begin());
140 auto Len = Builder.CreatePtrDiff(PtrPhi, Str);
141 Len = Builder.CreateZExt(Len, Int64Ty);
142 Len = Builder.CreateAdd(Len, One);
146 Builder.SetInsertPoint(Join->
begin());
147 auto LenPhi = Builder.CreatePHI(Len->getType(), 2);
148 LenPhi->addIncoming(Len, WhileDone);
149 LenPhi->addIncoming(Zero, Prev);
156 auto Int64Ty = Builder.getInt64Ty();
157 auto IsLastInt32 = Builder.getInt32(isLast);
158 auto M = Builder.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});
172 bool SpecIsCString,
bool IsLast) {
185 static const char ConvSpecifiers[] =
"diouxXfFeEgGaAcspn";
191 Str = Str.drop_front(SpecPos + 1);
193 if (Str.consume_front(
"%"))
195 size_t SpecEnd = Str.find_first_of(ConvSpecifiers);
199 ArgIdx += Str.take_front(SpecEnd).count(
'*');
200 if (Str[SpecEnd] ==
's')
202 Str = Str.drop_front(SpecEnd + 1);
225 std::string Str(S.
str() +
'\0');
230 const uint64_t ReadSize = 4;
231 uint64_t ReadNow = std::min(ReadSize, Str.size() -
Offset.tell());
232 uint64_t ReadBytes = 0;
237 ReadBytes = Extractor.getU8(
Offset);
240 ReadBytes = Extractor.getU16(
Offset);
243 ReadBytes = Extractor.getU24(
Offset);
246 ReadBytes = Extractor.getU32(
Offset);
249 cantFail(
Offset.takeError(),
"failed to read bytes from constant array");
253 int Rem = (Str.size() % 8);
254 if (Rem > 0 && Rem <= 4)
276 Module *M = Builder.getModule();
277 Value *NonConstStrLen =
nullptr;
278 Value *LenWithNull =
nullptr;
279 Value *LenWithNullAligned =
nullptr;
280 Value *TempAdd =
nullptr;
291 TempAdd = Builder.CreateAdd(LenWithNull,
292 ConstantInt::get(LenWithNull->
getType(), 7U));
293 NonConstStrLen = Builder.CreateAnd(
294 TempAdd, ConstantInt::get(LenWithNull->
getType(), ~7U));
300 for (
size_t i = 1; i < Args.size(); i++) {
301 if (SpecIsCString.
test(i)) {
307 nullptr,
nullptr,
true));
308 BufSize += alignedLen;
313 TempAdd = Builder.CreateAdd(
314 LenWithNull, ConstantInt::get(LenWithNull->
getType(), 7U));
315 LenWithNullAligned = Builder.CreateAnd(
316 TempAdd, ConstantInt::get(LenWithNull->
getType(), ~7U));
318 if (NonConstStrLen) {
319 auto Val = Builder.CreateAdd(LenWithNullAligned, NonConstStrLen,
321 NonConstStrLen = Val;
323 NonConstStrLen = LenWithNullAligned;
329 int AllocSize = M->getDataLayout().getTypeAllocSize(Args[i]->
getType());
332 BufSize += std::max(AllocSize, 8);
337 Value *SizeToReserve = ConstantInt::get(Builder.getInt64Ty(), BufSize,
false);
340 SizeToReserve = Builder.CreateAdd(NonConstStrLen, SizeToReserve);
342 ArgSize = Builder.CreateTrunc(SizeToReserve, Builder.getInt32Ty());
347 Builder.getContext(), AttributeList::FunctionIndex, Attribute::NoUnwind);
349 Type *Tys_alloc[1] = {Builder.getInt32Ty()};
351 Builder.getPtrTy(M->getDataLayout().getDefaultGlobalsAddressSpace());
354 M->getOrInsertFunction(
StringRef(
"__printf_alloc"), FTy_alloc, Attr);
356 return Builder.CreateCall(PrintfAllocFn, Alloc_args,
"printf_alloc_fn");
365 WhatToStore.
push_back(Builder.getInt32(Word));
373 if (IntTy->getBitWidth() < 64) {
374 return Builder.CreateZExt(Arg, Builder.getInt64Ty());
378 if (Ty->isFloatingPointTy()) {
379 if (
DL.getTypeAllocSize(Ty) < 8) {
380 return Builder.CreateFPExt(Arg, Builder.getDoubleTy());
391 bool IsConstFmtStr) {
392 Module *M = Builder.getModule();
394 auto StrIt = StringContents.
begin();
395 size_t i = IsConstFmtStr ? 1 : 0;
396 for (; i < Args.size(); i++) {
398 if ((i == 0) || SpecIsCString.
test(i)) {
399 if (StrIt->IsConst) {
408 Builder.CreateMemCpy(PtrToStore,
Align(1), Args[i],
409 Args[i]->getPointerAlignment(
DL),
413 Builder.CreateInBoundsGEP(Builder.getInt8Ty(), PtrToStore,
414 {StrIt->AlignedSize},
"PrintBuffNextPtr");
416 << *PtrToStore <<
'\n');
426 for (
Value *toStore : WhatToStore) {
427 StoreInst *StBuff = Builder.CreateStore(toStore, PtrToStore);
428 LLVM_DEBUG(
dbgs() <<
"inserting store to printf buffer:" << *StBuff
431 PtrToStore = Builder.CreateConstInBoundsGEP1_32(
432 Builder.getInt8Ty(), PtrToStore,
433 M->getDataLayout().getTypeAllocSize(toStore->getType()),
435 LLVM_DEBUG(
dbgs() <<
"inserting gep to the printf buffer:" << *PtrToStore
443 auto NumOps = Args.size();
455 Module *M = Builder.getModule();
457 auto Int8Ty = Builder.getInt8Ty();
458 auto Int32Ty = Builder.getInt32Ty();
459 bool IsConstFmtStr = !FmtStr.
empty();
461 Value *ArgSize =
nullptr;
464 SpecIsCString, StringContents, ArgSize);
471 auto *Cmp =
cast<ICmpInst>(Builder.CreateICmpNE(Ptr, zeroIntPtr,
""));
474 Builder.GetInsertBlock()->getParent());
476 Ctx,
"argpush.block", Builder.GetInsertBlock()->getParent());
479 Builder.SetInsertPoint(ArgPush);
485 auto ConstantTwo = Builder.getInt32(2);
486 auto ControlDWord = Builder.CreateShl(ArgSize, ConstantTwo);
488 ControlDWord = Builder.CreateOr(ControlDWord, ConstantTwo);
490 Builder.CreateStore(ControlDWord, Ptr);
492 Ptr = Builder.CreateConstInBoundsGEP1_32(Int8Ty, Ptr, 4);
496 NamedMDNode *metaD = M->getOrInsertNamedMetadata(
"llvm.printf.fmts");
505 Ptr = Builder.CreateConstInBoundsGEP1_32(Int8Ty, Ptr, 8);
524 Builder.SetInsertPoint(
End);
525 return Builder.CreateSExt(Builder.CreateNot(Cmp), Int32Ty,
"printf_result");
534 for (
unsigned int i = 1; i !=
NumOps; ++i) {
535 bool IsLast = i ==
NumOps - 1;
536 bool IsCString = SpecIsCString.
test(i);
540 return Builder.CreateTrunc(
Desc, Builder.getInt32Ty());
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static Value * appendString(IRBuilder<> &Builder, Value *Desc, Value *Arg, bool IsLast)
static void callBufferedPrintfArgPush(IRBuilder<> &Builder, ArrayRef< Value * > Args, Value *PtrToStore, SparseBitVector< 8 > &SpecIsCString, SmallVectorImpl< StringData > &StringContents, bool IsConstFmtStr)
static void processConstantStringArg(StringData *SD, IRBuilder<> &Builder, SmallVectorImpl< Value * > &WhatToStore)
static Value * callBufferedPrintfStart(IRBuilder<> &Builder, ArrayRef< Value * > Args, Value *Fmt, bool isConstFmtStr, SparseBitVector< 8 > &SpecIsCString, SmallVectorImpl< StringData > &StringContents, Value *&ArgSize)
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)
static Value * callPrintfBegin(IRBuilder<> &Builder, Value *Version)
static Value * fitArgInto64Bits(IRBuilder<> &Builder, Value *Arg)
static Value * callAppendStringN(IRBuilder<> &Builder, Value *Desc, Value *Str, Value *Length, bool isLast)
static Value * appendArg(IRBuilder<> &Builder, Value *Desc, Value *Arg, bool IsLast)
static Value * processNonStringArg(Value *Arg, IRBuilder<> &Builder)
static Value * processArg(IRBuilder<> &Builder, Value *Desc, Value *Arg, bool SpecIsCString, bool IsLast)
static Value * getStrlenWithNull(IRBuilder<> &Builder, Value *Str)
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)
Represent a constant reference to an array (0 or more elements consecutively in memory),...
LLVM Basic Block Representation.
iterator begin()
Instruction iterator methods.
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
static CondBrInst * Create(Value *Cond, BasicBlock *IfTrue, BasicBlock *IfFalse, 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.
Represent a constant reference to a string, i.e.
static constexpr size_t npos
std::string str() const
Get the contents as an std::string.
constexpr bool empty() const
Check if the string is empty.
constexpr size_t size() const
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 UncondBrInst * Create(BasicBlock *Target, InsertPosition InsertBefore=nullptr)
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<X> - Return the argument parameter cast to the specified type.
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 std::string getAMDGPUPrintfFormatMetadata(StringRef Fmt)
Returns the llvm.printf.fmts entry that maps the ID of the constant format string Fmt back to the str...
LLVM_ABI Value * emitAMDGPUPrintfCall(IRBuilder<> &Builder, ArrayRef< Value * > Args, bool isBuffered)
LLVM_ABI uint64_t getAMDGPUPrintfFormatHash(StringRef Fmt)
Returns the ID that buffered printf stores in place of the constant format string Fmt the low 64 bits...
LLVM_ABI void locateAMDGPUPrintfCStrings(SparseBitVector< 8 > &BV, StringRef Fmt)
Marks the printf arguments that the format string Fmt specifies as strings, i.e.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
bool isa(const From &Val)
isa<X> - 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.
LLVM_ABI void packAMDGPUPrintfConstantString(StringRef Str, SmallVectorImpl< uint32_t > &Words)
Splits the constant string argument Str, including its terminating NUL, into the little-endian 32-bit...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
@ End
Run the machine verifier once, at the end of the pipeline.
constexpr StringLiteral AMDGPUPrintfNonConstFormatMetadata
The llvm.printf.fmts entry added when a module only uses buffered printf with non-constant format str...
StringData(StringRef ST, Value *RS, Value *AS, bool IC)
This struct is a compact representation of a valid (non-zero power of two) alignment.