LLVM 24.0.0git
SemanticSignatures.cpp
Go to the documentation of this file.
1//===- SemanticSignatures.cpp - HLSL Semantic Signature helpers -----------===//
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///
9/// \file This file implements a library for working with HLSL shader input and
10/// output semantic signatures and their DirectX metadata representation.
11///
12//===----------------------------------------------------------------------===//
13
15#include "llvm/ADT/Enum.h"
17#include "llvm/IR/Constants.h"
18#include "llvm/IR/Metadata.h"
19#include "llvm/IR/Type.h"
20
21using namespace llvm;
22using namespace llvm::hlsl;
23
24namespace {
25
26// Inclusive upper bounds of the operand enums
27constexpr uint32_t MaxCompType =
29constexpr uint32_t MaxSemanticKind =
30 static_cast<uint32_t>(dxbc::PSV::SemanticKind::Invalid);
31constexpr uint32_t MaxInterpMode =
32 static_cast<uint32_t>(dxbc::PSV::InterpolationMode::Invalid);
33
34Error makeError(const Twine &Msg) {
36}
37
38Expected<uint64_t> extractInt(const MDNode *Node, unsigned OpId) {
39 auto *CI = mdconst::dyn_extract_or_null<ConstantInt>(Node->getOperand(OpId));
40 if (!CI)
41 return makeError("expected integer operand " + Twine(OpId));
42 return CI->getZExtValue();
43}
44} // namespace
45
47 if (!SemanticName.consume_front_insensitive("SV_"))
48 return dxbc::PSV::SemanticKind::Arbitrary;
49
50 for (const auto &Kind : dxbc::PSV::getSemanticKinds())
51 if (SemanticName.equals_insensitive(Kind.name()))
52 return Kind.value();
53
54 return dxbc::PSV::SemanticKind::Invalid;
55}
56
59 // Operand positions within a signature element metadata node.
60 enum class OpIdx : unsigned {
61 SigId,
67 Rows,
68 Cols,
74 LastEntry = GSStream,
75 };
76 const unsigned NumElementOperands = to_underlying(OpIdx::LastEntry) + 1;
77
78 if (!Node)
79 return makeError("signature element node is null");
80 if (Node->getNumOperands() != NumElementOperands)
81 return makeError("signature element node has wrong number of operands");
82
84
85 Expected<uint64_t> SigId = extractInt(Node, to_underlying(OpIdx::SigId));
86 if (!SigId)
87 return SigId.takeError();
88 Elem.SigId = *SigId;
89
90 auto *Name =
91 dyn_cast<MDString>(Node->getOperand(to_underlying(OpIdx::SemanticName)));
92 if (!Name)
93 return makeError("expected semantic name string");
94 Elem.SemanticName = Name->getString();
95
97 extractInt(Node, to_underlying(OpIdx::CompType));
98 if (!CompType)
99 return CompType.takeError();
100 if (*CompType > MaxCompType)
101 return makeError("invalid component type");
102 Elem.CompType = static_cast<dxil::ElementType>(*CompType);
103
105 extractInt(Node, to_underlying(OpIdx::SemanticKind));
106 if (!SemanticKind)
107 return SemanticKind.takeError();
108 if (*SemanticKind > MaxSemanticKind)
109 return makeError("invalid semantic kind");
110 Elem.SemanticKind = static_cast<dxbc::PSV::SemanticKind>(*SemanticKind);
111
112 auto *Indices =
113 dyn_cast<MDNode>(Node->getOperand(to_underlying(OpIdx::SemanticIndices)));
114 if (!Indices)
115 return makeError("expected semantic indices node");
116 for (unsigned I = 0, E = Indices->getNumOperands(); I != E; ++I) {
117 Expected<uint64_t> Index = extractInt(Indices, I);
118 if (!Index)
119 return Index.takeError();
120 Elem.SemanticIndices.push_back(*Index);
121 }
122
124 extractInt(Node, to_underlying(OpIdx::InterpMode));
125 if (!InterpMode)
126 return InterpMode.takeError();
127 if (*InterpMode > MaxInterpMode)
128 return makeError("invalid interpolation mode");
129 Elem.InterpMode = static_cast<dxbc::PSV::InterpolationMode>(*InterpMode);
130
131 Expected<uint64_t> Rows = extractInt(Node, to_underlying(OpIdx::Rows));
132 if (!Rows)
133 return Rows.takeError();
134 Elem.Rows = *Rows;
135
136 Expected<uint64_t> Cols = extractInt(Node, to_underlying(OpIdx::Cols));
137 if (!Cols)
138 return Cols.takeError();
139 if (*Cols < 1 || *Cols > 4)
140 return makeError("number of components per row must be within 1-4");
141 Elem.Cols = *Cols;
142
144 extractInt(Node, to_underlying(OpIdx::StartRow));
145 if (!StartRow)
146 return StartRow.takeError();
147 Elem.StartRow = *StartRow;
148
150 extractInt(Node, to_underlying(OpIdx::StartCol));
151 if (!StartCol)
152 return StartCol.takeError();
153 if (*StartCol > 3 && *StartCol != UnallocatedCol)
154 return makeError("start column must be within 0-3 or unallocated");
155 Elem.StartCol = *StartCol;
156
157 // The row/col sentinels are always set together
158 if ((Elem.StartRow == UnallocatedRow) != (Elem.StartCol == UnallocatedCol))
159 return makeError("start row and column sentinels must be set together");
160
162 extractInt(Node, to_underlying(OpIdx::UsageMask));
163 if (!UsageMask)
164 return UsageMask.takeError();
165 if (*UsageMask > 0xF)
166 return makeError("usage mask must be a 4-bit value");
167 Elem.UsageMask = *UsageMask;
168
170 extractInt(Node, to_underlying(OpIdx::DynIndexMask));
171 if (!DynIndexMask)
172 return DynIndexMask.takeError();
173 if (*DynIndexMask > 0xF)
174 return makeError("dynamic index mask must be a 4-bit value");
176
178 extractInt(Node, to_underlying(OpIdx::GSStream));
179 if (!GSStream)
180 return GSStream.takeError();
181 if (*GSStream > 3)
182 return makeError("geometry shader stream index must be within 0-3");
183 Elem.GSStream = *GSStream;
184
185 if (Elem.SemanticIndices.size() != Elem.Rows)
186 return makeError(
187 "number of semantic indices must equal the number of rows");
188
189 return Elem;
190}
191
193 Type *I32Ty = Type::getInt32Ty(Ctx);
194 Type *I8Ty = Type::getInt8Ty(Ctx);
195 auto GetI32 = [&](uint32_t Val) -> Metadata * {
196 return ConstantAsMetadata::get(ConstantInt::get(I32Ty, Val));
197 };
198 auto GetI8 = [&](uint8_t Val) -> Metadata * {
199 return ConstantAsMetadata::get(ConstantInt::get(I8Ty, Val));
200 };
201
203 for (uint32_t Index : SemanticIndices)
204 IndexOps.push_back(GetI32(Index));
205
206 return MDNode::get(Ctx,
207 {GetI32(SigId), MDString::get(Ctx, SemanticName),
208 GetI32(static_cast<uint32_t>(CompType)),
209 GetI32(static_cast<uint32_t>(SemanticKind)),
210 MDNode::get(Ctx, IndexOps),
211 GetI32(static_cast<uint32_t>(InterpMode)), GetI32(Rows),
212 GetI8(Cols), GetI32(StartRow), GetI8(StartCol),
213 GetI8(UsageMask), GetI8(DynIndexMask), GetI32(GSStream)});
214}
This file contains the declarations for the subclasses of Constant, which represent the different fla...
#define I(x, y, z)
Definition MD5.cpp:57
This file contains the declarations for metadata subclasses.
const char * Msg
This file contains library features backported from future STL versions.
static ConstantAsMetadata * get(Constant *C)
Definition Metadata.h:537
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
Tagged union holding either a T or a Error.
Definition Error.h:485
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
Metadata node.
Definition Metadata.h:1069
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1567
static LLVM_ABI MDString * get(LLVMContext &Context, StringRef Str)
Definition Metadata.cpp:615
Root of the metadata hierarchy.
Definition Metadata.h:64
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
bool equals_insensitive(StringRef RHS) const
Check for string equality, ignoring case.
Definition StringRef.h:170
bool consume_front_insensitive(StringRef Prefix)
Returns true if this StringRef has the given prefix, ignoring case, and removes that prefix.
Definition StringRef.h:681
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:309
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
Definition Type.cpp:307
LLVM_ABI EnumStrings< SemanticKind, 1 > getSemanticKinds()
ElementType
The element type of an SRV or UAV resource.
Definition DXILABI.h:68
static constexpr uint32_t UnallocatedRow
LLVM_ABI dxbc::PSV::SemanticKind getSemanticKind(StringRef SemanticName)
static constexpr uint8_t UnallocatedCol
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:709
This is an optimization pass for GlobalISel generic memory operations.
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
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition Error.h:1321
constexpr std::underlying_type_t< Enum > to_underlying(Enum E)
Returns underlying integer value of an enum.
static LLVM_ABI Expected< SemanticSignatureElement > fromMetadata(const MDNode *Node)
dxbc::PSV::InterpolationMode InterpMode
LLVM_ABI MDNode * toMetadata(LLVMContext &Ctx) const