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.