LLVM: lib/Target/DirectX/DXILTranslateMetadata.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

33#include

34

35using namespace llvm;

37

38namespace {

39

40

41

42class DiagnosticInfoValidateMD : public DiagnosticInfo {

43private:

44 const Twine &Msg;

46

47public:

48

49

50

51 DiagnosticInfoValidateMD(const Module &M,

54 : DiagnosticInfo(DK_Unsupported, Severity), Msg(Msg), Mod(M) {}

55

56 void print(DiagnosticPrinter &DP) const override {

57 DP << Mod.getName() << ": " << Msg << '\n';

58 }

59};

60

63 M.getContext().diagnose(DiagnosticInfoValidateMD(M, Message, Severity));

64}

65

66static void reportLoopError(Module &M, Twine Message,

68 reportError(M, Twine("Invalid \"llvm.loop\" metadata: ") + Message, Severity);

69}

70

71enum class EntryPropsTag {

72 ShaderFlags = 0,

73 GSState,

74 DSState,

75 HSState,

76 NumThreads,

77 AutoBindingSpace,

78 RayPayloadSize,

79 RayAttribSize,

80 ShaderKind,

81 MSState,

82 ASStateTag,

83 WaveSize,

84 EntryRootSig,

85 WaveRange = 23,

86};

87

88}

89

93

95 if (!RI.hasSymbol())

96 RI.createSymbol(M,

97 DRTM[RI.getHandleTy()].createElementStruct(RI.getName()));

98

101 SRVs.push_back(RI.getAsMetadata(M, DRTM[RI.getHandleTy()]));

103 UAVs.push_back(RI.getAsMetadata(M, DRTM[RI.getHandleTy()]));

105 CBufs.push_back(RI.getAsMetadata(M, DRTM[RI.getHandleTy()]));

107 Smps.push_back(RI.getAsMetadata(M, DRTM[RI.getHandleTy()]));

108

113

115 return nullptr;

116

117 NamedMDNode *ResourceMD = M.getOrInsertNamedMetadata("dx.resources");

119 MDNode::get(M.getContext(), {SRVMD, UAVMD, CBufMD, SmpMD}));

120

121 return ResourceMD;

122}

123

125 switch (Env) {

127 return "ps";

129 return "vs";

131 return "gs";

133 return "hs";

135 return "ds";

137 return "cs";

139 return "lib";

141 return "ms";

143 return "as";

145 return "rootsig";

146 default:

147 break;

148 }

149 llvm_unreachable("Unsupported environment for DXIL generation.");

150}

151

155

160 ConstantInt::get(Type::getInt32Ty(Ctx), static_cast<int>(Tag))));

161 switch (Tag) {

162 case EntryPropsTag::ShaderFlags:

165 break;

166 case EntryPropsTag::ShaderKind:

169 break;

170 case EntryPropsTag::GSState:

171 case EntryPropsTag::DSState:

172 case EntryPropsTag::HSState:

173 case EntryPropsTag::NumThreads:

174 case EntryPropsTag::AutoBindingSpace:

175 case EntryPropsTag::RayPayloadSize:

176 case EntryPropsTag::RayAttribSize:

177 case EntryPropsTag::MSState:

178 case EntryPropsTag::ASStateTag:

179 case EntryPropsTag::WaveSize:

180 case EntryPropsTag::EntryRootSig:

181 case EntryPropsTag::WaveRange:

183 }

184 return MDVals;

185}

186

192 if (EntryShaderFlags != 0)

194 EntryShaderFlags, Ctx));

195

196 if (EP.Entry != nullptr) {

197

198

199

204

206

208 Type::getInt32Ty(Ctx), static_cast<int>(EntryPropsTag::NumThreads))));

216

217

218

221 bool IsWaveSize =

223

224 if (!IsWaveRange && !IsWaveSize) {

225 reportError(M, "Shader model 6.6 or greater is required to specify "

226 "the \"hlsl.wavesize\" function attribute");

227 return nullptr;

228 }

229

230

233 M, "Shader model 6.8 or greater is required to specify "

234 "wave size range values of the \"hlsl.wavesize\" function "

235 "attribute");

236 return nullptr;

237 }

238

239 EntryPropsTag Tag =

240 IsWaveSize ? EntryPropsTag::WaveSize : EntryPropsTag::WaveRange;

242 ConstantInt::get(Type::getInt32Ty(Ctx), static_cast<int>(Tag))));

243

246 if (IsWaveRange) {

251 }

252

254 }

255 }

256 }

257

258 if (MDVals.empty())

259 return nullptr;

261}

262

266

267

268

269

270

271

273 MDVals[0] =

276 MDVals[2] = Signatures;

277 MDVals[3] = Resources;

278 MDVals[4] = Properties;

280}

281

284 const uint64_t EntryShaderFlags,

289}

290

293 return;

294

298 MDVals[0] =

302 NamedMDNode *ValVerNode = M.getOrInsertNamedMetadata("dx.valver");

303

306}

307

317 NamedMDNode *SMMDNode = M.getOrInsertNamedMetadata("dx.shaderModel");

319}

320

327 DXILVals[1] =

329 NamedMDNode *DXILVerMDNode = M.getOrInsertNamedMetadata("dx.version");

331}

332

336 MDTuple *Properties = nullptr;

337 if (ShaderFlags != 0) {

342 }

343

344

346}

347

349 MDNode *HlslControlFlowMD =

350 BBTerminatorInst->getMetadata("hlsl.controlflow.hint");

351

352 if (!HlslControlFlowMD)

353 return;

354

356 "invalid operands for hlsl.controlflow.hint");

357

358 MDBuilder MDHelper(M.getContext());

359

363

365

367 BBTerminatorInst->setMetadata("hlsl.controlflow.hint", nullptr);

368}

369

370

371

372

373

375

376 std::array<StringLiteral, 3> ValidHintNames = {"llvm.loop.unroll.count",

377 "llvm.loop.unroll.disable",

378 "llvm.loop.unroll.full"};

379

382 return false;

383

385 if (!HintStr)

386 return false;

387

389 return false;

390

391 auto ValidCountNode = [](MDNode *CountMD) -> bool {

392 if (CountMD->getNumOperands() == 2)

395 return true;

396 return false;

397 };

398

399 if (HintStr->getString() == "llvm.loop.unroll.count") {

400 if (!ValidCountNode(HintMD)) {

401 reportLoopError(M, "\"llvm.loop.unroll.count\" must have 2 operands and "

402 "the second must be a constant integer");

403 return false;

404 }

406 reportLoopError(

407 M, "\"llvm.loop.unroll.disable\" and \"llvm.loop.unroll.full\" "

408 "must be provided as a single operand");

409 return false;

410 }

411

412 return true;

413}

414

416

417 auto IsDistinctNode = [](MDNode *Node) -> bool {

418 return Node && Node->getNumOperands() != 0 && Node == Node->getOperand(0);

419 };

420

421

422 if (BaseMD->getNumOperands() == 0 || !IsDistinctNode(BaseMD))

423 return I->setMetadata("llvm.loop", nullptr);

424

425

426

427

428

429

430

431

432

433

434

438

439

440

443

444

445

450

451 if (2 < CompatibleOperands.size())

452 reportLoopError(M, "Provided conflicting hints");

453

454 MDNode *CompatibleLoopMD = MDNode::get(M.getContext(), CompatibleOperands);

455 TempNode->replaceAllUsesWith(CompatibleLoopMD);

456

457 I->setMetadata("llvm.loop", CompatibleLoopMD);

458}

459

461

463 return {

464 M.getMDKindID("dx.nonuniform"), M.getMDKindID("dx.controlflow.hints"),

465 M.getMDKindID("dx.precise"), llvm::LLVMContext::MD_range,

466 llvm::LLVMContext::MD_alias_scope, llvm::LLVMContext::MD_noalias,

467 M.getMDKindID("llvm.loop")};

468}

469

471

473 unsigned char MDLoopKind = M.getContext().getMDKindID("llvm.loop");

474

477

478

479 if (auto *I = BB.getTerminator())

481

484 if (MDNode *LoopMD = I.getMetadata(MDLoopKind))

486 I.dropUnknownNonDebugMetadata(DXILCompatibleMDs);

487 }

488 }

489 }

490}

491

493 NamedMDNode *MDFlags = M.getModuleFlagsMetadata();

494 if (!MDFlags)

495 return;

496

498 M.getModuleFlagsMetadata(FlagEntries);

499 bool Updated = false;

500 for (auto &Flag : FlagEntries) {

501

503 continue;

505 Updated = true;

506 }

507

508 if (!Updated)

509 return;

510

512

513 for (auto &Flag : FlagEntries)

514 M.addModuleFlag(Flag.Behavior, Flag.Key->getString(), Flag.Val);

515}

516

518

519

520

521

523 "llvm.ident", "llvm.module.flags", "dx.resources", "dx.valver",

524 "dx.shaderModel", "dx.version", "dx.entryPoints",

525};

526

534

539 auto *ResourceMD =

540 (NamedResourceMD != nullptr) ? NamedResourceMD->getOperand(0) : nullptr;

541

542

543 MDTuple *Signatures = nullptr;

544

546

547

548

549 uint64_t CombinedMask = ShaderFlags.getCombinedFlags();

553 reportError(M, "Non-library shader: One and only one entry expected");

554

556 uint64_t EntryShaderFlags = 0;

558 EntryShaderFlags = ShaderFlags.getFunctionFlags(EntryProp.Entry);

561 M, "Shader stage '" +

564 "' different from specified target profile '" +

566 "'"));

567 }

569 M, EntryProp, Signatures, ResourceMD, EntryShaderFlags, MMDI));

570 }

571

573 M.getOrInsertNamedMetadata("dx.entryPoints");

574 for (auto *Entry : EntryFnMDNodes)

575 EntryPointsNamedMD->addOperand(Entry);

576

578

579

580

582

583 for (NamedMDNode &NamedMD : M.named_metadata())

584 if (!NamedMD.getName().starts_with("llvm.dbg.") &&

587

589 NamedMD->eraseFromParent();

590}

591

604

618

628

631 return true;

632}

633

635

639

641 "DXIL Translate Metadata", false, false)

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

static Error reportError(StringRef Message)

#define LLVM_LIFETIME_BOUND

This file contains the declarations for the subclasses of Constant, which represent the different fla...

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

Machine Check Debug Module

ModuleAnalysisManager MAM

#define INITIALIZE_PASS_DEPENDENCY(depName)

#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)

#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)

This file defines the SmallVector class.

Defines the llvm::VersionTuple class, which represents a version in the form major[....

Represent the analysis usage information of a pass.

AnalysisUsage & addRequired()

AnalysisUsage & addPreserved()

Add the specified Pass class to the set of analyses preserved by this pass.

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

ArrayRef< T > drop_front(size_t N=1) const

Drop the first N elements of the array.

LLVM Basic Block Representation.

iterator_range< iterator > samplers()

iterator_range< iterator > srvs()

iterator_range< iterator > cbuffers()

iterator_range< iterator > uavs()

This is the base abstract class for diagnostic reporting in the backend.

LLVMContext & getContext() const

getContext - Return a reference to the LLVMContext associated with this function.

ConstantInt * getInt32(uint32_t C)

Get a constant 32-bit value.

This provides a uniform API for creating instructions and inserting them into a basic block: either a...

MDNode * getMetadata(unsigned KindID) const

Get the metadata of given kind attached to this Instruction.

LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)

Set the metadata of the specified kind to the specified node.

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

LLVM_ABI ConstantAsMetadata * createConstant(Constant *C)

Return the given constant as metadata.

LLVM_ABI MDString * createString(StringRef Str)

Return the given string as metadata.

const MDOperand & getOperand(unsigned I) const

static TempMDTuple getTemporary(LLVMContext &Context, ArrayRef< Metadata * > MDs)

ArrayRef< MDOperand > operands() const

static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)

unsigned getNumOperands() const

Return number of MDNode operands.

static LLVM_ABI MDString * get(LLVMContext &Context, StringRef Str)

ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...

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

@ AppendUnique

Appends the two values, which are required to be metadata nodes.

@ Warning

Emits a warning if two values disagree.

LLVM_ABI void eraseFromParent()

Drop all references and remove the node from parent module.

LLVM_ABI MDNode * getOperand(unsigned i) const

LLVM_ABI void clearOperands()

Drop all references to this node's operands.

LLVM_ABI void addOperand(MDNode *M)

AnalysisType & getAnalysis() const

getAnalysis() - This function is used by subclasses to get to the analysis information ...

A set of analyses that are preserved following a run of a transformation pass.

static PreservedAnalyses all()

Construct a special preserved set that preserves all passes.

reference emplace_back(ArgTypes &&... Args)

void append(ItTy in_start, ItTy in_end)

Add the specified range to the end of the SmallVector.

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

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

static LLVM_ABI StringRef getEnvironmentTypeName(EnvironmentType Kind)

Get the canonical name for the Kind environment.

Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...

static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)

static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)

LLVM Value Representation.

LLVM_ABI StringRef getName() const

Return a constant reference to the value's name.

Represents a version number in the form major[.minor[.subminor[.build]]].

unsigned getMajor() const

Retrieve the major version number.

bool empty() const

Determine whether this version information is empty (e.g., all version components are zero).

std::optional< unsigned > getMinor() const

Retrieve the minor version number, if provided.

Wrapper pass for the legacy pass manager.

Wrapper pass for the legacy pass manager.

#define llvm_unreachable(msg)

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

std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract(Y &&MD)

Extract a Value from Metadata.

This is an optimization pass for GlobalISel generic memory operations.

Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)

decltype(auto) dyn_cast(const From &Val)

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

ModulePass * createDXILTranslateMetadataLegacyPass()

Pass to emit metadata for DXIL.

Definition DXILTranslateMetadata.cpp:636

iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)

Make a range that does early increment to allow mutation of the underlying range without disrupting i...

FunctionAddr VTableAddr Count

bool isa(const From &Val)

isa - Return true if the parameter to the template is an instance of one of the template type argu...

DWARFExpression::Operation Op

DiagnosticSeverity

Defines the different supported severity of a diagnostic.

bool is_contained(R &&Range, const E &Element)

Returns true if Element is found in Range.

AnalysisManager< Module > ModuleAnalysisManager

Convenience typedef for the Module analysis manager.

Triple::EnvironmentType ShaderStage