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
16#include "llvm/IR/Constants.h"
17#include "llvm/IR/Metadata.h"
18#include "llvm/IR/Type.h"
19
20using namespace llvm;
21using namespace llvm::hlsl;
22
23namespace {
24
25// Inclusive upper bounds of the operand enums
26constexpr uint32_t MaxCompType =
28constexpr uint32_t MaxSemanticKind =
29 static_cast<uint32_t>(dxbc::PSV::SemanticKind::Invalid);
30constexpr uint32_t MaxInterpMode =
31 static_cast<uint32_t>(dxbc::PSV::InterpolationMode::Invalid);
32
33Error makeError(const Twine &Msg) {
35}
36
37Expected<uint64_t> extractInt(const MDNode *Node, unsigned OpId) {
38 auto *CI = mdconst::dyn_extract_or_null<ConstantInt>(Node->getOperand(OpId));
39 if (!CI)
40 return makeError("expected integer operand " + Twine(OpId));
41 return CI->getZExtValue();
42}
43} // namespace
44
47 // Operand positions within a signature element metadata node.
48 enum class OpIdx : unsigned {
49 SigId,
55 Rows,
56 Cols,
62 LastEntry = GSStream,
63 };
64 const unsigned NumElementOperands = to_underlying(OpIdx::LastEntry) + 1;
65
66 if (!Node)
67 return makeError("signature element node is null");
68 if (Node->getNumOperands() != NumElementOperands)
69 return makeError("signature element node has wrong number of operands");
70
72
73 Expected<uint64_t> SigId = extractInt(Node, to_underlying(OpIdx::SigId));
74 if (!SigId)
75 return SigId.takeError();
76 Elem.SigId = *SigId;
77
78 auto *Name =
79 dyn_cast<MDString>(Node->getOperand(to_underlying(OpIdx::SemanticName)));
80 if (!Name)
81 return makeError("expected semantic name string");
82 Elem.SemanticName = Name->getString();
83
85 extractInt(Node, to_underlying(OpIdx::CompType));
86 if (!CompType)
87 return CompType.takeError();
88 if (*CompType > MaxCompType)
89 return makeError("invalid component type");
90 Elem.CompType = static_cast<dxil::ElementType>(*CompType);
91
93 extractInt(Node, to_underlying(OpIdx::SemanticKind));
94 if (!SemanticKind)
95 return SemanticKind.takeError();
96 if (*SemanticKind > MaxSemanticKind)
97 return makeError("invalid semantic kind");
98 Elem.SemanticKind = static_cast<dxbc::PSV::SemanticKind>(*SemanticKind);
99
100 auto *Indices =
101 dyn_cast<MDNode>(Node->getOperand(to_underlying(OpIdx::SemanticIndices)));
102 if (!Indices)
103 return makeError("expected semantic indices node");
104 for (unsigned I = 0, E = Indices->getNumOperands(); I != E; ++I) {
105 Expected<uint64_t> Index = extractInt(Indices, I);
106 if (!Index)
107 return Index.takeError();
108 Elem.SemanticIndices.push_back(*Index);
109 }
110
112 extractInt(Node, to_underlying(OpIdx::InterpMode));
113 if (!InterpMode)
114 return InterpMode.takeError();
115 if (*InterpMode > MaxInterpMode)
116 return makeError("invalid interpolation mode");
117 Elem.InterpMode = static_cast<dxbc::PSV::InterpolationMode>(*InterpMode);
118
119 Expected<uint64_t> Rows = extractInt(Node, to_underlying(OpIdx::Rows));
120 if (!Rows)
121 return Rows.takeError();
122 Elem.Rows = *Rows;
123
124 Expected<uint64_t> Cols = extractInt(Node, to_underlying(OpIdx::Cols));
125 if (!Cols)
126 return Cols.takeError();
127 if (*Cols < 1 || *Cols > 4)
128 return makeError("number of components per row must be within 1-4");
129 Elem.Cols = *Cols;
130
132 extractInt(Node, to_underlying(OpIdx::StartRow));
133 if (!StartRow)
134 return StartRow.takeError();
135 Elem.StartRow = *StartRow;
136
138 extractInt(Node, to_underlying(OpIdx::StartCol));
139 if (!StartCol)
140 return StartCol.takeError();
141 if (*StartCol > 3 && *StartCol != UnallocatedCol)
142 return makeError("start column must be within 0-3 or unallocated");
143 Elem.StartCol = *StartCol;
144
145 // The row/col sentinels are always set together
146 if ((Elem.StartRow == UnallocatedRow) != (Elem.StartCol == UnallocatedCol))
147 return makeError("start row and column sentinels must be set together");
148
150 extractInt(Node, to_underlying(OpIdx::UsageMask));
151 if (!UsageMask)
152 return UsageMask.takeError();
153 if (*UsageMask > 0xF)
154 return makeError("usage mask must be a 4-bit value");
155 Elem.UsageMask = *UsageMask;
156
158 extractInt(Node, to_underlying(OpIdx::DynIndexMask));
159 if (!DynIndexMask)
160 return DynIndexMask.takeError();
161 if (*DynIndexMask > 0xF)
162 return makeError("dynamic index mask must be a 4-bit value");
164
166 extractInt(Node, to_underlying(OpIdx::GSStream));
167 if (!GSStream)
168 return GSStream.takeError();
169 if (*GSStream > 3)
170 return makeError("geometry shader stream index must be within 0-3");
171 Elem.GSStream = *GSStream;
172
173 if (Elem.SemanticIndices.size() != Elem.Rows)
174 return makeError(
175 "number of semantic indices must equal the number of rows");
176
177 return Elem;
178}
179
181 Type *I32Ty = Type::getInt32Ty(Ctx);
182 Type *I8Ty = Type::getInt8Ty(Ctx);
183 auto GetI32 = [&](uint32_t Val) -> Metadata * {
184 return ConstantAsMetadata::get(ConstantInt::get(I32Ty, Val));
185 };
186 auto GetI8 = [&](uint8_t Val) -> Metadata * {
187 return ConstantAsMetadata::get(ConstantInt::get(I8Ty, Val));
188 };
189
191 for (uint32_t Index : SemanticIndices)
192 IndexOps.push_back(GetI32(Index));
193
194 return MDNode::get(Ctx,
195 {GetI32(SigId), MDString::get(Ctx, SemanticName),
196 GetI32(static_cast<uint32_t>(CompType)),
197 GetI32(static_cast<uint32_t>(SemanticKind)),
198 MDNode::get(Ctx, IndexOps),
199 GetI32(static_cast<uint32_t>(InterpMode)), GetI32(Rows),
200 GetI8(Cols), GetI32(StartRow), GetI8(StartCol),
201 GetI8(UsageMask), GetI8(DynIndexMask), GetI32(GSStream)});
202}
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.
MachineInstr unsigned OpIdx
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.
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
ElementType
The element type of an SRV or UAV resource.
Definition DXILABI.h:68
static constexpr uint32_t UnallocatedRow
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