@@ -32,6 +32,20 @@ using namespace llvm::dxil;
32
32
33
33
namespace {
34
34
35
+ struct DXILArgSelect {
36
+ enum class Type {
37
+ Index,
38
+ I32,
39
+ I8,
40
+ };
41
+ Type Type = Type::Index;
42
+ int Value = -1 ;
43
+ };
44
+ struct DXILIntrinsicSelect {
45
+ StringRef Intrinsic;
46
+ SmallVector<DXILArgSelect, 4 > Args;
47
+ };
48
+
35
49
struct DXILOperationDesc {
36
50
std::string OpName; // name of DXIL operation
37
51
int OpCode; // ID of DXIL operation
@@ -42,8 +56,7 @@ struct DXILOperationDesc {
42
56
SmallVector<const Record *> OverloadRecs;
43
57
SmallVector<const Record *> StageRecs;
44
58
SmallVector<const Record *> AttrRecs;
45
- StringRef Intrinsic; // The llvm intrinsic map to OpName. Default is "" which
46
- // means no map exists
59
+ SmallVector<DXILIntrinsicSelect> IntrinsicSelects;
47
60
SmallVector<StringRef, 4 >
48
61
ShaderStages; // shader stages to which this applies, empty for all.
49
62
int OverloadParamIndex; // Index of parameter with overload type.
@@ -71,6 +84,21 @@ static void AscendingSortByVersion(std::vector<const Record *> &Recs) {
71
84
});
72
85
}
73
86
87
+ // / Take a `int_{intrinsic_name}` and return just the intrinsic_name part if
88
+ // / available. Otherwise return the empty string.
89
+ static StringRef GetIntrinsicName (const RecordVal *RV) {
90
+ if (RV && RV->getValue ()) {
91
+ if (const DefInit *DI = dyn_cast<DefInit>(RV->getValue ())) {
92
+ auto *IntrinsicDef = DI->getDef ();
93
+ auto DefName = IntrinsicDef->getName ();
94
+ assert (DefName.starts_with (" int_" ) && " invalid intrinsic name" );
95
+ // Remove the int_ from intrinsic name.
96
+ return DefName.substr (4 );
97
+ }
98
+ }
99
+ return " " ;
100
+ }
101
+
74
102
// / Construct an object using the DXIL Operation records specified
75
103
// / in DXIL.td. This serves as the single source of reference of
76
104
// / the information extracted from the specified Record R, for
@@ -157,14 +185,63 @@ DXILOperationDesc::DXILOperationDesc(const Record *R) {
157
185
OpName);
158
186
}
159
187
160
- const RecordVal *RV = R->getValue (" LLVMIntrinsic" );
161
- if (RV && RV->getValue ()) {
162
- if (const DefInit *DI = dyn_cast<DefInit>(RV->getValue ())) {
163
- auto *IntrinsicDef = DI->getDef ();
164
- auto DefName = IntrinsicDef->getName ();
165
- assert (DefName.starts_with (" int_" ) && " invalid intrinsic name" );
166
- // Remove the int_ from intrinsic name.
167
- Intrinsic = DefName.substr (4 );
188
+ {
189
+ DXILIntrinsicSelect IntrSelect;
190
+ IntrSelect.Intrinsic = GetIntrinsicName (R->getValue (" LLVMIntrinsic" ));
191
+ if (IntrSelect.Intrinsic .size ())
192
+ IntrinsicSelects.emplace_back (std::move (IntrSelect));
193
+ }
194
+
195
+ auto IntrinsicSelectRecords = R->getValueAsListOfDefs (" intrinsic_selects" );
196
+ if (IntrinsicSelectRecords.size ()) {
197
+ if (IntrinsicSelects.size ()) {
198
+ PrintFatalError (
199
+ R, Twine (" LLVMIntrinsic and intrinsic_selects cannot be both "
200
+ " defined for DXIL operation - " ) +
201
+ OpName);
202
+ } else {
203
+ for (const Record *R : IntrinsicSelectRecords) {
204
+ DXILIntrinsicSelect IntrSelect;
205
+ IntrSelect.Intrinsic = GetIntrinsicName (R->getValue (" intrinsic" ));
206
+ auto Args = R->getValueAsListOfDefs (" args" );
207
+ for (const Record *Arg : Args) {
208
+ bool IsI8 = Arg->getValueAsBit (" is_i8" );
209
+ bool IsI32 = Arg->getValueAsBit (" is_i32" );
210
+ int Index = Arg->getValueAsInt (" index" );
211
+ const Record *ValueRec = Arg->getValueAsOptionalDef (" value" );
212
+
213
+ DXILArgSelect ArgSelect;
214
+ if (IsI8) {
215
+ if (!ValueRec) {
216
+ PrintFatalError (R, Twine (" 'value' must be defined for i8 "
217
+ " ArgSelect for DXIL operation - " ) +
218
+ OpName);
219
+ }
220
+ ArgSelect.Type = DXILArgSelect::Type::I8;
221
+ ArgSelect.Value = ValueRec->getValueAsInt (" value" );
222
+ } else if (IsI32) {
223
+ if (!ValueRec) {
224
+ PrintFatalError (R, Twine (" 'value' must be defined for i32 "
225
+ " ArgSelect for DXIL operation - " ) +
226
+ OpName);
227
+ }
228
+ ArgSelect.Type = DXILArgSelect::Type::I32;
229
+ ArgSelect.Value = ValueRec->getValueAsInt (" value" );
230
+ } else {
231
+ if (Index < 0 ) {
232
+ PrintFatalError (
233
+ R, Twine (" Index in ArgSelect<index> must be equal to or "
234
+ " greater than 0 for DXIL operation - " ) +
235
+ OpName);
236
+ }
237
+ ArgSelect.Type = DXILArgSelect::Type::Index;
238
+ ArgSelect.Value = Index;
239
+ }
240
+
241
+ IntrSelect.Args .emplace_back (std::move (ArgSelect));
242
+ }
243
+ IntrinsicSelects.emplace_back (std::move (IntrSelect));
244
+ }
168
245
}
169
246
}
170
247
}
@@ -377,10 +454,29 @@ static void emitDXILIntrinsicMap(ArrayRef<DXILOperationDesc> Ops,
377
454
OS << " #ifdef DXIL_OP_INTRINSIC\n " ;
378
455
OS << " \n " ;
379
456
for (const auto &Op : Ops) {
380
- if (Op.Intrinsic .empty ())
457
+ if (Op.IntrinsicSelects .empty ()) {
381
458
continue ;
382
- OS << " DXIL_OP_INTRINSIC(dxil::OpCode::" << Op.OpName
383
- << " , Intrinsic::" << Op.Intrinsic << " )\n " ;
459
+ }
460
+ for (const DXILIntrinsicSelect &MappedIntr : Op.IntrinsicSelects ) {
461
+ OS << " DXIL_OP_INTRINSIC(dxil::OpCode::" << Op.OpName
462
+ << " , Intrinsic::" << MappedIntr.Intrinsic ;
463
+ for (const DXILArgSelect &ArgSelect : MappedIntr.Args ) {
464
+ OS << " , (ArgSelect { " ;
465
+ switch (ArgSelect.Type ) {
466
+ case DXILArgSelect::Type::Index:
467
+ OS << " ArgSelect::Type::Index, " ;
468
+ break ;
469
+ case DXILArgSelect::Type::I8:
470
+ OS << " ArgSelect::Type::I8, " ;
471
+ break ;
472
+ case DXILArgSelect::Type::I32:
473
+ OS << " ArgSelect::Type::I32, " ;
474
+ break ;
475
+ }
476
+ OS << ArgSelect.Value << " })" ;
477
+ }
478
+ OS << " )\n " ;
479
+ }
384
480
}
385
481
OS << " \n " ;
386
482
OS << " #undef DXIL_OP_INTRINSIC\n " ;
0 commit comments