LLVM: lib/Target/AMDGPU/AMDGPULibFunc.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

25

26using namespace llvm;

27

29 "amdgpu-enable-ocl-mangling-mismatch-workaround", cl::init(true),

31 cl::desc("Enable the workaround for OCL name mangling mismatch."));

32

33namespace {

34

35enum EManglingParam {

36 E_NONE,

37 EX_EVENT,

38 EX_FLOAT4,

39 EX_INTV4,

40 EX_RESERVEDID,

41 EX_SAMPLER,

42 EX_SIZET,

43 EX_UINT,

44 EX_UINTV4,

45 E_ANY,

46 E_CONSTPTR_ANY,

47 E_CONSTPTR_SWAPGL,

48 E_COPY,

49 E_IMAGECOORDS,

50 E_POINTEE,

51 E_SETBASE_I32,

52 E_SETBASE_U32,

53 E_MAKEBASE_UNS,

54 E_V16_OF_POINTEE,

55 E_V2_OF_POINTEE,

56 E_V3_OF_POINTEE,

57 E_V4_OF_POINTEE,

58 E_V8_OF_POINTEE,

59 E_VLTLPTR_ANY,

60};

61

62struct ManglingRule {

63 const char *Name;

64 unsigned char Lead[2];

65 unsigned char Param[5];

66

67 int maxLeadIndex() const { return (std::max)(Lead[0], Lead[1]); }

68 int getNumLeads() const { return (Lead[0] ? 1 : 0) + (Lead[1] ? 1 : 0); }

69

70 unsigned getNumArgs() const;

71

72 static StringMap buildManglingRulesMap();

73};

74

75

76class UnmangledFuncInfo {

77 const char *Name;

78 unsigned NumArgs;

79

80

81 static const UnmangledFuncInfo Table[];

82

83

84 static const unsigned TableSize;

85

86 static StringMap buildNameMap();

87

88public:

89 using ID = AMDGPULibFunc::EFuncId;

90 constexpr UnmangledFuncInfo(const char *_Name, unsigned _NumArgs)

91 : Name(_Name), NumArgs(_NumArgs) {}

92

93 static bool lookup(StringRef Name, ID &Id);

94 static unsigned toIndex(ID Id) {

95 assert(static_cast<unsigned>(Id) >

96 static_cast<unsigned>(AMDGPULibFunc::EI_LAST_MANGLED) &&

97 "Invalid unmangled library function");

98 return static_cast<unsigned>(Id) - 1 -

99 static_cast<unsigned>(AMDGPULibFunc::EI_LAST_MANGLED);

100 }

101 static ID toFuncId(unsigned Index) {

102 assert(Index < TableSize &&

103 "Invalid unmangled library function");

104 return static_cast<ID>(

105 Index + 1 + static_cast<unsigned>(AMDGPULibFunc::EI_LAST_MANGLED));

106 }

107 static unsigned getNumArgs(ID Id) { return Table[toIndex(Id)].NumArgs; }

108 static StringRef getName(ID Id) { return Table[toIndex(Id)].Name; }

109};

110

111unsigned ManglingRule::getNumArgs() const {

112 unsigned I=0;

113 while (I < (sizeof Param/sizeof Param[0]) && Param[I]) ++I;

114 return I;

115}

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141static constexpr ManglingRule manglingRules[] = {

142{ "", {0}, {0} },

143{ "abs" , {1}, {E_ANY}},

144{ "abs_diff" , {1}, {E_ANY,E_COPY}},

145{ "acos" , {1}, {E_ANY}},

146{ "acosh" , {1}, {E_ANY}},

147{ "acospi" , {1}, {E_ANY}},

148{ "add_sat" , {1}, {E_ANY,E_COPY}},

149{ "all" , {1}, {E_ANY}},

150{ "any" , {1}, {E_ANY}},

151{ "asin" , {1}, {E_ANY}},

152{ "asinh" , {1}, {E_ANY}},

153{ "asinpi" , {1}, {E_ANY}},

154{ "async_work_group_copy" , {1}, {E_ANY,E_CONSTPTR_SWAPGL,EX_SIZET,EX_EVENT}},

155{ "async_work_group_strided_copy" , {1}, {E_ANY,E_CONSTPTR_SWAPGL,EX_SIZET,EX_SIZET,EX_EVENT}},

156{ "atan" , {1}, {E_ANY}},

157{ "atan2" , {1}, {E_ANY,E_COPY}},

158{ "atan2pi" , {1}, {E_ANY,E_COPY}},

159{ "atanh" , {1}, {E_ANY}},

160{ "atanpi" , {1}, {E_ANY}},

161{ "atomic_add" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},

162{ "atomic_and" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},

163{ "atomic_cmpxchg" , {1}, {E_VLTLPTR_ANY,E_POINTEE,E_POINTEE}},

164{ "atomic_dec" , {1}, {E_VLTLPTR_ANY}},

165{ "atomic_inc" , {1}, {E_VLTLPTR_ANY}},

166{ "atomic_max" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},

167{ "atomic_min" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},

168{ "atomic_or" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},

169{ "atomic_sub" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},

170{ "atomic_xchg" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},

171{ "atomic_xor" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},

172{ "bitselect" , {1}, {E_ANY,E_COPY,E_COPY}},

173{ "cbrt" , {1}, {E_ANY}},

174{ "ceil" , {1}, {E_ANY}},

175{ "clamp" , {1}, {E_ANY,E_COPY,E_COPY}},

176{ "clz" , {1}, {E_ANY}},

177{ "commit_read_pipe" , {1}, {E_ANY,EX_RESERVEDID}},

178{ "commit_write_pipe" , {1}, {E_ANY,EX_RESERVEDID}},

179{ "copysign" , {1}, {E_ANY,E_COPY}},

180{ "cos" , {1}, {E_ANY}},

181{ "cosh" , {1}, {E_ANY}},

182{ "cospi" , {1}, {E_ANY}},

183{ "cross" , {1}, {E_ANY,E_COPY}},

184{ "ctz" , {1}, {E_ANY}},

185{ "degrees" , {1}, {E_ANY}},

186{ "distance" , {1}, {E_ANY,E_COPY}},

187{ "divide" , {1}, {E_ANY,E_COPY}},

188{ "dot" , {1}, {E_ANY,E_COPY}},

189{ "erf" , {1}, {E_ANY}},

190{ "erfc" , {1}, {E_ANY}},

191{ "exp" , {1}, {E_ANY}},

192{ "exp10" , {1}, {E_ANY}},

193{ "exp2" , {1}, {E_ANY}},

194{ "expm1" , {1}, {E_ANY}},

195{ "fabs" , {1}, {E_ANY}},

196{ "fast_distance" , {1}, {E_ANY,E_COPY}},

197{ "fast_length" , {1}, {E_ANY}},

198{ "fast_normalize" , {1}, {E_ANY}},

199{ "fdim" , {1}, {E_ANY,E_COPY}},

200{ "floor" , {1}, {E_ANY}},

201{ "fma" , {1}, {E_ANY,E_COPY,E_COPY}},

202{ "fmax" , {1}, {E_ANY,E_COPY}},

203{ "fmin" , {1}, {E_ANY,E_COPY}},

204{ "fmod" , {1}, {E_ANY,E_COPY}},

205{ "fract" , {2}, {E_POINTEE,E_ANY}},

206{ "frexp" , {1,2}, {E_ANY,E_ANY}},

207{ "get_image_array_size" , {1}, {E_ANY}},

208{ "get_image_channel_data_type" , {1}, {E_ANY}},

209{ "get_image_channel_order" , {1}, {E_ANY}},

210{ "get_image_dim" , {1}, {E_ANY}},

211{ "get_image_height" , {1}, {E_ANY}},

212{ "get_image_width" , {1}, {E_ANY}},

213{ "get_pipe_max_packets" , {1}, {E_ANY}},

214{ "get_pipe_num_packets" , {1}, {E_ANY}},

215{ "hadd" , {1}, {E_ANY,E_COPY}},

216{ "hypot" , {1}, {E_ANY,E_COPY}},

217{ "ilogb" , {1}, {E_ANY}},

218{ "isequal" , {1}, {E_ANY,E_COPY}},

219{ "isfinite" , {1}, {E_ANY}},

220{ "isgreater" , {1}, {E_ANY,E_COPY}},

221{ "isgreaterequal" , {1}, {E_ANY,E_COPY}},

222{ "isinf" , {1}, {E_ANY}},

223{ "isless" , {1}, {E_ANY,E_COPY}},

224{ "islessequal" , {1}, {E_ANY,E_COPY}},

225{ "islessgreater" , {1}, {E_ANY,E_COPY}},

226{ "isnan" , {1}, {E_ANY}},

227{ "isnormal" , {1}, {E_ANY}},

228{ "isnotequal" , {1}, {E_ANY,E_COPY}},

229{ "isordered" , {1}, {E_ANY,E_COPY}},

230{ "isunordered" , {1}, {E_ANY,E_COPY}},

231{ "ldexp" , {1}, {E_ANY,E_SETBASE_I32}},

232{ "length" , {1}, {E_ANY}},

233{ "lgamma" , {1}, {E_ANY}},

234{ "lgamma_r" , {1,2}, {E_ANY,E_ANY}},

235{ "log" , {1}, {E_ANY}},

236{ "log10" , {1}, {E_ANY}},

237{ "log1p" , {1}, {E_ANY}},

238{ "log2" , {1}, {E_ANY}},

239{ "logb" , {1}, {E_ANY}},

240{ "mad" , {1}, {E_ANY,E_COPY,E_COPY}},

241{ "mad24" , {1}, {E_ANY,E_COPY,E_COPY}},

242{ "mad_hi" , {1}, {E_ANY,E_COPY,E_COPY}},

243{ "mad_sat" , {1}, {E_ANY,E_COPY,E_COPY}},

244{ "max" , {1}, {E_ANY,E_COPY}},

245{ "maxmag" , {1}, {E_ANY,E_COPY}},

246{ "min" , {1}, {E_ANY,E_COPY}},

247{ "minmag" , {1}, {E_ANY,E_COPY}},

248{ "mix" , {1}, {E_ANY,E_COPY,E_COPY}},

249{ "modf" , {2}, {E_POINTEE,E_ANY}},

250{ "mul24" , {1}, {E_ANY,E_COPY}},

251{ "mul_hi" , {1}, {E_ANY,E_COPY}},

252{ "nan" , {1}, {E_ANY}},

253{ "nextafter" , {1}, {E_ANY,E_COPY}},

254{ "normalize" , {1}, {E_ANY}},

255{ "popcount" , {1}, {E_ANY}},

256{ "pow" , {1}, {E_ANY,E_COPY}},

257{ "pown" , {1}, {E_ANY,E_SETBASE_I32}},

258{ "powr" , {1}, {E_ANY,E_COPY}},

259{ "prefetch" , {1}, {E_CONSTPTR_ANY,EX_SIZET}},

260{ "radians" , {1}, {E_ANY}},

261{ "recip" , {1}, {E_ANY}},

262{ "remainder" , {1}, {E_ANY,E_COPY}},

263{ "remquo" , {1,3}, {E_ANY,E_COPY,E_ANY}},

264{ "reserve_read_pipe" , {1}, {E_ANY,EX_UINT}},

265{ "reserve_write_pipe" , {1}, {E_ANY,EX_UINT}},

266{ "rhadd" , {1}, {E_ANY,E_COPY}},

267{ "rint" , {1}, {E_ANY}},

268{ "rootn" , {1}, {E_ANY,E_SETBASE_I32}},

269{ "rotate" , {1}, {E_ANY,E_COPY}},

270{ "round" , {1}, {E_ANY}},

271{ "rsqrt" , {1}, {E_ANY}},

272{ "select" , {1,3}, {E_ANY,E_COPY,E_ANY}},

273{ "shuffle" , {1,2}, {E_ANY,E_ANY}},

274{ "shuffle2" , {1,3}, {E_ANY,E_COPY,E_ANY}},

275{ "sign" , {1}, {E_ANY}},

276{ "signbit" , {1}, {E_ANY}},

277{ "sin" , {1}, {E_ANY}},

278{ "sincos" , {2}, {E_POINTEE,E_ANY}},

279{ "sinh" , {1}, {E_ANY}},

280{ "sinpi" , {1}, {E_ANY}},

281{ "smoothstep" , {1}, {E_ANY,E_COPY,E_COPY}},

282{ "sqrt" , {1}, {E_ANY}},

283{ "step" , {1}, {E_ANY,E_COPY}},

284{ "sub_group_broadcast" , {1}, {E_ANY,EX_UINT}},

285{ "sub_group_commit_read_pipe" , {1}, {E_ANY,EX_RESERVEDID}},

286{ "sub_group_commit_write_pipe" , {1}, {E_ANY,EX_RESERVEDID}},

287{ "sub_group_reduce_add" , {1}, {E_ANY}},

288{ "sub_group_reduce_max" , {1}, {E_ANY}},

289{ "sub_group_reduce_min" , {1}, {E_ANY}},

290{ "sub_group_reserve_read_pipe" , {1}, {E_ANY,EX_UINT}},

291{ "sub_group_reserve_write_pipe" , {1}, {E_ANY,EX_UINT}},

292{ "sub_group_scan_exclusive_add" , {1}, {E_ANY}},

293{ "sub_group_scan_exclusive_max" , {1}, {E_ANY}},

294{ "sub_group_scan_exclusive_min" , {1}, {E_ANY}},

295{ "sub_group_scan_inclusive_add" , {1}, {E_ANY}},

296{ "sub_group_scan_inclusive_max" , {1}, {E_ANY}},

297{ "sub_group_scan_inclusive_min" , {1}, {E_ANY}},

298{ "sub_sat" , {1}, {E_ANY,E_COPY}},

299{ "tan" , {1}, {E_ANY}},

300{ "tanh" , {1}, {E_ANY}},

301{ "tanpi" , {1}, {E_ANY}},

302{ "tgamma" , {1}, {E_ANY}},

303{ "trunc" , {1}, {E_ANY}},

304{ "upsample" , {1}, {E_ANY,E_MAKEBASE_UNS}},

305{ "vec_step" , {1}, {E_ANY}},

306{ "vstore" , {3}, {E_POINTEE,EX_SIZET,E_ANY}},

307{ "vstore16" , {3}, {E_V16_OF_POINTEE,EX_SIZET,E_ANY}},

308{ "vstore2" , {3}, {E_V2_OF_POINTEE,EX_SIZET,E_ANY}},

309{ "vstore3" , {3}, {E_V3_OF_POINTEE,EX_SIZET,E_ANY}},

310{ "vstore4" , {3}, {E_V4_OF_POINTEE,EX_SIZET,E_ANY}},

311{ "vstore8" , {3}, {E_V8_OF_POINTEE,EX_SIZET,E_ANY}},

312{ "work_group_commit_read_pipe" , {1}, {E_ANY,EX_RESERVEDID}},

313{ "work_group_commit_write_pipe" , {1}, {E_ANY,EX_RESERVEDID}},

314{ "work_group_reduce_add" , {1}, {E_ANY}},

315{ "work_group_reduce_max" , {1}, {E_ANY}},

316{ "work_group_reduce_min" , {1}, {E_ANY}},

317{ "work_group_reserve_read_pipe" , {1}, {E_ANY,EX_UINT}},

318{ "work_group_reserve_write_pipe" , {1}, {E_ANY,EX_UINT}},

319{ "work_group_scan_exclusive_add" , {1}, {E_ANY}},

320{ "work_group_scan_exclusive_max" , {1}, {E_ANY}},

321{ "work_group_scan_exclusive_min" , {1}, {E_ANY}},

322{ "work_group_scan_inclusive_add" , {1}, {E_ANY}},

323{ "work_group_scan_inclusive_max" , {1}, {E_ANY}},

324{ "work_group_scan_inclusive_min" , {1}, {E_ANY}},

325{ "write_imagef" , {1}, {E_ANY,E_IMAGECOORDS,EX_FLOAT4}},

326{ "write_imagei" , {1}, {E_ANY,E_IMAGECOORDS,EX_INTV4}},

327{ "write_imageui" , {1}, {E_ANY,E_IMAGECOORDS,EX_UINTV4}},

328{ "ncos" , {1}, {E_ANY} },

329{ "nexp2" , {1}, {E_ANY} },

330{ "nfma" , {1}, {E_ANY, E_COPY, E_COPY} },

331{ "nlog2" , {1}, {E_ANY} },

332{ "nrcp" , {1}, {E_ANY} },

333{ "nrsqrt" , {1}, {E_ANY} },

334{ "nsin" , {1}, {E_ANY} },

335{ "nsqrt" , {1}, {E_ANY} },

336{ "ftz" , {1}, {E_ANY} },

337{ "fldexp" , {1}, {E_ANY, EX_UINT} },

338{ "class" , {1}, {E_ANY, EX_UINT} },

339{ "rcbrt" , {1}, {E_ANY} },

340};

341

342

343const UnmangledFuncInfo UnmangledFuncInfo::Table[] = {

344 {"__read_pipe_2", 4},

345 {"__read_pipe_4", 6},

346 {"__write_pipe_2", 4},

347 {"__write_pipe_4", 6},

348};

349

350const unsigned UnmangledFuncInfo::TableSize =

351 std::size(UnmangledFuncInfo::Table);

352

353static AMDGPULibFunc::Param getRetType(AMDGPULibFunc::EFuncId id,

354 const AMDGPULibFunc::Param (&Leads)[2]) {

355 AMDGPULibFunc::Param Res = Leads[0];

356

357 switch (id) {

358 case AMDGPULibFunc::EI_SINCOS:

359 Res.PtrKind = AMDGPULibFunc::BYVALUE;

360 break;

361 default:

362 break;

363 }

364 return Res;

365}

366

367class ParamIterator {

368 const AMDGPULibFunc::Param (&Leads)[2];

369 const ManglingRule& Rule;

370 int Index = 0;

371public:

372 ParamIterator(const AMDGPULibFunc::Param (&leads)[2],

373 const ManglingRule& rule)

374 : Leads(leads), Rule(rule) {}

375

376 AMDGPULibFunc::Param getNextParam();

377};

378

379AMDGPULibFunc::Param ParamIterator::getNextParam() {

380 AMDGPULibFunc::Param P;

381 if (Index >= int(sizeof Rule.Param/sizeof Rule.Param[0])) return P;

382

383 const char R = Rule.Param[Index];

384 switch (R) {

385 case E_NONE: break;

386 case EX_UINT:

387 P.ArgType = AMDGPULibFunc::U32; break;

388 case EX_INTV4:

389 P.ArgType = AMDGPULibFunc::I32; P.VectorSize = 4; break;

390 case EX_UINTV4:

391 P.ArgType = AMDGPULibFunc::U32; P.VectorSize = 4; break;

392 case EX_FLOAT4:

393 P.ArgType = AMDGPULibFunc::F32; P.VectorSize = 4; break;

394 case EX_SIZET:

395 P.ArgType = AMDGPULibFunc::U64; break;

396 case EX_EVENT:

397 P.ArgType = AMDGPULibFunc::EVENT; break;

398 case EX_SAMPLER:

399 P.ArgType = AMDGPULibFunc::SAMPLER; break;

400 case EX_RESERVEDID: break;

401 default:

402 if (Index == (Rule.Lead[1] - 1)) P = Leads[1];

403 else P = Leads[0];

404

405 switch (R) {

406 case E_ANY:

407 case E_COPY: break;

408

409 case E_POINTEE:

410 P.PtrKind = AMDGPULibFunc::BYVALUE; break;

411 case E_V2_OF_POINTEE:

412 P.VectorSize = 2; P.PtrKind = AMDGPULibFunc::BYVALUE; break;

413 case E_V3_OF_POINTEE:

414 P.VectorSize = 3; P.PtrKind = AMDGPULibFunc::BYVALUE; break;

415 case E_V4_OF_POINTEE:

416 P.VectorSize = 4; P.PtrKind = AMDGPULibFunc::BYVALUE; break;

417 case E_V8_OF_POINTEE:

418 P.VectorSize = 8; P.PtrKind = AMDGPULibFunc::BYVALUE; break;

419 case E_V16_OF_POINTEE:

420 P.VectorSize = 16; P.PtrKind = AMDGPULibFunc::BYVALUE; break;

421 case E_CONSTPTR_ANY:

422 P.PtrKind |= AMDGPULibFunc::CONST; break;

423 case E_VLTLPTR_ANY:

424 P.PtrKind |= AMDGPULibFunc::VOLATILE; break;

425 case E_SETBASE_I32:

426 P.ArgType = AMDGPULibFunc::I32; break;

427 case E_SETBASE_U32:

428 P.ArgType = AMDGPULibFunc::U32; break;

429

430 case E_MAKEBASE_UNS:

431 P.ArgType &= ~AMDGPULibFunc::BASE_TYPE_MASK;

432 P.ArgType |= AMDGPULibFunc::UINT;

433 break;

434

435 case E_IMAGECOORDS:

436 switch (P.ArgType) {

437 case AMDGPULibFunc::IMG1DA: P.VectorSize = 2; break;

438 case AMDGPULibFunc::IMG1DB: P.VectorSize = 1; break;

439 case AMDGPULibFunc::IMG2DA: P.VectorSize = 4; break;

440 case AMDGPULibFunc::IMG1D: P.VectorSize = 1; break;

441 case AMDGPULibFunc::IMG2D: P.VectorSize = 2; break;

442 case AMDGPULibFunc::IMG3D: P.VectorSize = 4; break;

443 }

444 P.PtrKind = AMDGPULibFunc::BYVALUE;

445 P.ArgType = AMDGPULibFunc::I32;

446 break;

447

448 case E_CONSTPTR_SWAPGL: {

449 unsigned AS = AMDGPULibFunc::getAddrSpaceFromEPtrKind(P.PtrKind);

450 switch (AS) {

453 }

454 P.PtrKind = AMDGPULibFunc::getEPtrKindFromAddrSpace(AS);

455 P.PtrKind |= AMDGPULibFunc::CONST;

456 break;

457 }

458

459 default:

461 }

462 }

464 return P;

465}

466

467inline static void drop_front(StringRef& str, size_t n = 1) {

469}

470

471static bool eatTerm(StringRef& mangledName, const char c) {

472 if (mangledName.front() == c) {

473 drop_front(mangledName);

474 return true;

475 }

476 return false;

477}

478

479template <size_t N>

480static bool eatTerm(StringRef& mangledName, const char (&str)[N]) {

481 if (mangledName.starts_with(StringRef(str, N - 1))) {

482 drop_front(mangledName, N-1);

483 return true;

484 }

485 return false;

486}

487

488static int eatNumber(StringRef& s) {

489 size_t const savedSize = s.size();

490 int n = 0;

492 n = n*10 + s.front() - '0';

493 drop_front(s);

494 }

495 return s.size() < savedSize ? n : -1;

496}

497

498static StringRef eatLengthPrefixedName(StringRef& mangledName) {

499 int const Len = eatNumber(mangledName);

500 if (Len <= 0 || static_cast<size_t>(Len) > mangledName.size())

501 return StringRef();

502 StringRef Res = mangledName.substr(0, Len);

503 drop_front(mangledName, Len);

504 return Res;

505}

506

507}

508

516

519 FuncTy = nullptr;

520}

521

529

531 bool SignedInts) {

534 if (NumArgs >= 1)

536 if (NumArgs >= 2)

538}

539

540

541

542

544 size_t const Len = eatNumber(mangledName);

545 switch (Len) {

546 case 2: case 3: case 4: case 8: case 16:

547 return Len;

548 default:

549 break;

550 }

551 return 1;

552}

553

555 std::pair<StringRef, StringRef> const P = mangledName.split('_');

561

563 mangledName = P.second;

564

565 return Pfx;

566}

567

568StringMap ManglingRule::buildManglingRulesMap() {

569 StringMap Map(std::size(manglingRules));

570 int Id = 0;

571 for (auto Rule : manglingRules)

572 Map.insert({Rule.Name, Id++});

573 return Map;

574}

575

576bool AMDGPUMangledLibFunc::parseUnmangledName(StringRef FullName) {

577 static const StringMap manglingRulesMap =

578 ManglingRule::buildManglingRulesMap();

579 FuncId = static_cast<EFuncId>(manglingRulesMap.lookup(FullName));

580 return FuncId != EI_NONE;

581}

582

583

584

585

586namespace {

587struct ItaniumParamParser {

588 AMDGPULibFunc::Param Prev;

589 bool parseItaniumParam(StringRef& param, AMDGPULibFunc::Param &res);

590};

591}

592

593bool ItaniumParamParser::parseItaniumParam(StringRef& param,

594 AMDGPULibFunc::Param &res) {

596 if (param.empty()) return false;

597

598

599 if (eatTerm(param, 'P')) {

600 if (eatTerm(param, 'K')) res.PtrKind |= AMDGPULibFunc::CONST;

601 if (eatTerm(param, 'V')) res.PtrKind |= AMDGPULibFunc::VOLATILE;

602 unsigned AS;

603 if (!eatTerm(param, "U3AS")) {

604 AS = 0;

605 } else {

606 AS = param.front() - '0';

607 drop_front(param, 1);

608 }

610 } else {

611 res.PtrKind = AMDGPULibFunc::BYVALUE;

612 }

613

614

615 if (eatTerm(param,"Dv")) {

617 if (res.VectorSize==1 || !eatTerm(param, '_')) return false;

618 }

619

620

621 char const TC = param.front();

624 StringSwitchAMDGPULibFunc::EType(eatLengthPrefixedName(param))

625 .StartsWith("ocl_image1d_array", AMDGPULibFunc::IMG1DA)

626 .StartsWith("ocl_image1d_buffer", AMDGPULibFunc::IMG1DB)

627 .StartsWith("ocl_image2d_array", AMDGPULibFunc::IMG2DA)

628 .StartsWith("ocl_image1d", AMDGPULibFunc::IMG1D)

629 .StartsWith("ocl_image2d", AMDGPULibFunc::IMG2D)

630 .StartsWith("ocl_image3d", AMDGPULibFunc::IMG3D)

631 .Case("ocl_event", AMDGPULibFunc::DUMMY)

632 .Case("ocl_sampler", AMDGPULibFunc::DUMMY)

633 .Default(AMDGPULibFunc::DUMMY);

634 } else {

635 drop_front(param);

636 switch (TC) {

637 case 'h': res.ArgType = AMDGPULibFunc::U8; break;

638 case 't': res.ArgType = AMDGPULibFunc::U16; break;

639 case 'j': res.ArgType = AMDGPULibFunc::U32; break;

640 case 'm': res.ArgType = AMDGPULibFunc::U64; break;

641 case 'c': res.ArgType = AMDGPULibFunc::I8; break;

642 case 's': res.ArgType = AMDGPULibFunc::I16; break;

643 case 'i': res.ArgType = AMDGPULibFunc::I32; break;

644 case 'l': res.ArgType = AMDGPULibFunc::I64; break;

645 case 'f': res.ArgType = AMDGPULibFunc::F32; break;

646 case 'd': res.ArgType = AMDGPULibFunc::F64; break;

647 case 'D': if (!eatTerm(param, 'h')) return false;

648 res.ArgType = AMDGPULibFunc::F16; break;

649 case 'S':

650 if (!eatTerm(param, '_')) {

651 eatNumber(param);

652 if (!eatTerm(param, '_')) return false;

653 }

655 res.ArgType = Prev.ArgType;

656 break;

657 default:;

658 }

659 }

660 if (res.ArgType == 0) return false;

662 Prev.ArgType = res.ArgType;

663 return true;

664}

665

667 StringRef Name = eatLengthPrefixedName(mangledName);

669 if (!parseUnmangledName(Name))

670 return false;

671

672 const ManglingRule& Rule = manglingRules[FuncId];

673 ItaniumParamParser Parser;

674 for (int I=0; I < Rule.maxLeadIndex(); ++I) {

676 if (!Parser.parseItaniumParam(mangledName, P))

677 return false;

678

679 if ((I + 1) == Rule.Lead[0]) Leads[0] = P;

680 if ((I + 1) == Rule.Lead[1]) Leads[1] = P;

681 }

682 return true;

683}

684

686 if (!UnmangledFuncInfo::lookup(Name, FuncId))

687 return false;

689 return true;

690}

691

693 if (FuncName.empty()) {

694 F.Impl = std::unique_ptr();

695 return false;

696 }

697

698 if (eatTerm(FuncName, "_Z"))

699 F.Impl = std::make_unique();

700 else

701 F.Impl = std::make_unique();

702 if (F.Impl->parseFuncName(FuncName))

703 return true;

704

705 F.Impl = std::unique_ptr();

706 return false;

707}

708

711 if (eatTerm(S, "_Z"))

712 return eatLengthPrefixedName(S);

714}

715

716

717

718

719template

720void AMDGPUMangledLibFunc::writeName(Stream &OS) const {

721 const char *Pfx = "";

722 switch (FKind) {

723 case NATIVE: Pfx = "native_"; break;

724 case HALF: Pfx = "half_"; break;

725 default: break;

726 }

727 if (!Name.empty()) {

728 OS << Pfx << Name;

729 } else if (FuncId != EI_NONE) {

730 OS << Pfx;

731 const StringRef& S = manglingRules[FuncId].Name;

732 OS.write(S.data(), S.size());

733 }

734}

735

737

738

739

740

742 switch (T) {

762 default:

764 }

765 return nullptr;

766}

767

768namespace {

769

770

771

772

773

774

775

776

777

778

779

780

781

782

783

784

785

786

787

788

789

790

791

792

793class ItaniumMangler {

795 bool UseAddrSpace;

796

797 int findSubst(const AMDGPULibFunc::Param& P) const {

798 for(unsigned I = 0; I < Str.size(); ++I) {

799 const AMDGPULibFunc::Param& T = Str[I];

800 if (P.PtrKind == T.PtrKind &&

801 P.VectorSize == T.VectorSize &&

802 P.ArgType == T.ArgType) {

803 return I;

804 }

805 }

806 return -1;

807 }

808

809 template

810 bool trySubst(Stream& os, const AMDGPULibFunc::Param& p) {

811 int const subst = findSubst(p);

812 if (subst < 0) return false;

813

814

815

816 if (subst == 0) os << "S_";

817 else os << 'S' << (subst-1) << '_';

818 return true;

819 }

820

821public:

822 ItaniumMangler(bool useAddrSpace)

823 : UseAddrSpace(useAddrSpace) {}

824

825 template

826 void operator()(Stream& os, AMDGPULibFunc::Param p) {

827

828

829

830

831

832

833

834

835

836

837

838 AMDGPULibFunc::Param Ptr;

839

840 if (p.PtrKind) {

841 if (trySubst(os, p)) return;

842 os << 'P';

843 if (p.PtrKind & AMDGPULibFunc::CONST) os << 'K';

844 if (p.PtrKind & AMDGPULibFunc::VOLATILE) os << 'V';

845 unsigned AS = UseAddrSpace

847 : 0;

849 os << "U3AS" << AS;

850 Ptr = p;

851 p.PtrKind = 0;

852 }

853

854 if (p.VectorSize > 1) {

855 if (trySubst(os, p)) goto exit;

856 Str.push_back(p);

857 os << "Dv" << static_cast<unsigned>(p.VectorSize) << '_';

858 }

859

861

862 exit:

863 if (Ptr.ArgType) Str.push_back(Ptr);

864 }

865};

866}

867

868std::string AMDGPUMangledLibFunc::mangleNameItanium() const {

869 SmallString<128> Buf;

870 raw_svector_ostream S(Buf);

871 SmallString<128> NameBuf;

872 raw_svector_ostream Name(NameBuf);

873 writeName(Name);

874 const StringRef& NameStr = Name.str();

875 S << "_Z" << static_cast<int>(NameStr.size()) << NameStr;

876

877 ItaniumMangler Mangler(true);

878 ParamIterator I(Leads, manglingRules[FuncId]);

880 while ((P = I.getNextParam()).ArgType != 0)

881 Mangler(S, P);

882 return std::string(S.str());

883}

884

885

886

887

892 P.VectorSize = VT->getNumElements();

893 Ty = VT->getElementType();

894 }

895

896 switch (Ty->getTypeID()) {

899 break;

902 break;

905 break;

908 case 8:

910 break;

911 case 16:

913 break;

914 case 32:

916 break;

917 case 64:

919 break;

920 default:

922 }

923

924 break;

925 default:

927 }

928

929 return P;

930}

931

934 bool UseAddrSpace) {

935 Type *T = nullptr;

936 switch (P.ArgType) {

937 default:

938 return nullptr;

942 break;

946 break;

950 break;

954 break;

957 break;

960 break;

963 break;

964

974 break;

984 return nullptr;

985 }

986 if (P.VectorSize > 1)

991 return T;

992}

993

996 std::vector<Type*> Args;

997 ParamIterator I(Leads, manglingRules[FuncId]);

999 while ((P = I.getNextParam()).ArgType != 0) {

1001 if (!ParamTy)

1002 return nullptr;

1003

1004 Args.push_back(ParamTy);

1005 }

1006

1008 if (!RetTy)

1009 return nullptr;

1010

1012}

1013

1015 return manglingRules[FuncId].getNumArgs();

1016}

1017

1019 return UnmangledFuncInfo::getNumArgs(FuncId);

1020}

1021

1025 writeName(OS);

1026 return std::string(OS.str());

1027}

1028

1032

1033 if (!FuncTy) {

1034

1036 return false;

1037

1038

1039

1041 }

1042

1043

1044 if (FuncTy == CallTy)

1045 return true;

1046

1047 const unsigned NumParams = FuncTy->getNumParams();

1049 return false;

1050

1051 for (unsigned I = 0; I != NumParams; ++I) {

1052 Type *FuncArgTy = FuncTy->getParamType(I);

1054 if (FuncArgTy == CallArgTy)

1055 continue;

1056

1057

1059 if (FuncVecTy && FuncVecTy->getElementType() == CallArgTy &&

1061 continue;

1062

1063 return false;

1064 }

1065

1066 return true;

1067}

1068

1070 std::string FuncName = fInfo.mangle();

1072 M->getValueSymbolTable().lookup(FuncName));

1073 if (F || F->isDeclaration())

1074 return nullptr;

1075

1076 if (F->hasFnAttribute(Attribute::NoBuiltin))

1077 return nullptr;

1078

1080 return nullptr;

1081

1082 return F;

1083}

1084

1087 std::string const FuncName = fInfo.mangle();

1089 M->getValueSymbolTable().lookup(FuncName));

1090

1091 if (F) {

1092 if (F->hasFnAttribute(Attribute::NoBuiltin))

1093 return nullptr;

1094 if (F->isDeclaration() &&

1096 return F;

1097 }

1098

1101

1102 bool hasPtr = false;

1104 PI = FuncTy->param_begin(),

1105 PE = FuncTy->param_end();

1106 PI != PE; ++PI) {

1107 const Type* argTy = static_cast<const Type*>(*PI);

1109 hasPtr = true;

1110 break;

1111 }

1112 }

1113

1115 if (hasPtr) {

1116

1117 C = M->getOrInsertFunction(FuncName, FuncTy);

1118 } else {

1119 AttributeList Attr;

1121 Attr = Attr.addFnAttribute(

1123 Attr = Attr.addFnAttribute(Ctx, Attribute::NoUnwind);

1124 C = M->getOrInsertFunction(FuncName, FuncTy, Attr);

1125 }

1126

1127 return C;

1128}

1129

1132 for (unsigned I = 0; I != TableSize; ++I)

1133 Map[Table[I].Name] = I;

1134 return Map;

1135}

1136

1137bool UnmangledFuncInfo::lookup(StringRef Name, ID &Id) {

1139 auto Loc = Map.find(Name);

1140 if (Loc != Map.end()) {

1141 Id = toFuncId(Loc->second);

1142 return true;

1143 }

1144 Id = AMDGPULibFunc::EI_NONE;

1145 return false;

1146}

1147

1150 Impl = std::make_unique(*MF);

1152 Impl = std::make_unique(*UMF);

1153 else

1154 Impl = std::unique_ptr();

1155}

1156

1158 if (this == &F)

1159 return *this;

1161 return *this;

1162}

1163

1166 "not supported");

1167 Impl = std::make_unique(

1169}

1170

1172 Impl = std::make_unique(Id, FT, SignedInts);

1173}

1174

1176 Impl = std::make_unique(Name, FT);

1177}

1178

1179void AMDGPULibFunc::initMangled() {

1180 Impl = std::make_unique();

1181}

1182

1184 if (!Impl)

1185 initMangled();

1187}

1188

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

This file defines the StringMap class.

static cl::opt< bool > EnableOCLManglingMismatchWA("amdgpu-enable-ocl-mangling-mismatch-workaround", cl::init(true), cl::ReallyHidden, cl::desc("Enable the workaround for OCL name mangling mismatch."))

static AMDGPULibFunc::ENamePrefix parseNamePrefix(StringRef &mangledName)

Definition AMDGPULibFunc.cpp:554

static const char * getItaniumTypeName(AMDGPULibFunc::EType T)

Definition AMDGPULibFunc.cpp:741

static int parseVecSize(StringRef &mangledName)

Definition AMDGPULibFunc.cpp:543

static Type * getIntrinsicParamType(LLVMContext &C, const AMDGPULibFunc::Param &P, bool UseAddrSpace)

Definition AMDGPULibFunc.cpp:932

Module.h This file contains the declarations for the Module class.

static bool lookup(const GsymReader &GR, DataExtractor &Data, uint64_t &Offset, uint64_t BaseAddr, uint64_t Addr, SourceLocations &SrcLocs, llvm::Error &Err)

A Lookup helper functions.

static StringRef getName(Value *V)

This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...

static unsigned getBitWidth(Type *Ty, const DataLayout &DL)

Returns the bitwidth of the given scalar or pointer type.

static unsigned getEPtrKindFromAddrSpace(unsigned AS)

static unsigned getAddrSpaceFromEPtrKind(unsigned Kind)

static bool isMangled(EFuncId Id)

void setName(StringRef N)

static Function * getFunction(llvm::Module *M, const AMDGPULibFunc &fInfo)

Definition AMDGPULibFunc.cpp:1069

static bool parse(StringRef MangledName, AMDGPULibFunc &Ptr)

Definition AMDGPULibFunc.cpp:692

static FunctionCallee getOrInsertFunction(llvm::Module *M, const AMDGPULibFunc &fInfo)

Definition AMDGPULibFunc.cpp:1085

FunctionType * getFunctionType(const Module &M) const

bool isCompatibleSignature(const Module &M, const FunctionType *FuncTy) const

Definition AMDGPULibFunc.cpp:1029

bool allowsImplicitVectorSplat(int ArgIdx) const

Return true if it's legal to splat a scalar value passed in parameter ArgIdx to a vector argument.

std::string mangle() const

AMDGPULibFunc & operator=(const AMDGPULibFunc &F)

Definition AMDGPULibFunc.cpp:1157

Param * getLeads()

Get leading parameters for mangled lib functions.

Definition AMDGPULibFunc.cpp:1183

unsigned getNumArgs() const

static StringRef getUnmangledName(StringRef MangledName)

Definition AMDGPULibFunc.cpp:709

unsigned getNumArgs() const override

Definition AMDGPULibFunc.cpp:1014

bool parseFuncName(StringRef &mangledName) override

Definition AMDGPULibFunc.cpp:666

std::string getName() const override

Get unmangled name for mangled library function and name for unmangled library function.

Definition AMDGPULibFunc.cpp:1022

FunctionType * getFunctionType(const Module &M) const override

Definition AMDGPULibFunc.cpp:994

AMDGPUMangledLibFunc()

Definition AMDGPULibFunc.cpp:509

std::string mangle() const override

Definition AMDGPULibFunc.cpp:736

unsigned getNumArgs() const override

Definition AMDGPULibFunc.cpp:1018

AMDGPUUnmangledLibFunc()

Definition AMDGPULibFunc.cpp:517

bool parseFuncName(StringRef &Name) override

Definition AMDGPULibFunc.cpp:685

static LLVM_ABI Attribute getWithMemoryEffects(LLVMContext &Context, MemoryEffects ME)

Class to represent fixed width SIMD vectors.

static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)

A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...

Class to represent function types.

unsigned getNumParams() const

Return the number of fixed parameters this function type requires.

Type::subtype_iterator param_iterator

Type * getParamType(unsigned i) const

Parameter type accessors.

static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)

This static method is the primary way of constructing a FunctionType.

This is an important class for using LLVM in a threaded context.

static MemoryEffectsBase readOnly()

A Module instance is used to store all the information related to an LLVM module.

static PointerType * getUnqual(Type *ElementType)

This constructs a pointer to an object of the specified type in the default address space (address sp...

static LLVM_ABI PointerType * get(Type *ElementType, unsigned AddressSpace)

This constructs a pointer to an object of the specified type in a numbered address space.

SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...

StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...

ValueTy lookup(StringRef Key) const

lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...

StringRef - Represent a constant reference to a string, i.e.

std::pair< StringRef, StringRef > split(char Separator) const

Split into two substrings around the first occurrence of a separator character.

constexpr StringRef substr(size_t Start, size_t N=npos) const

Return a reference to the substring from [Start, Start + N).

bool starts_with(StringRef Prefix) const

Check if this string starts with the given Prefix.

constexpr bool empty() const

empty - Check if the string is empty.

StringRef drop_front(size_t N=1) const

Return a StringRef equal to 'this' but with the first N elements dropped.

constexpr size_t size() const

size - Get the string size.

char front() const

front - Get the first character in the string.

constexpr const char * data() const

data - Get a pointer to the start of the string (which may not be null terminated).

A switch()-like statement whose cases are string literals.

StringSwitch & Case(StringLiteral S, T Value)

The instances of the Type class are immutable: once they are created, they are never changed.

static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)

static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)

bool isPointerTy() const

True if this is an instance of PointerType.

@ HalfTyID

16-bit floating point type

@ FloatTyID

32-bit floating point type

@ IntegerTyID

Arbitrary bit width integers.

@ DoubleTyID

64-bit floating point type

static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)

static LLVM_ABI IntegerType * getInt16Ty(LLVMContext &C)

static LLVM_ABI Type * getDoubleTy(LLVMContext &C)

static LLVM_ABI Type * getFloatTy(LLVMContext &C)

static LLVM_ABI Type * getHalfTy(LLVMContext &C)

A raw_ostream that writes to an SmallVector or SmallString.

StringRef str() const

Return a StringRef for the vector contents.

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

@ LOCAL_ADDRESS

Address space for local memory.

@ GLOBAL_ADDRESS

Address space for global memory (RAT0, VTX0).

unsigned ID

LLVM IR allows to use arbitrary numbers as calling convention identifiers.

@ C

The default llvm calling convention, compatible with C.

initializer< Ty > init(const Ty &Val)

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.

auto dyn_cast_or_null(const Y &Val)

bool isDigit(char C)

Checks if character C is one of the 10 decimal digits.

class LLVM_GSL_OWNER SmallVector

Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...

decltype(auto) cast(const From &Val)

cast - Return the argument parameter cast to the specified type.

static Param getFromTy(Type *Ty, bool Signed)

Definition AMDGPULibFunc.cpp:888