LLVM 24.0.0git
DXILSignatureAnalysis.cpp
Go to the documentation of this file.
1//===- DXILSignatureAnalysis.cpp - Semantic signatures --------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10#include "DirectX.h"
11#include "llvm/ADT/STLExtras.h"
15#include "llvm/IR/Constants.h"
18#include "llvm/IR/IntrinsicsDirectX.h"
19#include "llvm/IR/Module.h"
22#include "llvm/Support/Error.h"
24#include <array>
25#include <set>
26
27using namespace llvm;
28using namespace llvm::dxil;
29using namespace llvm::hlsl;
30
31static Error signatureError(const Twine &Message) {
33}
34
35static bool isSignatureAccess(const IntrinsicInst &I) {
36 return I.getIntrinsicID() == Intrinsic::dx_load_input ||
37 I.getIntrinsicID() == Intrinsic::dx_store_output;
38}
39
40// Validate widths before fromMetadata extracts integer values or narrows them.
42 if (!Node || Node->getNumOperands() != 13)
43 return signatureError("expected a 13-operand signature element");
44 for (unsigned I = 0; I != 13; ++I) {
45 if (I == 1 || I == 4)
46 continue;
47 auto *CI = mdconst::dyn_extract_or_null<ConstantInt>(Node->getOperand(I));
48 unsigned Width = (I == 7 || (I >= 9 && I <= 11)) ? 8 : 32;
49 if (!CI || CI->getBitWidth() != Width)
50 return signatureError("expected i" + Twine(Width) + " at operand " +
51 Twine(I));
52 }
53 if (!isa_and_nonnull<MDString>(Node->getOperand(1)))
54 return signatureError("expected semantic name string");
55 auto *Indices = dyn_cast_or_null<MDNode>(Node->getOperand(4));
56 if (!Indices)
57 return signatureError("expected semantic indices node");
58 for (const MDOperand &Index : Indices->operands()) {
60 if (!CI || CI->getBitWidth() != 32)
61 return signatureError("expected i32 semantic index");
62 }
63 return Error::success();
64}
65
71
73 switch (E.SemanticKind) {
74 case dxbc::PSV::SemanticKind::Position:
75 if (E.Rows != 1 || E.Cols != 4 ||
76 (E.CompType != ElementType::F16 && E.CompType != ElementType::F32))
77 return signatureError(
78 "SV_Position requires one row of four floating-point components");
79 break;
80 case dxbc::PSV::SemanticKind::VertexID:
81 if (E.Rows != 1 || E.Cols != 1 ||
82 (E.CompType != ElementType::I16 && E.CompType != ElementType::U16 &&
83 E.CompType != ElementType::I32 && E.CompType != ElementType::U32))
84 return signatureError(
85 "SV_VertexID requires a scalar 16- or 32-bit integer");
86 break;
87 case dxbc::PSV::SemanticKind::InstanceID:
88 if (E.Rows != 1 || E.Cols != 1 ||
89 (E.CompType != ElementType::U16 && E.CompType != ElementType::U32))
90 return signatureError(
91 "SV_InstanceID requires a scalar 16- or 32-bit unsigned integer");
92 break;
93 default:
94 break;
95 }
96 return Error::success();
97}
98
100 switch (E.SemanticKind) {
101 case dxbc::PSV::SemanticKind::Target:
102 if (E.Rows != 1 || E.SemanticIndices.front() >= 8)
103 return signatureError(
104 "pixel targets require one row and an index within 0-7");
105 break;
106 case dxbc::PSV::SemanticKind::VertexID:
107 if (E.SemanticIndices.front() != 0)
108 return signatureError("SV_VertexID requires semantic index 0");
109 break;
110 default:
111 break;
112 }
113 return Error::success();
114}
115
120 bool Native16, unsigned &Extent) {
121 if (!MD)
122 return Error::success();
123 auto *List = dyn_cast<MDNode>(MD);
124 if (!List)
125 return signatureError("expected a signature element list or null");
126 if (List->getNumOperands() > 128)
127 return signatureError("too many signature elements");
128
129 std::set<std::pair<std::string, uint32_t>> Semantics;
130 std::array<uint8_t, MaxSignatureRows> AllocatedColumns = {};
131 std::array<dxbc::PSV::InterpolationMode, MaxSignatureRows> RowModes = {};
132 std::array<bool, MaxSignatureRows> RowNative16 = {};
133 for (const MDOperand &Op : List->operands()) {
135 if (Error Err = checkElementNode(Node))
136 return Err;
138 if (!Parsed)
139 return Parsed.takeError();
140 SemanticSignatureElement E = std::move(*Parsed);
141 if (E.SigId != Out.size())
142 return signatureError("signature IDs must be dense and in list order");
143 if (Stage != Triple::Vertex && Stage != Triple::Pixel)
144 return signatureError("nonempty signatures are currently supported only "
145 "for vertex and pixel entries");
146 if (!E.Rows || E.Rows > MaxSignatureRows)
147 return signatureError("signature row count must be within 1-32");
148 if (E.SemanticName.empty() || E.SemanticName.contains('\0'))
149 return signatureError("invalid semantic name");
150 if (E.CompType != ElementType::F16 && E.CompType != ElementType::F32 &&
151 !isIntegerComponent(E.CompType))
152 return signatureError("unsupported signature component type");
153 if (E.GSStream != 0)
154 return signatureError("nonzero stream requires a geometry output");
155 auto NamedKind = getSemanticKind(E.SemanticName);
156 auto Interpretation = getInterpretationKind(NamedKind, Stage, IO);
157 if (Interpretation == SemanticInterpretation::Invalid)
158 return signatureError("invalid or unsupported semantic for this stage "
159 "and signature category");
160 if (Interpretation == SemanticInterpretation::NotAllocated)
161 return signatureError("semantic accessed by a dedicated intrinsic must "
162 "not appear in an input/output signature");
163 auto ExpectedKind = Interpretation == SemanticInterpretation::Arbitrary
164 ? dxbc::PSV::SemanticKind::Arbitrary
165 : NamedKind;
166 if (E.SemanticKind != ExpectedKind)
167 return signatureError("semantic name and kind disagree at this signature "
168 "point");
169 if (!E.isAllocated())
170 return signatureError("signature element " + Twine(E.SigId) + " ('" +
171 E.SemanticName + "') has no allocated location");
172 if (E.StartRow >= MaxSignatureRows ||
173 E.Rows > MaxSignatureRows - E.StartRow || E.StartCol + E.Cols > 4)
174 return signatureError(
175 "allocated signature element exceeds register bounds");
176 if (E.InterpMode == dxbc::PSV::InterpolationMode::Invalid)
177 return signatureError("invalid interpolation mode");
178
179 for (uint32_t Index : E.SemanticIndices)
180 if (!Semantics.emplace(E.SemanticName.upper(), Index).second)
181 return signatureError("duplicate semantic name and index");
182 if (Error Err = validateSemanticType(E))
183 return Err;
184 if (Error Err = validateSemanticIndex(E))
185 return Err;
186
187 if (Stage == Triple::Vertex && IO == IOType::In &&
188 (E.StartRow != Extent || E.StartCol != 0))
189 return signatureError("vertex inputs require stacked locations in "
190 "signature order (element " +
191 Twine(E.SigId) + ")");
192 if (Interpretation == SemanticInterpretation::Target &&
193 (E.StartRow != E.SemanticIndices.front() || E.StartCol != 0))
194 return signatureError("pixel target location must match its semantic "
195 "index at column 0");
196 if (Stage == Triple::Pixel && IO == IOType::In &&
197 isIntegerComponent(E.CompType) &&
198 E.InterpMode != dxbc::PSV::InterpolationMode::Constant)
199 return signatureError(
200 "integer pixel inputs require constant interpolation");
201
202 // Co-packed elements must obey row constraints, even when their component
203 // masks do not overlap. Min-precision types occupy 32-bit components.
204 bool IsNative16 = Native16 && (E.CompType == ElementType::F16 ||
205 E.CompType == ElementType::I16 ||
206 E.CompType == ElementType::U16);
207 uint8_t Mask = E.getDeclaredMask();
208 for (unsigned Row = E.StartRow; Row != E.StartRow + E.Rows; ++Row) {
209 if (AllocatedColumns[Row] & Mask)
210 return signatureError("signature elements overlap at row " +
211 Twine(Row) + " (element " + Twine(E.SigId) + ")");
212 if (AllocatedColumns[Row] && RowModes[Row] != E.InterpMode)
213 return signatureError("signature elements have different interpolation "
214 "modes at row " +
215 Twine(Row) + " (element " + Twine(E.SigId) + ")");
216 if (AllocatedColumns[Row] && RowNative16[Row] != IsNative16)
217 return signatureError("signature elements have different component "
218 "widths at row " +
219 Twine(Row) + " (element " + Twine(E.SigId) + ")");
220 AllocatedColumns[Row] |= Mask;
221 RowModes[Row] = E.InterpMode;
222 RowNative16[Row] = IsNative16;
223 }
224 Extent = std::max(Extent, E.StartRow + E.Rows);
225 E.SemanticName = Info.Names.insert(E.SemanticName).first->getKey();
226
227 // Access masks will be recomputed so reset to 0 here.
228 E.UsageMask = 0;
229 E.DynIndexMask = 0;
230 Out.push_back(std::move(E));
231 }
232 return Error::success();
233}
234
236 bool Input = I.getIntrinsicID() == Intrinsic::dx_load_input;
237 auto &Elements = Input ? Sig.Inputs : Sig.Outputs;
238 auto *ID = dyn_cast<ConstantInt>(I.getArgOperand(0));
239 auto *Col = dyn_cast<ConstantInt>(I.getArgOperand(2));
240 StringRef Category = Input ? "input" : "output";
241 if (!ID)
242 return signatureError(Category +
243 " signature: signature access requires a constant "
244 "element ID");
245 if (ID->getZExtValue() >= Elements.size())
246 return signatureError(Category +
247 " signature: signature access has an invalid element "
248 "ID " +
249 Twine(ID->getZExtValue()));
250 auto &E = Elements[ID->getZExtValue()];
251 auto AccessError = [&](const Twine &Message) {
252 return signatureError(Category + " signature element " + Twine(E.SigId) +
253 " ('" + E.SemanticName + "'): " + Message);
254 };
255 Type *Ty = Input ? I.getType() : I.getArgOperand(3)->getType();
256 unsigned Width = 1;
257 if (auto *VT = dyn_cast<FixedVectorType>(Ty)) {
258 Width = VT->getNumElements();
259 Ty = VT->getElementType();
260 }
261 if (!Col || Col->getZExtValue() >= E.Cols ||
262 Width > E.Cols - Col->getZExtValue())
263 return AccessError("signature access has an invalid component index");
264 auto *Row = dyn_cast<ConstantInt>(I.getArgOperand(1));
265 if (Row && Row->getZExtValue() >= E.Rows)
266 return AccessError("signature access has an invalid row index");
267 if (!Row && E.Rows == 1)
268 return AccessError(
269 "dynamic indexing requires a multi-row signature element");
270 bool CorrectType = false;
271 switch (E.CompType) {
272 case ElementType::F16:
273 CorrectType = Ty->isHalfTy();
274 break;
275 case ElementType::F32:
276 CorrectType = Ty->isFloatTy();
277 break;
278 case ElementType::I16:
279 case ElementType::U16:
280 CorrectType = Ty->isIntegerTy(16);
281 break;
282 case ElementType::I1:
283 // Boolean signature elements use the i32 load/store overload.
284 CorrectType = Ty->isIntegerTy(32);
285 break;
286 case ElementType::I32:
287 case ElementType::U32:
288 CorrectType = Ty->isIntegerTy(32);
289 break;
290 default:
291 llvm_unreachable("invalid signature component type");
292 }
293 if (!CorrectType)
294 return AccessError("signature access type disagrees with its element");
295 uint8_t Mask = ((1U << Width) - 1) << Col->getZExtValue();
296 E.UsageMask |= Mask << E.StartCol;
297 if (!Row)
298 E.DynIndexMask |= Mask;
299 return Error::success();
300}
301
303 // Each output vector needs four component bits, so one 32-bit word holds
304 // eight vectors. Adding seven rounds up to include a partially filled word.
305 unsigned Words = (Sig.OutputVectors + 7) / 8;
306 Sig.InputOutputMap.assign(Sig.InputVectors * 4 * Words, 0);
307 // Conservatively connect every accessed input component to every written
308 // output component. This includes control, memory, call, and dynamic-index
309 // dependencies without incorrectly claiming that unknown dependencies are
310 // absent. Unused components and padding remain zero. Both DXIL and PSV use
311 // this same map; a more precise dependency analysis can refine it later.
312 for (const auto &Input : Sig.Inputs)
313 for (unsigned IR = 0; IR != Input.Rows; ++IR)
314 for (unsigned IC = 0; IC != 4; ++IC) {
315 if (!(Input.UsageMask & (1U << IC)))
316 continue;
317 unsigned Base = ((Input.StartRow + IR) * 4 + IC) * Words;
318 for (const auto &Output : Sig.Outputs)
319 for (unsigned OR = 0; OR != Output.Rows; ++OR)
320 for (unsigned OC = 0; OC != 4; ++OC) {
321 if (!(Output.UsageMask & (1U << OC)))
322 continue;
323 unsigned Bit = (Output.StartRow + OR) * 4 + OC;
324 Sig.InputOutputMap[Base + Bit / 32] |= 1U << (Bit % 32);
325 }
326 }
327}
328
332 if (NamedMDNode *Table = M.getNamedMetadata("dx.semantic.signatures")) {
333 for (const MDNode *Record : Table->operands()) {
334 if (Record->getNumOperands() != 3)
335 return signatureError(
336 "expected an entry/input/output signature triple");
337 auto *VAM = dyn_cast_or_null<ValueAsMetadata>(Record->getOperand(0));
338 auto *F = VAM ? dyn_cast<Function>(VAM->getValue()) : nullptr;
339 if (!F || F->getParent() != &M || F->isDeclaration())
340 return signatureError(
341 "signature entry must be a defined function in the module");
342 auto EP =
344 [F](const EntryProperties &E) { return E.Entry == F; });
345 if (EP == MMI.EntryPropertyVec.end())
346 return signatureError("signature function is not a shader entry");
347 if (Info.Entries.contains(F))
348 return signatureError("duplicate signature record for entry '" +
349 F->getName() + "'");
350 EntrySignature Sig;
351 Sig.Stage = EP->ShaderStage;
353 M.getModuleFlag("dx.nativelowprec")))
354 Sig.UseNative16Bit = !Native->isZero();
355 if (Sig.UseNative16Bit && MMI.ShaderModelVersion < VersionTuple(6, 2))
356 return signatureError(
357 "native 16-bit signatures require shader model 6.2");
358 auto AddContext = [&](Error Err, StringRef Category) -> Error {
359 return signatureError("entry '" + F->getName() + "' " + Category +
360 " signature: " + toString(std::move(Err)));
361 };
362 if (Error Err =
363 parseSignature(Record->getOperand(1), Sig.Inputs, Info, Sig.Stage,
365 return AddContext(std::move(Err), "input");
366 if (Error Err = parseSignature(Record->getOperand(2), Sig.Outputs, Info,
368 Sig.OutputVectors))
369 return AddContext(std::move(Err), "output");
370 for (const Instruction &I : instructions(F))
371 if (auto *II = dyn_cast<IntrinsicInst>(&I);
373 if (Error Err = analyzeAccess(*II, Sig))
374 return signatureError("entry '" + F->getName() +
375 "': " + toString(std::move(Err)));
377 Info.Entries.try_emplace(F, std::move(Sig));
378 }
379 }
380 // Signature IDs are local to an entry. Do not guess which entry a helper's
381 // accesses belong to, even if that helper happens to have a single caller.
382 for (const Function &F : M)
383 if (!Info.Entries.contains(&F))
384 for (const Instruction &I : instructions(F))
385 if (auto *II = dyn_cast<IntrinsicInst>(&I);
387 return signatureError("signature access in function '" + F.getName() +
388 "' has no entry signature metadata");
389 return std::move(Info);
390}
391
393 const ModuleMetadataInfo &MMI) {
394 auto Result = analyzeModule(M, MMI);
395 if (!Result) {
396 M.getContext().emitError("Invalid semantic signature: " +
397 toString(Result.takeError()));
398 return ModuleSignatureInfo();
399 }
400 return std::move(*Result);
401}
402
405 VersionTuple ValidatorVersion) {
406 if (Elements.empty())
407 return nullptr;
408 auto I32 = [&](uint32_t V) {
409 return ConstantAsMetadata::get(ConstantInt::get(Type::getInt32Ty(Ctx), V));
410 };
411 auto I8 = [&](uint8_t V) {
412 return ConstantAsMetadata::get(ConstantInt::get(Type::getInt8Ty(Ctx), V));
413 };
415 for (const auto &E : Elements) {
416 SmallVector<Metadata *> Indices, Props;
417 for (uint32_t Index : E.SemanticIndices)
418 Indices.push_back(I32(Index));
419 if (E.GSStream)
420 Props.append({I32(0), I32(E.GSStream)});
421 if (E.DynIndexMask)
422 Props.append({I32(2), I32(E.DynIndexMask)});
423 if (E.UsageMask &&
424 (ValidatorVersion.empty() || ValidatorVersion == VersionTuple(0, 0) ||
425 ValidatorVersion >= VersionTuple(1, 5)))
426 Props.append({I32(3), I32(E.UsageMask >> E.StartCol)});
428 Ctx, {I32(E.SigId), MDString::get(Ctx, E.SemanticName),
429 I8(static_cast<uint8_t>(E.CompType)),
430 I8(static_cast<uint8_t>(E.SemanticKind)),
431 MDNode::get(Ctx, Indices), I8(static_cast<uint8_t>(E.InterpMode)),
432 I32(E.Rows), I8(E.Cols), I32(E.StartRow), I8(E.StartCol),
433 Props.empty() ? nullptr : MDNode::get(Ctx, Props)}));
434 }
435 return MDNode::get(Ctx, Nodes);
436}
437
439 switch (Type) {
440 case ElementType::I1:
441 return Legacy ? dxbc::SigComponentType::Unknown
442 : dxbc::SigComponentType::UInt32;
443 case ElementType::I16:
444 return dxbc::SigComponentType::SInt16;
445 case ElementType::U16:
446 return dxbc::SigComponentType::UInt16;
447 case ElementType::I32:
448 return dxbc::SigComponentType::SInt32;
449 case ElementType::U32:
450 return dxbc::SigComponentType::UInt32;
451 case ElementType::F16:
452 return dxbc::SigComponentType::Float16;
453 case ElementType::F32:
454 return dxbc::SigComponentType::Float32;
455 default:
456 llvm_unreachable("invalid signature component type");
457 }
458}
459
461 using KindTy = dxbc::PSV::SemanticKind;
462 switch (Kind) {
463 case KindTy::Arbitrary:
464 return dxbc::D3DSystemValue::Undefined;
465 case KindTy::VertexID:
466 return dxbc::D3DSystemValue::VertexID;
467 case KindTy::InstanceID:
468 return dxbc::D3DSystemValue::InstanceID;
469 case KindTy::Position:
470 return dxbc::D3DSystemValue::Position;
471 case KindTy::IsFrontFace:
472 return dxbc::D3DSystemValue::IsFrontFace;
473 case KindTy::ClipDistance:
474 return dxbc::D3DSystemValue::ClipDistance;
475 case KindTy::CullDistance:
476 return dxbc::D3DSystemValue::CullDistance;
477 case KindTy::Target:
478 return dxbc::D3DSystemValue::Target;
479 default:
480 llvm_unreachable("validated vertex/pixel signature semantic");
481 }
482}
483
484// The DXIL reader normalizes system-value semantic names when loading module
485// metadata. The validator then recreates ISG1/OSG1 from those normalized names
486// and compares the parts byte-for-byte, so the container must use the same
487// spelling even if HLSL (or the source metadata) used a different casing.
489 using Kind = dxbc::PSV::SemanticKind;
490 switch (E.SemanticKind) {
491 case Kind::Arbitrary:
492 return E.SemanticName;
493 case Kind::VertexID:
494 return "SV_VertexID";
495 case Kind::InstanceID:
496 return "SV_InstanceID";
497 case Kind::Position:
498 return "SV_Position";
499 case Kind::IsFrontFace:
500 return "SV_IsFrontFace";
501 case Kind::ClipDistance:
502 return "SV_ClipDistance";
503 case Kind::CullDistance:
504 return "SV_CullDistance";
505 case Kind::Target:
506 return "SV_Target";
507 default:
508 llvm_unreachable("validated vertex/pixel signature semantic");
509 }
510}
511
514 bool Input, bool Native16, bool Legacy) {
515 for (const auto &E : Elements) {
516 uint8_t Mask = E.getDeclaredMask();
517 uint8_t ExclusiveMask =
518 Input ? E.getAlwaysReadsMask() : E.getNeverWritesMask();
519 if (Legacy)
520 ExclusiveMask = Input ? 0 : static_cast<uint8_t>(~Mask);
521 for (auto [Row, Index] : enumerate(E.SemanticIndices))
522 Sig.addParam(E.GSStream, getContainerSemanticName(E), Index,
523 getSystemValue(E.SemanticKind),
524 getComponentType(E.CompType, Legacy), E.StartRow + Row, Mask,
525 ExclusiveMask, E.getMinPrecision(!Native16));
526 }
527}
528
531 bool Legacy) {
532 for (const auto &E : Elements) {
533 auto Type = getComponentType(E.CompType, Legacy);
534 // SigComponentType and PSV ComponentType share COMPONENT_TYPE definitions.
535 Dest.push_back({E.SemanticKind == dxbc::PSV::SemanticKind::Arbitrary
536 ? E.SemanticName
537 : StringRef(),
538 E.SemanticIndices, static_cast<uint8_t>(E.StartRow), E.Cols,
539 E.StartCol, E.isAllocated(), E.SemanticKind,
540 static_cast<dxbc::PSV::ComponentType>(Type), E.InterpMode,
541 E.DynIndexMask, static_cast<uint8_t>(E.GSStream)});
542 }
543}
544
546 VersionTuple ValidatorVersion) const {
547 if (Inputs.empty() && Outputs.empty())
548 return nullptr;
549 return MDNode::get(Ctx,
550 {emitSignature(Ctx, Inputs, ValidatorVersion),
551 emitSignature(Ctx, Outputs, ValidatorVersion), nullptr});
552}
553
555 mcdxbc::Signature &Output,
556 VersionTuple ValidatorVersion) const {
557 bool Legacy = !ValidatorVersion.empty() &&
558 ValidatorVersion != VersionTuple(0, 0) &&
559 ValidatorVersion < VersionTuple(1, 5);
562}
563
565 VersionTuple ValidatorVersion) const {
566 bool Legacy = !ValidatorVersion.empty() &&
567 ValidatorVersion != VersionTuple(0, 0) &&
568 ValidatorVersion < VersionTuple(1, 5);
574 if (Stage == Triple::Vertex)
576 llvm::any_of(Outputs, [](const auto &E) {
577 return E.SemanticKind == dxbc::PSV::SemanticKind::Position;
578 });
579 if (Stage == Triple::Pixel)
581 llvm::any_of(Inputs, [](const auto &E) {
582 return E.InterpMode == dxbc::PSV::InterpolationMode::LinearSample ||
583 E.InterpMode ==
584 dxbc::PSV::InterpolationMode::LinearNoperspectiveSample;
585 });
586}
587
593
595 auto Print = [&](StringRef Name, ArrayRef<SemanticSignatureElement> Elements,
596 unsigned Vectors) {
597 OS << " " << Name << ": " << Elements.size() << " elements, " << Vectors
598 << " vectors\n";
599 for (const auto &E : Elements)
600 OS << " " << E.SigId << ": " << E.SemanticName << " rows=" << E.Rows
601 << " cols=" << unsigned(E.Cols) << " at " << E.StartRow << ":"
602 << unsigned(E.StartCol) << " usage=" << unsigned(E.UsageMask)
603 << " dynamic=" << unsigned(E.DynIndexMask) << '\n';
604 };
605 Print("Inputs", Inputs, InputVectors);
606 Print("Outputs", Outputs, OutputVectors);
607}
608
610 for (const Function &F : M)
611 if (const auto *Sig = get(&F)) {
612 OS << "Semantic signatures for '" << F.getName() << "':\n";
613 Sig->print(OS);
614 }
615}
616
617AnalysisKey SignatureAnalysis::Key;
622
628
630 Info = std::make_unique<ModuleSignatureInfo>(collectSignatures(
631 M, getAnalysis<DXILMetadataAnalysisWrapperPass>().getModuleMetadata()));
632 return false;
633}
634
639
641 if (Info)
642 Info->print(OS, *M);
643}
644
647 "DXIL Semantic Signature Analysis", false, true)
650 "DXIL Semantic Signature Analysis", false, true)
Expand Atomic instructions
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static bool isSignatureAccess(const IntrinsicInst &I)
static bool isIntegerComponent(ElementType Type)
static Error validateSemanticType(const SemanticSignatureElement &E)
static MDNode * emitSignature(LLVMContext &Ctx, ArrayRef< SemanticSignatureElement > Elements, VersionTuple ValidatorVersion)
static void buildSignature(mcdxbc::Signature &Sig, ArrayRef< SemanticSignatureElement > Elements, bool Input, bool Native16, bool Legacy)
static dxbc::D3DSystemValue getSystemValue(dxbc::PSV::SemanticKind Kind)
static Expected< ModuleSignatureInfo > analyzeModule(Module &M, const ModuleMetadataInfo &MMI)
static ModuleSignatureInfo collectSignatures(Module &M, const ModuleMetadataInfo &MMI)
static dxbc::SigComponentType getComponentType(ElementType Type, bool Legacy)
static void buildDependencyMap(EntrySignature &Sig)
static Error parseSignature(Metadata *MD, SmallVectorImpl< SemanticSignatureElement > &Out, ModuleSignatureInfo &Info, Triple::EnvironmentType Stage, IOType IO, bool Native16, unsigned &Extent)
static Error validateSemanticIndex(const SemanticSignatureElement &E)
static Error checkElementNode(const MDNode *Node)
static void buildPSVElements(SmallVectorImpl< mcdxbc::PSVSignatureElement > &Dest, ArrayRef< SemanticSignatureElement > Elements, bool Legacy)
static StringRef getContainerSemanticName(const SemanticSignatureElement &E)
static Error signatureError(const Twine &Message)
static Error analyzeAccess(const IntrinsicInst &I, EntrySignature &Sig)
Module.h This file contains the declarations for the Module class.
Legalize the Machine IR a function s Machine IR
Definition Legalizer.cpp:85
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition PassSupport.h:42
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition PassSupport.h:44
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition PassSupport.h:39
This file contains some templates that are useful if you are working with the STL at all.
This file contains some functions that are useful when dealing with strings.
The Input class is used to parse a yaml document into in-memory structs and vectors.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
void setPreservesAll()
Set by analyses that do not transform their input at all.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
static ConstantAsMetadata * get(Constant *C)
Definition Metadata.h:548
void print(raw_ostream &OS, const Module *M) const override
print - Print out the internal state of the pass.
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
Tagged union holding either a T or a Error.
Definition Error.h:485
A wrapper class for inspecting calls to intrinsic functions.
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:71
Metadata node.
Definition Metadata.h:1081
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1579
Tracking metadata reference owned by Metadata.
Definition Metadata.h:902
static LLVM_ABI MDString * get(LLVMContext &Context, StringRef Str)
Definition Metadata.cpp:597
Tuple of metadata.
Definition Metadata.h:1496
Root of the metadata hierarchy.
Definition Metadata.h:64
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
A tuple of MDNodes.
Definition Metadata.h:1797
AnalysisType & getAnalysis() const
getAnalysis<AnalysisType>() - 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.
Definition Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void assign(size_type NumElts, ValueParamT Elt)
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.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Definition Type.cpp:299
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
Definition Type.cpp:297
Represents a version number in the form major[.minor[.subminor[.build]]].
bool empty() const
Determine whether this version information is empty (e.g., all version components are zero).
const EntrySignature * get(const Function *F) const
void print(raw_ostream &OS, const Module &M) const
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
bool runOnModule(Module &M) override
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
void print(raw_ostream &OS, const Module *M) const override
print - Print out the internal state of the pass.
Result run(Module &M, ModuleAnalysisManager &AM)
void addParam(uint32_t Stream, StringRef Name, uint32_t Index, dxbc::D3DSystemValue SystemValue, dxbc::SigComponentType CompType, uint32_t Register, uint8_t Mask, uint8_t ExclusiveMask, dxbc::SigMinPrecision MinPrecision)
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
ElementType
The element type of an SRV or UAV resource.
Definition DXILABI.h:68
LLVM_ABI SemanticInterpretation getInterpretationKind(dxbc::PSV::SemanticKind SemanticKind, Triple::EnvironmentType ShaderStage, IOType IOTy)
LLVM_ABI dxbc::PSV::SemanticKind getSemanticKind(StringRef SemanticName)
static constexpr unsigned MaxSignatureRows
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > dyn_extract_or_null(Y &&MD)
Extract a Value from Metadata, if any, allowing null.
Definition Metadata.h:720
This is an optimization pass for GlobalISel generic memory operations.
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2570
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition Error.cpp:94
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2224
bool isa_and_nonnull(const Y &Val)
Definition Casting.h:676
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition Error.h:1321
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1762
DWARFExpression::Operation Op
std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1788
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39
A special type used by analysis passes to provide an address that identifies that particular analysis...
Definition Analysis.h:29
SmallVector< hlsl::SemanticSignatureElement > Inputs
Triple::EnvironmentType Stage
void buildSignatures(mcdxbc::Signature &Input, mcdxbc::Signature &Output, VersionTuple ValidatorVersion) const
Append ISG1/OSG1 parameters to the supplied builders.
SmallVector< hlsl::SemanticSignatureElement > Outputs
void updatePSV(mcdxbc::PSVRuntimeInfo &PSV, VersionTuple ValidatorVersion) const
Append PSV signature elements and set vector extents, the dependency map, and stage-specific signatur...
MDTuple * getAsMetadata(LLVMContext &Ctx, VersionTuple ValidatorVersion) const
Return the DXIL input/output/patch-constant signature triple.
SmallVector< uint32_t > getDependencyState() const
Return the serialized dx.viewIdState words for this entry: input scalar count, output scalar count,...
SmallVector< uint32_t > InputOutputMap
void print(raw_ostream &OS) const
SmallVector< EntryProperties > EntryPropertyVec
static LLVM_ABI Expected< SemanticSignatureElement > fromMetadata(const MDNode *Node)
dxbc::PSV::v3::RuntimeInfo BaseData
SmallVector< PSVSignatureElement > InputElements
SmallVector< PSVSignatureElement > OutputElements
std::array< SmallVector< uint32_t >, 4 > InputOutputMap