18#include "llvm/IR/IntrinsicsDirectX.h"
36 return I.getIntrinsicID() == Intrinsic::dx_load_input ||
37 I.getIntrinsicID() == Intrinsic::dx_store_output;
42 if (!
Node ||
Node->getNumOperands() != 13)
44 for (
unsigned I = 0;
I != 13; ++
I) {
48 unsigned Width = (
I == 7 || (
I >= 9 &&
I <= 11)) ? 8 : 32;
49 if (!CI || CI->getBitWidth() != Width)
58 for (
const MDOperand &Index : Indices->operands()) {
60 if (!CI || CI->getBitWidth() != 32)
73 switch (
E.SemanticKind) {
74 case dxbc::PSV::SemanticKind::Position:
75 if (
E.Rows != 1 ||
E.Cols != 4 ||
78 "SV_Position requires one row of four floating-point components");
80 case dxbc::PSV::SemanticKind::VertexID:
81 if (
E.Rows != 1 ||
E.Cols != 1 ||
85 "SV_VertexID requires a scalar 16- or 32-bit integer");
87 case dxbc::PSV::SemanticKind::InstanceID:
88 if (
E.Rows != 1 ||
E.Cols != 1 ||
91 "SV_InstanceID requires a scalar 16- or 32-bit unsigned integer");
100 switch (
E.SemanticKind) {
101 case dxbc::PSV::SemanticKind::Target:
102 if (
E.Rows != 1 ||
E.SemanticIndices.front() >= 8)
104 "pixel targets require one row and an index within 0-7");
106 case dxbc::PSV::SemanticKind::VertexID:
107 if (
E.SemanticIndices.front() != 0)
120 bool Native16,
unsigned &Extent) {
125 return signatureError(
"expected a signature element list or null");
126 if (List->getNumOperands() > 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 = {};
139 return Parsed.takeError();
141 if (
E.SigId !=
Out.size())
142 return signatureError(
"signature IDs must be dense and in list order");
144 return signatureError(
"nonempty signatures are currently supported only "
145 "for vertex and pixel entries");
148 if (
E.SemanticName.empty() ||
E.SemanticName.contains(
'\0'))
154 return signatureError(
"nonzero stream requires a geometry output");
158 return signatureError(
"invalid or unsupported semantic for this stage "
159 "and signature category");
161 return signatureError(
"semantic accessed by a dedicated intrinsic must "
162 "not appear in an input/output signature");
164 ? dxbc::PSV::SemanticKind::Arbitrary
166 if (
E.SemanticKind != ExpectedKind)
167 return signatureError(
"semantic name and kind disagree at this signature "
169 if (!
E.isAllocated())
171 E.SemanticName +
"') has no allocated location");
175 "allocated signature element exceeds register bounds");
176 if (
E.InterpMode == dxbc::PSV::InterpolationMode::Invalid)
180 if (!Semantics.emplace(
E.SemanticName.upper(), Index).second)
188 (
E.StartRow != Extent ||
E.StartCol != 0))
189 return signatureError(
"vertex inputs require stacked locations in "
190 "signature order (element " +
193 (
E.StartRow !=
E.SemanticIndices.front() ||
E.StartCol != 0))
194 return signatureError(
"pixel target location must match its semantic "
195 "index at column 0");
198 E.InterpMode != dxbc::PSV::InterpolationMode::Constant)
200 "integer pixel inputs require constant interpolation");
208 for (
unsigned Row =
E.StartRow; Row !=
E.StartRow +
E.Rows; ++Row) {
209 if (AllocatedColumns[Row] & Mask)
212 if (AllocatedColumns[Row] && RowModes[Row] !=
E.InterpMode)
213 return signatureError(
"signature elements have different interpolation "
216 if (AllocatedColumns[Row] && RowNative16[Row] != IsNative16)
217 return signatureError(
"signature elements have different component "
220 AllocatedColumns[Row] |= Mask;
221 RowModes[Row] =
E.InterpMode;
222 RowNative16[Row] = IsNative16;
224 Extent = std::max(Extent,
E.StartRow +
E.Rows);
225 E.SemanticName = Info.Names.insert(
E.SemanticName).first->getKey();
230 Out.push_back(std::move(
E));
236 bool Input =
I.getIntrinsicID() == Intrinsic::dx_load_input;
243 " signature: signature access requires a constant "
245 if (ID->getZExtValue() >= Elements.size())
247 " signature: signature access has an invalid element "
249 Twine(ID->getZExtValue()));
250 auto &
E = Elements[ID->getZExtValue()];
251 auto AccessError = [&](
const Twine &Message) {
253 " ('" +
E.SemanticName +
"'): " + Message);
255 Type *Ty =
Input ?
I.getType() :
I.getArgOperand(3)->getType();
258 Width = VT->getNumElements();
259 Ty = VT->getElementType();
261 if (!Col || Col->getZExtValue() >=
E.Cols ||
262 Width >
E.Cols - Col->getZExtValue())
263 return AccessError(
"signature access has an invalid component index");
265 if (Row && Row->getZExtValue() >=
E.Rows)
266 return AccessError(
"signature access has an invalid row index");
267 if (!Row &&
E.Rows == 1)
269 "dynamic indexing requires a multi-row signature element");
270 bool CorrectType =
false;
271 switch (
E.CompType) {
273 CorrectType = Ty->isHalfTy();
276 CorrectType = Ty->isFloatTy();
280 CorrectType = Ty->isIntegerTy(16);
284 CorrectType = Ty->isIntegerTy(32);
288 CorrectType = Ty->isIntegerTy(32);
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;
298 E.DynIndexMask |= Mask;
314 for (
unsigned IC = 0; IC != 4; ++IC) {
315 if (!(
Input.UsageMask & (1U << IC)))
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)))
323 unsigned Bit = (Output.StartRow + OR) * 4 + OC;
334 if (
Record->getNumOperands() != 3)
336 "expected an entry/input/output signature triple");
339 if (!
F ||
F->getParent() != &M ||
F->isDeclaration())
341 "signature entry must be a defined function in the module");
346 return signatureError(
"signature function is not a shader entry");
347 if (Info.Entries.contains(
F))
351 Sig.
Stage = EP->ShaderStage;
353 M.getModuleFlag(
"dx.nativelowprec")))
357 "native 16-bit signatures require shader model 6.2");
360 " signature: " +
toString(std::move(Err)));
365 return AddContext(std::move(Err),
"input");
369 return AddContext(std::move(Err),
"output");
377 Info.Entries.try_emplace(
F, std::move(Sig));
383 if (!Info.Entries.contains(&
F))
388 "' has no entry signature metadata");
389 return std::move(Info);
396 M.getContext().emitError(
"Invalid semantic signature: " +
400 return std::move(*Result);
406 if (Elements.empty())
415 for (
const auto &
E : Elements) {
429 I8(
static_cast<uint8_t>(
E.CompType)),
430 I8(
static_cast<uint8_t>(
E.SemanticKind)),
432 I32(
E.Rows), I8(
E.Cols),
I32(
E.StartRow), I8(
E.StartCol),
441 return Legacy ? dxbc::SigComponentType::Unknown
442 : dxbc::SigComponentType::UInt32;
444 return dxbc::SigComponentType::SInt16;
446 return dxbc::SigComponentType::UInt16;
448 return dxbc::SigComponentType::SInt32;
450 return dxbc::SigComponentType::UInt32;
452 return dxbc::SigComponentType::Float16;
454 return dxbc::SigComponentType::Float32;
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;
478 return dxbc::D3DSystemValue::Target;
490 switch (
E.SemanticKind) {
491 case Kind::Arbitrary:
492 return E.SemanticName;
494 return "SV_VertexID";
495 case Kind::InstanceID:
496 return "SV_InstanceID";
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";
515 for (
const auto &
E : Elements) {
518 Input ?
E.getAlwaysReadsMask() :
E.getNeverWritesMask();
520 ExclusiveMask =
Input ? 0 :
static_cast<uint8_t>(~Mask);
521 for (
auto [Row, Index] :
enumerate(
E.SemanticIndices))
525 ExclusiveMask,
E.getMinPrecision(!Native16));
532 for (
const auto &
E : Elements) {
535 Dest.
push_back({
E.SemanticKind == dxbc::PSV::SemanticKind::Arbitrary
538 E.SemanticIndices,
static_cast<uint8_t>(
E.StartRow),
E.Cols,
539 E.StartCol,
E.isAllocated(),
E.SemanticKind,
541 E.DynIndexMask,
static_cast<uint8_t>(
E.GSStream)});
577 return E.SemanticKind == dxbc::PSV::SemanticKind::Position;
582 return E.InterpMode == dxbc::PSV::InterpolationMode::LinearSample ||
584 dxbc::PSV::InterpolationMode::LinearNoperspectiveSample;
597 OS <<
" " << Name <<
": " << Elements.size() <<
" elements, " << Vectors
599 for (
const auto &E : Elements)
600 OS <<
" " << E.SigId <<
": " << E.SemanticName <<
" rows=" << E.Rows
601 <<
" cols=" <<
unsigned(E.Cols) <<
" at " << E.StartRow <<
":"
603 <<
" dynamic=" <<
unsigned(E.DynIndexMask) <<
'\n';
611 if (
const auto *Sig =
get(&
F)) {
612 OS <<
"Semantic signatures for '" <<
F.getName() <<
"':\n";
647 "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
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
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),...
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
A wrapper class for inspecting calls to intrinsic functions.
This is an important class for using LLVM in a threaded context.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Tracking metadata reference owned by Metadata.
static LLVM_ABI MDString * get(LLVMContext &Context, StringRef Str)
A Module instance is used to store all the information related to an LLVM module.
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.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
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.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
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.
#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.
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.
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,...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
bool isa_and_nonnull(const Y &Val)
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
auto dyn_cast_or_null(const Y &Val)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
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.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
A special type used by analysis passes to provide an address that identifies that particular analysis...
PipelinePSVInfo StageInfo
uint8_t SigOutputVectors[4]
uint8_t OutputPositionPresent
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
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