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

1

2

3

4

5

6

7

8

9

10

11

12

26

27using namespace llvm;

29

30

31

32

33

34

35

36

37

38

39

40

41#define GEN_HAS_MEMBER(member) \

42 class HasMember##member { \

43 private: \

44 struct KnownWithMember { \

45 int member; \

46 }; \

47 class AmbiguousDerived : public AMDGPUMCKernelCodeT, \

48 public KnownWithMember {}; \

49 template \

50 static constexpr std::false_type Test(decltype(U::member) *); \

51 template static constexpr std::true_type Test(...); \

52 \

53 public: \

54 static constexpr bool RESULT = \

55 std::is_same_v<decltype(Test(nullptr)), \

56 std::true_type>; \

57 }; \

58 class IsMCExpr##member { \

59 template <typename U, \

60 typename std::enable_if_t< \

61 HasMember##member::RESULT && \

62 std::is_same_v<decltype(U::member), const MCExpr *>, \

63 U> * = nullptr> \

64 static constexpr std::true_type HasMCExprType(decltype(U::member) *); \

65 template static constexpr std::false_type HasMCExprType(...); \

66 \

67 public: \

68 static constexpr bool RESULT = \

69 std::is_same_v<decltype(HasMCExprType(nullptr)), \

70 std::true_type>; \

71 }; \

72 class GetMember##member { \

73 public: \

74 static const MCExpr *Phony; \

75 template <typename U, typename std::enable_if_t<IsMCExpr##member::RESULT, \

76 U> * = nullptr> \

77 static const MCExpr *&Get(U &C) { \

78 assert(IsMCExpr##member::RESULT && \

79 "Trying to retrieve member that does not exist."); \

80 return C.member; \

81 } \

82 template <typename U, typename std::enable_if_t<!IsMCExpr##member::RESULT, \

83 U> * = nullptr> \

84 static const MCExpr *&Get(U &C) { \

85 return Phony; \

86 } \

87 }; \

88 const MCExpr *GetMember##member::Phony = nullptr;

89

90

91

92

93

100

103

115

116GEN_HAS_MEMBER(enable_sgpr_private_segment_wave_byte_offset)

127

145

157GEN_HAS_MEMBER(debug_wavefront_private_segment_offset_sgpr)

165

168 "",

169#define RECORD(name, altName, print, parse) #name

171#undef RECORD

172 };

174}

175

178 "",

179#define RECORD(name, altName, print, parse) #altName

181#undef RECORD

182 };

184}

185

187 static bool const Table[] = {

188#define RECORD(name, altName, print, parse) (IsMCExpr##name::RESULT)

190#undef RECORD

191 };

193}

194

196

199#define RECORD(name, altName, print, parse) GetMember##name::Get

201#undef RECORD

202 };

204}

205

210 for (unsigned i = 0; i < names.size(); ++i) {

211 map.insert(std::pair(names[i], i));

212 map.insert(std::pair(altNames[i], i));

213 }

214 return map;

215}

216

220 return map.lookup(name) - 1;

221}

222

224public:

226 typename std::enable_if_t<!std::is_integral_v, T> * = nullptr>

233 }

234

236 typename std::enable_if_t<std::is_integral_v, T> * = nullptr>

240 OS << Name << " = " << (int)(C.*ptr);

241 }

242};

243

244template <typename T, T AMDGPUMCKernelCodeT::*ptr, int shift, int width = 1>

248 const auto Mask = (static_cast<T>(1) << width) - 1;

249 OS << Name << " = " << (int)((C.*ptr >> shift) & Mask);

250}

251

254

257 static const PrintFx Table[] = {

258#define COMPPGM1(name, aname, AccMacro) \

259 COMPPGM(name, aname, C_00B848_##AccMacro, S_00B848_##AccMacro, 0)

260#define COMPPGM2(name, aname, AccMacro) \

261 COMPPGM(name, aname, C_00B84C_##AccMacro, S_00B84C_##AccMacro, 32)

262#define PRINTFIELD(sname, aname, name) PrintField::printField<FLD_T(name)>

263#define PRINTCOMP(Complement, PGMType) \

264 [](StringRef Name, const AMDGPUMCKernelCodeT &C, raw_ostream &OS, \

265 MCContext &Ctx, AMDGPUMCKernelCodeT::PrintHelper Helper) { \

266 OS << Name << " = "; \

267 auto [Shift, Mask] = getShiftMask(Complement); \

268 const MCExpr *Value; \

269 if (PGMType == 0) { \

270 Value = \

271 maskShiftGet(C.compute_pgm_resource1_registers, Mask, Shift, Ctx); \

272 } else { \

273 Value = \

274 maskShiftGet(C.compute_pgm_resource2_registers, Mask, Shift, Ctx); \

275 } \

276 Helper(Value, OS, Ctx.getAsmInfo()); \

277 }

278#define RECORD(name, altName, print, parse) print

280#undef RECORD

281 };

283}

284

287

289 Err << "expected '='";

290 return false;

291 }

293

295 Err << "integer absolute expression expected";

296 return false;

297 }

298 return true;

299}

300

301template <typename T, T AMDGPUMCKernelCodeT::*ptr>

304 int64_t Value = 0;

306 return false;

308 return true;

309}

310

311template <typename T, T AMDGPUMCKernelCodeT::*ptr, int shift, int width = 1>

314 int64_t Value = 0;

316 return false;

317 const uint64_t Mask = ((UINT64_C(1) << width) - 1) << shift;

318 C.*ptr &= (T)~Mask;

319 C.*ptr |= (T)((Value << shift) & Mask);

320 return true;

321}

322

326 Err << "expected '='";

327 return false;

328 }

330

332 Err << "Could not parse expression";

333 return false;

334 }

335 return true;

336}

337

339

341 static const ParseFx Table[] = {

342#define COMPPGM1(name, aname, AccMacro) \

343 COMPPGM(name, aname, G_00B848_##AccMacro, C_00B848_##AccMacro, 0)

344#define COMPPGM2(name, aname, AccMacro) \

345 COMPPGM(name, aname, G_00B84C_##AccMacro, C_00B84C_##AccMacro, 32)

346#define PARSECOMP(Complement, PGMType) \

347 [](AMDGPUMCKernelCodeT &C, MCAsmParser &MCParser, \

348 raw_ostream &Err) -> bool { \

349 MCContext &Ctx = MCParser.getContext(); \

350 const MCExpr *Value; \

351 if (!parseExpr(MCParser, Value, Err)) \

352 return false; \

353 auto [Shift, Mask] = getShiftMask(Complement); \

354 Value = maskShiftSet(Value, Mask, Shift, Ctx); \

355 const MCExpr *Compl = MCConstantExpr::create(Complement, Ctx); \

356 if (PGMType == 0) { \

357 C.compute_pgm_resource1_registers = MCBinaryExpr::createAnd( \

358 C.compute_pgm_resource1_registers, Compl, Ctx); \

359 C.compute_pgm_resource1_registers = MCBinaryExpr::createOr( \

360 C.compute_pgm_resource1_registers, Value, Ctx); \

361 } else { \

362 C.compute_pgm_resource2_registers = MCBinaryExpr::createAnd( \

363 C.compute_pgm_resource2_registers, Compl, Ctx); \

364 C.compute_pgm_resource2_registers = MCBinaryExpr::createOr( \

365 C.compute_pgm_resource2_registers, Value, Ctx); \

366 } \

367 return true; \

368 }

369#define RECORD(name, altName, print, parse) parse

371#undef RECORD

372 };

374}

375

382}

383

385 MCContext &Ctx, bool InitMCExpr) {

387

389

390 if (InitMCExpr) {

400 }

401}

402

406 return;

407

409 Ctx.reportError({}, "enable_dx10_clamp=1 is not allowed on GFX12+");

410 return;

411 }

412

414 Ctx.reportError({}, "enable_ieee_mode=1 is not allowed on GFX12+");

415 return;

416 }

417

419 Ctx.reportError({}, "enable_wgp_mode=1 is only allowed on GFX10+");

420 return;

421 }

422

424 Ctx.reportError({}, "enable_mem_ordered=1 is only allowed on GFX10+");

425 return;

426 }

427

429 Ctx.reportError({}, "enable_fwd_progress=1 is only allowed on GFX10+");

430 return;

431 }

432}

433

436 return IndexTable[Index](*this);

437}

438

442 if (Idx < 0) {

443 Err << "unexpected amd_kernel_code_t field name " << ID;

444 return false;

445 }

446

450 return false;

452 return true;

453 }

455 return Parser ? Parser(*this, MCParser, Err) : false;

456}

457

461 for (int i = 0; i < Size; ++i) {

462 OS << "\t\t";

467 } else {

469 }

470 OS << '\n';

471 }

472}

473

485

488 else

490 4);

491

494 else

496 4);

497

501 CodeProps,

505 Ctx);

506 OS.emitValue(CodeProps, 4);

507 } else

509

512 else

513 OS.emitIntValue(0, 4);

514

519

522 else

523 OS.emitIntValue(0, 2);

524

527 else

528 OS.emitIntValue(0, 2);

529

535 2);

541

546}

static void printBitField(StringRef Name, const AMDGPUMCKernelCodeT &C, raw_ostream &OS, MCContext &, AMDGPUMCKernelCodeT::PrintHelper)

static ArrayRef< StringLiteral > get_amd_kernel_code_t_FldNames()

static ArrayRef< StringLiteral > get_amd_kernel_code_t_FldAltNames()

static ArrayRef< bool > hasMCExprVersionTable()

static bool expectAbsExpression(MCAsmParser &MCParser, int64_t &Value, raw_ostream &Err)

void(*)(StringRef, const AMDGPUMCKernelCodeT &, raw_ostream &, MCContext &, AMDGPUMCKernelCodeT::PrintHelper Helper) PrintFx

static bool parseExpr(MCAsmParser &MCParser, const MCExpr *&Value, raw_ostream &Err)

static bool parseField(AMDGPUMCKernelCodeT &C, MCAsmParser &MCParser, raw_ostream &Err)

const MCExpr *&(*)(AMDGPUMCKernelCodeT &) RetrieveFx

static ArrayRef< RetrieveFx > getMCExprIndexTable()

bool(*)(AMDGPUMCKernelCodeT &, MCAsmParser &, raw_ostream &) ParseFx

#define GEN_HAS_MEMBER(member)

static bool parseBitField(AMDGPUMCKernelCodeT &C, MCAsmParser &MCParser, raw_ostream &Err)

static void printAmdKernelCodeField(const AMDGPUMCKernelCodeT &C, int FldIndex, raw_ostream &OS, MCContext &Ctx, AMDGPUMCKernelCodeT::PrintHelper Helper)

static ArrayRef< PrintFx > getPrinterTable(AMDGPUMCKernelCodeT::PrintHelper Helper)

static StringMap< int > createIndexMap(ArrayRef< StringLiteral > names, ArrayRef< StringLiteral > altNames)

static ArrayRef< ParseFx > getParserTable()

static int get_amd_kernel_code_t_FieldIndex(StringRef name)

MC layer struct for AMDGPUMCKernelCodeT, provides MCExpr functionality where required.

@ AMD_CODE_PROPERTY_IS_DYNAMIC_CALLSTACK_SHIFT

Indicate if the generated ISA is using a dynamically sized call stack.

@ AMD_CODE_PROPERTY_IS_DYNAMIC_CALLSTACK_WIDTH

dxil pretty DXIL Metadata Pretty Printer

Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx

#define G_00B848_FWD_PROGRESS(x)

#define G_00B848_MEM_ORDERED(x)

#define G_00B848_IEEE_MODE(x)

#define G_00B848_DX10_CLAMP(x)

#define G_00B848_WGP_MODE(x)

assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())

static void printField(StringRef Name, const AMDGPUMCKernelCodeT &C, raw_ostream &OS, MCContext &Ctx, AMDGPUMCKernelCodeT::PrintHelper Helper)

static void printField(StringRef Name, const AMDGPUMCKernelCodeT &C, raw_ostream &OS, MCContext &, AMDGPUMCKernelCodeT::PrintHelper)

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

size_t size() const

size - Get the array size.

bool isNot(AsmToken::TokenKind K) const

Check if the current token has kind K.

const AsmToken & Lex()

Consume the next token from the input stream and return it.

Generic assembler parser interface, for use by target specific assembly parsers.

virtual bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc)=0

Parse an arbitrary expression.

virtual MCAsmLexer & getLexer()=0

virtual bool parseAbsoluteExpression(int64_t &Res)=0

Parse an expression which must evaluate to an absolute value.

static const MCBinaryExpr * createOr(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)

static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)

Context object for machine code objects.

const MCAsmInfo * getAsmInfo() const

void reportError(SMLoc L, const Twine &Msg)

Base class for the full range of assembler expressions which are needed for parsing.

Streaming machine code generation interface.

Generic base class for all target subtargets.

A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...

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

bool insert(MapEntryTy *KeyValue)

insert - Insert the specified key/value pair into the map.

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

LLVM Value Representation.

An efficient, type-erasing, non-owning reference to a callable.

This class implements an extremely fast bulk output stream that can only output to a stream.

bool isGFX12Plus(const MCSubtargetInfo &STI)

const MCExpr * maskShiftSet(const MCExpr *Val, uint32_t Mask, uint32_t Shift, MCContext &Ctx)

Provided with the MCExpr * Val, uint32 Mask and Shift, will return the masked and left shifted,...

bool isGFX10Plus(const MCSubtargetInfo &STI)

void initDefaultAMDKernelCodeT(AMDGPUMCKernelCodeT &KernelCode, const MCSubtargetInfo *STI)

@ C

The default llvm calling convention, compatible with C.

unsigned ID

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

This is an optimization pass for GlobalISel generic memory operations.

constexpr uint32_t Hi_32(uint64_t Value)

Return the high 32 bits of a 64 bit value.

constexpr uint32_t Lo_32(uint64_t Value)

Return the low 32 bits of a 64 bit value.

uint16_t reserved_vgpr_first

uint16_t reserved_vgpr_count

uint16_t amd_machine_version_major

uint16_t amd_machine_kind

uint64_t kernarg_segment_byte_size

uint16_t amd_machine_version_stepping

uint8_t private_segment_alignment

uint16_t debug_wavefront_private_segment_offset_sgpr

int64_t kernel_code_entry_byte_offset

uint64_t control_directives[16]

const MCExpr * workitem_private_segment_byte_size

uint16_t debug_private_segment_buffer_sgpr

uint32_t amd_kernel_code_version_major

void EmitKernelCodeT(raw_ostream &OS, MCContext &Ctx, PrintHelper Helper)

const MCExpr * compute_pgm_resource2_registers

uint16_t amd_machine_version_minor

uint32_t gds_segment_byte_size

uint8_t group_segment_alignment

uint32_t workgroup_fbarrier_count

uint8_t kernarg_segment_alignment

uint16_t reserved_sgpr_first

void validate(const MCSubtargetInfo *STI, MCContext &Ctx)

AMDGPUMCKernelCodeT()=default

uint32_t amd_kernel_code_version_minor

const MCExpr * wavefront_sgpr_count

void initDefault(const MCSubtargetInfo *STI, MCContext &Ctx, bool InitMCExpr=true)

uint16_t reserved_sgpr_count

uint64_t kernel_code_prefetch_byte_size

const MCExpr * workitem_vgpr_count

const MCExpr * is_dynamic_callstack

int64_t kernel_code_prefetch_byte_offset

uint32_t workgroup_group_segment_byte_size

bool ParseKernelCodeT(StringRef ID, MCAsmParser &MCParser, raw_ostream &Err)

uint64_t runtime_loader_kernel_symbol

const MCExpr *& getMCExprForIndex(int Index)

const MCExpr * compute_pgm_resource1_registers

uint64_t compute_pgm_resource_registers