27#define DEBUG_TYPE "amdgpu-emit-printf"
30 auto Int64Ty =
Builder.getInt64Ty();
33 if (
auto IntTy = dyn_cast<IntegerType>(Ty)) {
34 switch (IntTy->getBitWidth()) {
36 return Builder.CreateZExt(Arg, Int64Ty);
43 return Builder.CreateBitCast(Arg, Int64Ty);
46 if (isa<PointerType>(Ty)) {
47 return Builder.CreatePtrToInt(Arg, Int64Ty);
54 auto Int64Ty =
Builder.getInt64Ty();
55 auto M =
Builder.GetInsertBlock()->getModule();
56 auto Fn = M->getOrInsertFunction(
"__ockl_printf_begin", Int64Ty, Int64Ty);
57 return Builder.CreateCall(Fn, Version);
64 auto Int64Ty =
Builder.getInt64Ty();
66 auto M =
Builder.GetInsertBlock()->getModule();
67 auto Fn = M->getOrInsertFunction(
"__ockl_printf_append_args", Int64Ty,
68 Int64Ty,
Int32Ty, Int64Ty, Int64Ty, Int64Ty,
69 Int64Ty, Int64Ty, Int64Ty, Int64Ty,
Int32Ty);
70 auto IsLastValue =
Builder.getInt32(IsLast);
71 auto NumArgsValue =
Builder.getInt32(NumArgs);
72 return Builder.CreateCall(Fn, {
Desc, NumArgsValue, Arg0, Arg1, Arg2, Arg3,
73 Arg4, Arg5, Arg6, IsLastValue});
79 auto Zero =
Builder.getInt64(0);
87 auto *Prev =
Builder.GetInsertBlock();
88 Module *M = Prev->getModule();
90 auto CharZero =
Builder.getInt8(0);
92 auto Zero =
Builder.getInt64(0);
93 auto Int64Ty =
Builder.getInt64Ty();
102 if (Prev->getTerminator()) {
112 Prev->getParent(), Join);
114 M->getContext(),
"strlen.while.done",
115 Prev->getParent(), Join);
126 auto PtrPhi =
Builder.CreatePHI(Str->getType(), 2);
127 PtrPhi->addIncoming(Str, Prev);
128 auto PtrNext =
Builder.CreateGEP(
Builder.getInt8Ty(), PtrPhi, One);
129 PtrPhi->addIncoming(PtrNext, While);
134 Builder.CreateCondBr(Cmp, WhileDone, While);
138 auto Begin =
Builder.CreatePtrToInt(Str, Int64Ty);
139 auto End =
Builder.CreatePtrToInt(PtrPhi, Int64Ty);
141 Len =
Builder.CreateAdd(Len, One);
146 auto LenPhi =
Builder.CreatePHI(Len->getType(), 2);
147 LenPhi->addIncoming(Len, WhileDone);
148 LenPhi->addIncoming(Zero, Prev);
155 auto Int64Ty =
Builder.getInt64Ty();
156 auto CharPtrTy =
Builder.getInt8PtrTy();
158 auto M =
Builder.GetInsertBlock()->getModule();
159 auto Fn = M->getOrInsertFunction(
"__ockl_printf_append_string_n", Int64Ty,
160 Int64Ty, CharPtrTy, Int64Ty,
Int32Ty);
161 auto IsLastInt32 =
Builder.getInt32(isLast);
174 bool SpecIsCString,
bool IsLast) {
175 if (SpecIsCString && isa<PointerType>(Arg->
getType())) {
187 static const char ConvSpecifiers[] =
"diouxXfFeEgGaAcspn";
192 while ((SpecPos = Str.find_first_of(
'%', SpecPos)) !=
StringRef::npos) {
193 if (Str[SpecPos + 1] ==
'%') {
197 auto SpecEnd = Str.find_first_of(ConvSpecifiers, SpecPos);
200 auto Spec = Str.slice(SpecPos, SpecEnd + 1);
201 ArgIdx +=
Spec.count(
'*');
202 if (Str[SpecEnd] ==
's') {
205 SpecPos = SpecEnd + 1;
229 Value *NonConstStrLen =
nullptr;
230 Value *LenWithNull =
nullptr;
231 Value *LenWithNullAligned =
nullptr;
232 Value *TempAdd =
nullptr;
243 TempAdd =
Builder.CreateAdd(LenWithNull,
245 NonConstStrLen =
Builder.CreateAnd(
252 for (
size_t i = 1; i < Args.size(); i++) {
253 if (SpecIsCString.
test(i)) {
259 nullptr,
nullptr,
true));
260 BufSize += alignedLen;
267 LenWithNullAligned =
Builder.CreateAnd(
270 if (NonConstStrLen) {
271 auto Val =
Builder.CreateAdd(LenWithNullAligned, NonConstStrLen,
273 NonConstStrLen = Val;
275 NonConstStrLen = LenWithNullAligned;
281 int AllocSize = M->getDataLayout().getTypeAllocSize(Args[i]->
getType());
284 BufSize += std::max(AllocSize, 8);
292 SizeToReserve =
Builder.CreateAdd(NonConstStrLen, SizeToReserve);
294 ArgSize =
Builder.CreateTrunc(SizeToReserve,
Builder.getInt32Ty());
303 Builder.getInt8PtrTy(M->getDataLayout().getDefaultGlobalsAddressSpace());
304 FunctionType *FTy_alloc = FunctionType::get(I8Ptr, Tys_alloc,
false);
306 M->getOrInsertFunction(
StringRef(
"__printf_alloc"), FTy_alloc, Attr);
308 return Builder.CreateCall(PrintfAllocFn, Alloc_args,
"printf_alloc_fn");
314 std::string Str(SD->
Str.
str() +
'\0');
320 uint64_t ReadNow = std::min(ReadSize, Str.size() -
Offset.tell());
338 cantFail(
Offset.takeError(),
"failed to read bytes from constant array");
340 APInt IntVal(8 * ReadSize, ReadBytes);
343 if (ReadNow < ReadSize)
344 IntVal = IntVal.zext(8 * ReadSize);
350 int Rem = (Str.size() % 8);
351 if (Rem > 0 && Rem <= 4)
359 if (
auto IntTy = dyn_cast<IntegerType>(Ty)) {
360 if (IntTy->getBitWidth() < 64) {
365 if (Ty->isFloatingPointTy()) {
366 if (
DL.getTypeAllocSize(Ty) < 8) {
378 bool IsConstFmtStr) {
381 auto StrIt = StringContents.
begin();
382 size_t i = IsConstFmtStr ? 1 : 0;
383 for (; i < Args.size(); i++) {
385 if ((i == 0) || SpecIsCString.
test(i)) {
386 if (StrIt->IsConst) {
396 Args[i]->getPointerAlignment(
DL),
401 {StrIt->AlignedSize},
"PrintBuffNextPtr");
403 << *PtrToStore <<
'\n');
413 for (
unsigned I = 0,
E = WhatToStore.
size();
I !=
E; ++
I) {
414 Value *toStore = WhatToStore[
I];
417 LLVM_DEBUG(
dbgs() <<
"inserting store to printf buffer:" << *StBuff
420 PtrToStore =
Builder.CreateConstInBoundsGEP1_32(
421 Builder.getInt8Ty(), PtrToStore,
422 M->getDataLayout().getTypeAllocSize(toStore->
getType()),
424 LLVM_DEBUG(
dbgs() <<
"inserting gep to the printf buffer:" << *PtrToStore
432 auto NumOps = Args.size();
446 auto Int8Ty =
Builder.getInt8Ty();
448 bool IsConstFmtStr = !FmtStr.
empty();
450 Value *ArgSize =
nullptr;
453 SpecIsCString, StringContents, ArgSize);
460 auto *Cmp = cast<ICmpInst>(
Builder.CreateICmpNE(
Ptr, zeroIntPtr,
""));
463 Builder.GetInsertBlock()->getParent());
465 Ctx,
"argpush.block",
Builder.GetInsertBlock()->getParent());
468 Builder.SetInsertPoint(ArgPush);
474 auto ConstantTwo =
Builder.getInt32(2);
475 auto ControlDWord =
Builder.CreateShl(ArgSize, ConstantTwo);
477 ControlDWord =
Builder.CreateOr(ControlDWord, ConstantTwo);
485 NamedMDNode *metaD = M->getOrInsertNamedMetadata(
"llvm.printf.fmts");
494 std::string MetadataStr =
495 "0:0:" + llvm::utohexstr(Hash.
low(),
true) +
"," +
509 MDString::get(Ctx,
"0:0:ffffffff,\"Non const format string\"");
531 for (
unsigned int i = 1; i != NumOps; ++i) {
532 bool IsLast = i == NumOps - 1;
533 bool IsCString = SpecIsCString.
test(i);
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
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 void locateCStrings(SparseBitVector< 8 > &BV, StringRef Str)
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)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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),...
static AttributeList get(LLVMContext &C, ArrayRef< std::pair< unsigned, Attribute > > Attrs)
Create an AttributeList with the specified parameters in it.
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.
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, Instruction *InsertBefore=nullptr)
static Constant * get(Type *Ty, uint64_t V, bool IsSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
A constant pointer value that points to null.
static ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
static 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.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
SymbolTableList< Instruction >::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.
void update(ArrayRef< uint8_t > Data)
Updates the hash for the byte stream provided.
void final(MD5Result &Result)
Finishes off the hash and puts the result in result.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
static MDString * get(LLVMContext &Context, StringRef Str)
A Module instance is used to store all the information related to an LLVM module.
unsigned getNumOperands() const
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.
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.
static constexpr size_t npos
The instances of the Type class are immutable: once they are created, they are never changed.
unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
@ DoubleTyID
64-bit floating point type
static 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.
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.
Value * emitAMDGPUPrintfCall(IRBuilder<> &Builder, ArrayRef< Value * > Args, bool isBuffered)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
StringData(StringRef ST, Value *RS, Value *AS, bool IC)
This struct is a compact representation of a valid (non-zero power of two) alignment.
Description of the encoding of one expression Op.