22
22
#include " llvm/Support/DXILABI.h"
23
23
#include " llvm/TableGen/Record.h"
24
24
#include " llvm/TableGen/TableGenBackend.h"
25
+ #include < string>
25
26
26
27
using namespace llvm ;
27
28
using namespace llvm ::dxil;
@@ -38,8 +39,8 @@ struct DXILOperationDesc {
38
39
int OpCode; // ID of DXIL operation
39
40
StringRef OpClass; // name of the opcode class
40
41
StringRef Doc; // the documentation description of this instruction
41
- SmallVector<MVT::SimpleValueType > OpTypes; // Vector of operand types -
42
- // return type is at index 0
42
+ SmallVector<Record * > OpTypes; // Vector of operand type records -
43
+ // return type is at index 0
43
44
SmallVector<std::string>
44
45
OpAttributes; // operation attribute represented as strings
45
46
StringRef Intrinsic; // The llvm intrinsic map to OpName. Default is "" which
@@ -57,20 +58,21 @@ struct DXILOperationDesc {
57
58
DXILShaderModel ShaderModel; // minimum shader model required
58
59
DXILShaderModel ShaderModelTranslated; // minimum shader model required with
59
60
// translation by linker
60
- int OverloadParamIndex; // parameter index which control the overload.
61
- // When < 0, should be only 1 overload type.
61
+ int OverloadParamIndex; // Index of parameter with overload type .
62
+ // -1 : no overload types
62
63
SmallVector<StringRef, 4 > counters; // counters for this inst.
63
64
DXILOperationDesc (const Record *);
64
65
};
65
66
} // end anonymous namespace
66
67
67
- // / Convert DXIL type name string to dxil::ParameterKind
68
+ // / Return dxil::ParameterKind corresponding to input LLVMType record
68
69
// /
69
- // / \param VT Simple Value Type
70
+ // / \param R TableGen def record of class LLVMType
70
71
// / \return ParameterKind As defined in llvm/Support/DXILABI.h
71
72
72
- static ParameterKind getParameterKind (MVT::SimpleValueType VT) {
73
- switch (VT) {
73
+ static ParameterKind getParameterKind (const Record *R) {
74
+ auto VTRec = R->getValueAsDef (" VT" );
75
+ switch (getValueType (VTRec)) {
74
76
case MVT::isVoid:
75
77
return ParameterKind::VOID;
76
78
case MVT::f16 :
@@ -90,6 +92,18 @@ static ParameterKind getParameterKind(MVT::SimpleValueType VT) {
90
92
case MVT::fAny :
91
93
case MVT::iAny:
92
94
return ParameterKind::OVERLOAD;
95
+ case MVT::Other:
96
+ // Handle DXIL-specific overload types
97
+ {
98
+ auto RetKind = StringSwitch<ParameterKind>(R->getNameInitAsString ())
99
+ .Cases (" llvm_i16ori32_ty" , " llvm_halforfloat_ty" ,
100
+ ParameterKind::OVERLOAD)
101
+ .Default (ParameterKind::INVALID);
102
+ if (RetKind != ParameterKind::INVALID) {
103
+ return RetKind;
104
+ }
105
+ }
106
+ LLVM_FALLTHROUGH;
93
107
default :
94
108
llvm_unreachable (" Support for specified DXIL Type not yet implemented" );
95
109
}
@@ -106,45 +120,80 @@ DXILOperationDesc::DXILOperationDesc(const Record *R) {
106
120
107
121
Doc = R->getValueAsString (" Doc" );
108
122
123
+ auto TypeRecs = R->getValueAsListOfDefs (" OpTypes" );
124
+ unsigned TypeRecsSize = TypeRecs.size ();
125
+ // Populate OpTypes with return type and parameter types
126
+
127
+ // Parameter indices of overloaded parameters.
128
+ // This vector contains overload parameters in the order order used to
129
+ // resolve an LLVMMatchType in accordance with convention outlined in
130
+ // the comment before the definition of class LLVMMatchType in
131
+ // llvm/IR/Intrinsics.td
132
+ SmallVector<int > OverloadParamIndices;
133
+ for (unsigned i = 0 ; i < TypeRecsSize; i++) {
134
+ auto TR = TypeRecs[i];
135
+ // Track operation parameter indices of any overload types
136
+ auto isAny = TR->getValueAsInt (" isAny" );
137
+ if (isAny == 1 ) {
138
+ // TODO: At present it is expected that all overload types in a DXIL Op
139
+ // are of the same type. Hence, OverloadParamIndices will have only one
140
+ // element. This implies we do not need a vector. However, until more
141
+ // (all?) DXIL Ops are added in DXIL.td, a vector is being used to flag
142
+ // cases this assumption would not hold.
143
+ if (!OverloadParamIndices.empty ()) {
144
+ bool knownType = true ;
145
+ // Ensure that the same overload type registered earlier is being used
146
+ for (auto Idx : OverloadParamIndices) {
147
+ if (TR != TypeRecs[Idx]) {
148
+ knownType = false ;
149
+ break ;
150
+ }
151
+ }
152
+ if (!knownType) {
153
+ report_fatal_error (" Specification of multiple differing overload "
154
+ " parameter types not yet supported" ,
155
+ false );
156
+ }
157
+ } else {
158
+ OverloadParamIndices.push_back (i);
159
+ }
160
+ }
161
+ // Populate OpTypes array according to the type specification
162
+ if (TR->isAnonymous ()) {
163
+ // Check prior overload types exist
164
+ assert (!OverloadParamIndices.empty () &&
165
+ " No prior overloaded parameter found to match." );
166
+ // Get the parameter index of anonymous type, TR, references
167
+ auto OLParamIndex = TR->getValueAsInt (" Number" );
168
+ // Resolve and insert the type to that at OLParamIndex
169
+ OpTypes.emplace_back (TypeRecs[OLParamIndex]);
170
+ } else {
171
+ // A non-anonymous type. Just record it in OpTypes
172
+ OpTypes.emplace_back (TR);
173
+ }
174
+ }
175
+
176
+ // Set the index of the overload parameter, if any.
177
+ OverloadParamIndex = -1 ; // default; indicating none
178
+ if (!OverloadParamIndices.empty ()) {
179
+ if (OverloadParamIndices.size () > 1 )
180
+ report_fatal_error (" Multiple overload type specification not supported" ,
181
+ false );
182
+ OverloadParamIndex = OverloadParamIndices[0 ];
183
+ }
184
+ // Get the operation class
185
+ OpClass = R->getValueAsDef (" OpClass" )->getName ();
186
+
109
187
if (R->getValue (" LLVMIntrinsic" )) {
110
188
auto *IntrinsicDef = R->getValueAsDef (" LLVMIntrinsic" );
111
189
auto DefName = IntrinsicDef->getName ();
112
190
assert (DefName.starts_with (" int_" ) && " invalid intrinsic name" );
113
191
// Remove the int_ from intrinsic name.
114
192
Intrinsic = DefName.substr (4 );
115
- // TODO: It is expected that return type and parameter types of
116
- // DXIL Operation are the same as that of the intrinsic. Deviations
117
- // are expected to be encoded in TableGen record specification and
118
- // handled accordingly here. Support to be added later, as needed.
119
- // Get parameter type list of the intrinsic. Types attribute contains
120
- // the list of as [returnType, param1Type,, param2Type, ...]
121
-
122
- OverloadParamIndex = -1 ;
123
- auto TypeRecs = IntrinsicDef->getValueAsListOfDefs (" Types" );
124
- unsigned TypeRecsSize = TypeRecs.size ();
125
- // Populate return type and parameter type names
126
- for (unsigned i = 0 ; i < TypeRecsSize; i++) {
127
- auto TR = TypeRecs[i];
128
- OpTypes.emplace_back (getValueType (TR->getValueAsDef (" VT" )));
129
- // Get the overload parameter index.
130
- // TODO : Seems hacky. Is it possible that more than one parameter can
131
- // be of overload kind??
132
- // TODO: Check for any additional constraints specified for DXIL operation
133
- // restricting return type.
134
- if (i > 0 ) {
135
- auto &CurParam = OpTypes.back ();
136
- if (getParameterKind (CurParam) >= ParameterKind::OVERLOAD) {
137
- OverloadParamIndex = i;
138
- }
139
- }
140
- }
141
- // Get the operation class
142
- OpClass = R->getValueAsDef (" OpClass" )->getName ();
143
-
144
- // NOTE: For now, assume that attributes of DXIL Operation are the same as
193
+ // TODO: For now, assume that attributes of DXIL Operation are the same as
145
194
// that of the intrinsic. Deviations are expected to be encoded in TableGen
146
195
// record specification and handled accordingly here. Support to be added
147
- // later .
196
+ // as needed .
148
197
auto IntrPropList = IntrinsicDef->getValueAsListInit (" IntrProperties" );
149
198
auto IntrPropListSize = IntrPropList->size ();
150
199
for (unsigned i = 0 ; i < IntrPropListSize; i++) {
@@ -191,12 +240,13 @@ static std::string getParameterKindStr(ParameterKind Kind) {
191
240
}
192
241
193
242
// / Return a string representation of OverloadKind enum that maps to
194
- // / input Simple Value Type enum
195
- // / \param VT Simple Value Type enum
243
+ // / input LLVMType record
244
+ // / \param R TableGen def record of class LLVMType
196
245
// / \return std::string string representation of OverloadKind
197
246
198
- static std::string getOverloadKindStr (MVT::SimpleValueType VT) {
199
- switch (VT) {
247
+ static std::string getOverloadKindStr (const Record *R) {
248
+ auto VTRec = R->getValueAsDef (" VT" );
249
+ switch (getValueType (VTRec)) {
200
250
case MVT::isVoid:
201
251
return " OverloadKind::VOID" ;
202
252
case MVT::f16 :
@@ -219,6 +269,20 @@ static std::string getOverloadKindStr(MVT::SimpleValueType VT) {
219
269
return " OverloadKind::I16 | OverloadKind::I32 | OverloadKind::I64" ;
220
270
case MVT::fAny :
221
271
return " OverloadKind::HALF | OverloadKind::FLOAT | OverloadKind::DOUBLE" ;
272
+ case MVT::Other:
273
+ // Handle DXIL-specific overload types
274
+ {
275
+ auto RetStr =
276
+ StringSwitch<std::string>(R->getNameInitAsString ())
277
+ .Case (" llvm_i16ori32_ty" , " OverloadKind::I16 | OverloadKind::I32" )
278
+ .Case (" llvm_halforfloat_ty" ,
279
+ " OverloadKind::HALF | OverloadKind::FLOAT" )
280
+ .Default (" " );
281
+ if (RetStr != " " ) {
282
+ return RetStr;
283
+ }
284
+ }
285
+ LLVM_FALLTHROUGH;
222
286
default :
223
287
llvm_unreachable (
224
288
" Support for specified parameter OverloadKind not yet implemented" );
0 commit comments