@@ -32,6 +32,20 @@ using namespace llvm::dxil;
3232
3333namespace {
3434
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+
3549struct DXILOperationDesc {
3650 std::string OpName; // name of DXIL operation
3751 int OpCode; // ID of DXIL operation
@@ -42,8 +56,7 @@ struct DXILOperationDesc {
4256 SmallVector<const Record *> OverloadRecs;
4357 SmallVector<const Record *> StageRecs;
4458 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;
4760 SmallVector<StringRef, 4 >
4861 ShaderStages; // shader stages to which this applies, empty for all.
4962 int OverloadParamIndex; // Index of parameter with overload type.
@@ -71,6 +84,21 @@ static void AscendingSortByVersion(std::vector<const Record *> &Recs) {
7184 });
7285}
7386
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+
74102// / Construct an object using the DXIL Operation records specified
75103// / in DXIL.td. This serves as the single source of reference of
76104// / the information extracted from the specified Record R, for
@@ -157,14 +185,63 @@ DXILOperationDesc::DXILOperationDesc(const Record *R) {
157185 OpName);
158186 }
159187
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+ }
168245 }
169246 }
170247}
@@ -377,10 +454,29 @@ static void emitDXILIntrinsicMap(ArrayRef<DXILOperationDesc> Ops,
377454 OS << " #ifdef DXIL_OP_INTRINSIC\n " ;
378455 OS << " \n " ;
379456 for (const auto &Op : Ops) {
380- if (Op.Intrinsic .empty ())
457+ if (Op.IntrinsicSelects .empty ()) {
381458 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+ }
384480 }
385481 OS << " \n " ;
386482 OS << " #undef DXIL_OP_INTRINSIC\n " ;
0 commit comments