diff --git a/docs/DXIL.rst b/docs/DXIL.rst index 8871d3d8c9..68fe0882bc 100644 --- a/docs/DXIL.rst +++ b/docs/DXIL.rst @@ -2342,18 +2342,6 @@ ID Name Description 223 TextureGatherRaw Gather raw elements from 4 texels with no type conversions (SRV type is constrained) 224 SampleCmpLevel samples a texture and compares a single component against the specified comparison value 225 TextureStoreSample stores texel data at specified sample index -226 Reserved0 reserved -227 Reserved1 reserved -228 Reserved2 reserved -229 Reserved3 reserved -230 Reserved4 reserved -231 Reserved5 reserved -232 Reserved6 reserved -233 Reserved7 reserved -234 Reserved8 reserved -235 Reserved9 reserved -236 Reserved10 reserved -237 Reserved11 reserved 238 AllocateNodeOutputRecords returns a handle for the output records 239 GetNodeRecordPtr retrieve node input/output record pointer in address space 6 240 IncrementOutputCount Select the next logical output count for an EmptyNodeOutput for the whole group or per thread. @@ -2375,9 +2363,6 @@ ID Name Description 256 StartVertexLocation returns the BaseVertexLocation from DrawIndexedInstanced or StartVertexLocation from DrawInstanced 257 StartInstanceLocation returns the StartInstanceLocation from Draw*Instanced 258 AllocateRayQuery2 allocates space for RayQuery and return handle -259 ReservedA0 reserved -260 ReservedA1 reserved -261 ReservedA2 reserved 262 HitObject_TraceRay Analogous to TraceRay but without invoking CH/MS and returns the intermediate state as a HitObject 263 HitObject_FromRayQuery Creates a new HitObject representing a committed hit from a RayQuery 264 HitObject_FromRayQueryWithAttrs Creates a new HitObject representing a committed hit from a RayQuery and committed attributes @@ -2406,19 +2391,6 @@ ID Name Description 287 HitObject_SetShaderTableIndex Returns a HitObject with updated shader table index 288 HitObject_LoadLocalRootTableConstant Returns the root table constant for this HitObject and offset 289 HitObject_Attributes Returns the attributes set for this HitObject -290 ReservedB28 reserved -291 ReservedB29 reserved -292 ReservedB30 reserved -293 ReservedC0 reserved -294 ReservedC1 reserved -295 ReservedC2 reserved -296 ReservedC3 reserved -297 ReservedC4 reserved -298 ReservedC5 reserved -299 ReservedC6 reserved -300 ReservedC7 reserved -301 ReservedC8 reserved -302 ReservedC9 reserved 303 RawBufferVectorLoad reads from a raw buffer and structured buffer 304 RawBufferVectorStore writes to a RWByteAddressBuffer or RWStructuredBuffer 305 MatVecMul Multiplies a MxK dimension matrix and a K sized input vector @@ -3095,9 +3067,6 @@ ID Name Description 2147483675 MatrixAccumulateToDescriptor accumulates a matrix to a RWByteAddressBuffer 2147483676 MatrixAccumulateToMemory accumulates a matrix to groupshared memory 2147483677 MatrixOuterProduct Outer products an M sized vector and a K sized vector producing an MxK matrix -2147483678 LinAlgMatrixReserved0 reserved -2147483679 LinAlgMatrixReserved1 reserved -2147483680 LinAlgMatrixReserved2 reserved 2147483681 DebugBreak triggers a breakpoint if a debugger is attached 2147483682 IsDebuggerPresent returns true if a debugger is attached ========== ======================================== =================================================================================================================== diff --git a/include/dxc/DXIL/DxilConstants.h b/include/dxc/DXIL/DxilConstants.h index eb5f6ac1dd..d9c678b0d1 100644 --- a/include/dxc/DXIL/DxilConstants.h +++ b/include/dxc/DXIL/DxilConstants.h @@ -511,11 +511,6 @@ namespace ExperimentalOps { static const OpCodeTableID TableID = OpCodeTableID::ExperimentalOps; // Enumeration for ExperimentalOps DXIL operations enum class OpCode : unsigned { - // - LinAlgMatrixReserved0 = 30, // reserved - LinAlgMatrixReserved1 = 31, // reserved - LinAlgMatrixReserved2 = 32, // reserved - // Debugging DebugBreak = 33, // triggers a breakpoint if a debugger is attached IsDebuggerPresent = 34, // returns true if a debugger is attached @@ -584,6 +579,9 @@ enum class OpCode : unsigned { HitObject_TriangleObjectPosition = 10, // returns triangle vertices in object space as <9 x float> + // Reserved values: + // 30, 31, 32 + NumOpCodes = 35, // exclusive last value of enumeration }; } // namespace ExperimentalOps @@ -599,36 +597,6 @@ static const unsigned NumOpCodeTables = 2; // OPCODE-ENUM:BEGIN // Enumeration for CoreOps DXIL operations enum class OpCode : unsigned { - // - Reserved0 = 226, // reserved - Reserved1 = 227, // reserved - Reserved10 = 236, // reserved - Reserved11 = 237, // reserved - Reserved2 = 228, // reserved - Reserved3 = 229, // reserved - Reserved4 = 230, // reserved - Reserved5 = 231, // reserved - Reserved6 = 232, // reserved - Reserved7 = 233, // reserved - Reserved8 = 234, // reserved - Reserved9 = 235, // reserved - ReservedA0 = 259, // reserved - ReservedA1 = 260, // reserved - ReservedA2 = 261, // reserved - ReservedB28 = 290, // reserved - ReservedB29 = 291, // reserved - ReservedB30 = 292, // reserved - ReservedC0 = 293, // reserved - ReservedC1 = 294, // reserved - ReservedC2 = 295, // reserved - ReservedC3 = 296, // reserved - ReservedC4 = 297, // reserved - ReservedC5 = 298, // reserved - ReservedC6 = 299, // reserved - ReservedC7 = 300, // reserved - ReservedC8 = 301, // reserved - ReservedC9 = 302, // reserved - // Amplification shader instructions DispatchMesh = 173, // Amplification shader intrinsic DispatchMesh @@ -1182,6 +1150,10 @@ enum class OpCode : unsigned { OutputComplete = 241, // indicates all outputs for a given records are complete + // Reserved values: + // 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 259, 260, 261, + // 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302 + NumOpCodes_Dxil_1_0 = 137, NumOpCodes_Dxil_1_1 = 139, NumOpCodes_Dxil_1_2 = 141, @@ -1322,12 +1294,6 @@ enum class OpCode : unsigned { EXP_OPCODE(ExperimentalOps, MatrixOuterProduct), // Outer products an M sized vector and a K // sized vector producing an MxK matrix - // LinAlgMatrixReserved0 = 0x8000001E, 2147483678U, -2147483618 - EXP_OPCODE(ExperimentalOps, LinAlgMatrixReserved0), // reserved - // LinAlgMatrixReserved1 = 0x8000001F, 2147483679U, -2147483617 - EXP_OPCODE(ExperimentalOps, LinAlgMatrixReserved1), // reserved - // LinAlgMatrixReserved2 = 0x80000020, 2147483680U, -2147483616 - EXP_OPCODE(ExperimentalOps, LinAlgMatrixReserved2), // reserved // DebugBreak = 0x80000021, 2147483681U, -2147483615 EXP_OPCODE(ExperimentalOps, DebugBreak), // triggers a breakpoint if a debugger is attached diff --git a/include/dxc/DXIL/DxilOperations.h b/include/dxc/DXIL/DxilOperations.h index fabf07ee14..453315bb06 100644 --- a/include/dxc/DXIL/DxilOperations.h +++ b/include/dxc/DXIL/DxilOperations.h @@ -275,6 +275,7 @@ class OP { unsigned *OptTableIndex = nullptr); static bool IsValidOpCode(unsigned EncodedOpCode); static bool IsValidOpCode(OpCode EncodedOpCode); + static bool IsReservedOpCode(unsigned EncodedOpCode); private: // Static properties. diff --git a/lib/DXIL/DxilOperations.cpp b/lib/DXIL/DxilOperations.cpp index eb5b2a2ceb..1026da8d21 100644 --- a/lib/DXIL/DxilOperations.cpp +++ b/lib/DXIL/DxilOperations.cpp @@ -34,6 +34,10 @@ using OCC = OP::OpCodeClass; // // OP class const-static data and related static methods. // +static const OP::OpCodeProperty ReservedOpCodeProps = { + OC::Invalid, "Reserved", OCC::Reserved, "reserved", Attribute::None, 0, + {}, {}}; + /* import hctdb_instrhelp */ @@ -1994,104 +1998,19 @@ static const OP::OpCodeProperty CoreOps_OpCodeProps[] = { Attribute::None, 1, {{0x63}}, - {{0x0}}}, // Overloads: hfwi - - {OC::Reserved0, - "Reserved0", - OCC::Reserved, - "reserved", - Attribute::None, - 0, - {}, - {}}, // Overloads: v - {OC::Reserved1, - "Reserved1", - OCC::Reserved, - "reserved", - Attribute::None, - 0, - {}, - {}}, // Overloads: v - {OC::Reserved2, - "Reserved2", - OCC::Reserved, - "reserved", - Attribute::None, - 0, - {}, - {}}, // Overloads: v - {OC::Reserved3, - "Reserved3", - OCC::Reserved, - "reserved", - Attribute::None, - 0, - {}, - {}}, // Overloads: v - {OC::Reserved4, - "Reserved4", - OCC::Reserved, - "reserved", - Attribute::None, - 0, - {}, - {}}, // Overloads: v - {OC::Reserved5, - "Reserved5", - OCC::Reserved, - "reserved", - Attribute::None, - 0, - {}, - {}}, // Overloads: v - {OC::Reserved6, - "Reserved6", - OCC::Reserved, - "reserved", - Attribute::None, - 0, - {}, - {}}, // Overloads: v - {OC::Reserved7, - "Reserved7", - OCC::Reserved, - "reserved", - Attribute::None, - 0, - {}, - {}}, // Overloads: v - {OC::Reserved8, - "Reserved8", - OCC::Reserved, - "reserved", - Attribute::None, - 0, - {}, - {}}, // Overloads: v - {OC::Reserved9, - "Reserved9", - OCC::Reserved, - "reserved", - Attribute::None, - 0, - {}, - {}}, // Overloads: v - {OC::Reserved10, - "Reserved10", - OCC::Reserved, - "reserved", - Attribute::None, - 0, - {}, - {}}, // Overloads: v - {OC::Reserved11, - "Reserved11", - OCC::Reserved, - "reserved", - Attribute::None, - 0, - {}, - {}}, // Overloads: v + {{0x0}}}, // Overloads: hfwi + ReservedOpCodeProps, // Reserved: 0x000000E2 + ReservedOpCodeProps, // Reserved: 0x000000E3 + ReservedOpCodeProps, // Reserved: 0x000000E4 + ReservedOpCodeProps, // Reserved: 0x000000E5 + ReservedOpCodeProps, // Reserved: 0x000000E6 + ReservedOpCodeProps, // Reserved: 0x000000E7 + ReservedOpCodeProps, // Reserved: 0x000000E8 + ReservedOpCodeProps, // Reserved: 0x000000E9 + ReservedOpCodeProps, // Reserved: 0x000000EA + ReservedOpCodeProps, // Reserved: 0x000000EB + ReservedOpCodeProps, // Reserved: 0x000000EC + ReservedOpCodeProps, // Reserved: 0x000000ED // Create/Annotate Node Handles {OC::AllocateNodeOutputRecords, @@ -2277,32 +2196,10 @@ static const OP::OpCodeProperty CoreOps_OpCodeProps[] = { Attribute::None, 0, {}, - {}}, // Overloads: v - - {OC::ReservedA0, - "ReservedA0", - OCC::Reserved, - "reserved", - Attribute::None, - 0, - {}, - {}}, // Overloads: v - {OC::ReservedA1, - "ReservedA1", - OCC::Reserved, - "reserved", - Attribute::None, - 0, - {}, - {}}, // Overloads: v - {OC::ReservedA2, - "ReservedA2", - OCC::Reserved, - "reserved", - Attribute::None, - 0, - {}, - {}}, // Overloads: v + {}}, // Overloads: v + ReservedOpCodeProps, // Reserved: 0x00000103 + ReservedOpCodeProps, // Reserved: 0x00000104 + ReservedOpCodeProps, // Reserved: 0x00000105 // Shader Execution Reordering {OC::HitObject_TraceRay, @@ -2528,112 +2425,20 @@ static const OP::OpCodeProperty CoreOps_OpCodeProps[] = { Attribute::ArgMemOnly, 1, {{0x100}}, - {{0x0}}}, // Overloads: u - - {OC::ReservedB28, - "ReservedB28", - OCC::Reserved, - "reserved", - Attribute::None, - 0, - {}, - {}}, // Overloads: v - {OC::ReservedB29, - "ReservedB29", - OCC::Reserved, - "reserved", - Attribute::None, - 0, - {}, - {}}, // Overloads: v - {OC::ReservedB30, - "ReservedB30", - OCC::Reserved, - "reserved", - Attribute::None, - 0, - {}, - {}}, // Overloads: v - {OC::ReservedC0, - "ReservedC0", - OCC::Reserved, - "reserved", - Attribute::None, - 0, - {}, - {}}, // Overloads: v - {OC::ReservedC1, - "ReservedC1", - OCC::Reserved, - "reserved", - Attribute::None, - 0, - {}, - {}}, // Overloads: v - {OC::ReservedC2, - "ReservedC2", - OCC::Reserved, - "reserved", - Attribute::None, - 0, - {}, - {}}, // Overloads: v - {OC::ReservedC3, - "ReservedC3", - OCC::Reserved, - "reserved", - Attribute::None, - 0, - {}, - {}}, // Overloads: v - {OC::ReservedC4, - "ReservedC4", - OCC::Reserved, - "reserved", - Attribute::None, - 0, - {}, - {}}, // Overloads: v - {OC::ReservedC5, - "ReservedC5", - OCC::Reserved, - "reserved", - Attribute::None, - 0, - {}, - {}}, // Overloads: v - {OC::ReservedC6, - "ReservedC6", - OCC::Reserved, - "reserved", - Attribute::None, - 0, - {}, - {}}, // Overloads: v - {OC::ReservedC7, - "ReservedC7", - OCC::Reserved, - "reserved", - Attribute::None, - 0, - {}, - {}}, // Overloads: v - {OC::ReservedC8, - "ReservedC8", - OCC::Reserved, - "reserved", - Attribute::None, - 0, - {}, - {}}, // Overloads: v - {OC::ReservedC9, - "ReservedC9", - OCC::Reserved, - "reserved", - Attribute::None, - 0, - {}, - {}}, // Overloads: v + {{0x0}}}, // Overloads: u + ReservedOpCodeProps, // Reserved: 0x00000122 + ReservedOpCodeProps, // Reserved: 0x00000123 + ReservedOpCodeProps, // Reserved: 0x00000124 + ReservedOpCodeProps, // Reserved: 0x00000125 + ReservedOpCodeProps, // Reserved: 0x00000126 + ReservedOpCodeProps, // Reserved: 0x00000127 + ReservedOpCodeProps, // Reserved: 0x00000128 + ReservedOpCodeProps, // Reserved: 0x00000129 + ReservedOpCodeProps, // Reserved: 0x0000012A + ReservedOpCodeProps, // Reserved: 0x0000012B + ReservedOpCodeProps, // Reserved: 0x0000012C + ReservedOpCodeProps, // Reserved: 0x0000012D + ReservedOpCodeProps, // Reserved: 0x0000012E // Resources {OC::RawBufferVectorLoad, @@ -2975,32 +2780,10 @@ static const OP::OpCodeProperty ExperimentalOps_OpCodeProps[] = { Attribute::None, 2, {{0x400}, {0x400}}, - {{0x63}, {0x63}}}, // Overloads: = DXIL::NumOpCodeTables) return false; + OP::OpCodeTable &Table = OP::g_OpCodeTables[TableIndex]; unsigned Op = (EncodedOpCode & 0xFFFF); - if (Op >= OP::g_OpCodeTables[TableIndex].Count) + if (Op >= Table.Count) return false; TableID = (OP::OpCodeTableID)TID; OpIndex = Op; if (OptTableIndex) *OptTableIndex = TableIndex; - return true; + return Table.Table[Op].opCode != OP::OpCode::Invalid; } bool OP::DecodeOpCode(OpCode EncodedOpCode, OP::OpCodeTableID &TableID, unsigned &OpIndex, unsigned *OptTableIndex) { @@ -3092,6 +2876,19 @@ bool OP::IsValidOpCode(unsigned EncodedOpCode) { bool OP::IsValidOpCode(OP::OpCode EncodedOpCode) { return IsValidOpCode((unsigned)EncodedOpCode); } +bool OP::IsReservedOpCode(unsigned EncodedOpCode) { + if (EncodedOpCode == (unsigned)OP::OpCode::Invalid) + return false; + OP::OpCodeTableID TID = (OP::OpCodeTableID)(EncodedOpCode >> 16); + unsigned TableIndex = GetOpCodeTableIndex(TID); + if (TableIndex >= DXIL::NumOpCodeTables) + return false; + OP::OpCodeTable &Table = OP::g_OpCodeTables[TableIndex]; + unsigned Op = (EncodedOpCode & 0xFFFF); + if (Op >= Table.Count) + return false; + return Table.Table[Op].opCodeClass == OP::OpCodeClass::Reserved; +} const OP::OpCodeProperty &OP::GetOpCodeProps(unsigned OriginalOpCode) { OP::OpCodeTableID TID = OP::OpCodeTableID::CoreOps; unsigned Op = 0; @@ -3282,6 +3079,9 @@ bool OP::CheckOpCodeTable() { const OP::OpCodeTable &Table = OP::g_OpCodeTables[TableIndex]; for (unsigned OpIndex = 0; OpIndex < Table.Count; OpIndex++) { const OP::OpCodeProperty &Prop = Table.Table[OpIndex]; + // Skip reserved opcodes, which must never be used. + if ((unsigned)Prop.opCode == (unsigned)OP::OpCode::Invalid) + continue; OP::OpCodeTableID DecodedTID; unsigned DecodedOpIndex; unsigned DecodedTableIndex; @@ -5936,56 +5736,6 @@ Function *OP::GetOpFunc(OpCode opCode, Type *pOverloadType) { A(pI32); break; - // - case OpCode::Reserved0: - A(pV); - A(pI32); - break; - case OpCode::Reserved1: - A(pV); - A(pI32); - break; - case OpCode::Reserved2: - A(pV); - A(pI32); - break; - case OpCode::Reserved3: - A(pV); - A(pI32); - break; - case OpCode::Reserved4: - A(pV); - A(pI32); - break; - case OpCode::Reserved5: - A(pV); - A(pI32); - break; - case OpCode::Reserved6: - A(pV); - A(pI32); - break; - case OpCode::Reserved7: - A(pV); - A(pI32); - break; - case OpCode::Reserved8: - A(pV); - A(pI32); - break; - case OpCode::Reserved9: - A(pV); - A(pI32); - break; - case OpCode::Reserved10: - A(pV); - A(pI32); - break; - case OpCode::Reserved11: - A(pV); - A(pI32); - break; - // Create/Annotate Node Handles case OpCode::AllocateNodeOutputRecords: A(pNodeRecordHandle); @@ -6145,20 +5895,6 @@ Function *OP::GetOpFunc(OpCode opCode, Type *pOverloadType) { A(pI32); break; - // - case OpCode::ReservedA0: - A(pV); - A(pI32); - break; - case OpCode::ReservedA1: - A(pV); - A(pI32); - break; - case OpCode::ReservedA2: - A(pV); - A(pI32); - break; - // Shader Execution Reordering case OpCode::HitObject_TraceRay: A(pHit); @@ -6339,60 +6075,6 @@ Function *OP::GetOpFunc(OpCode opCode, Type *pOverloadType) { A(udt); break; - // - case OpCode::ReservedB28: - A(pV); - A(pI32); - break; - case OpCode::ReservedB29: - A(pV); - A(pI32); - break; - case OpCode::ReservedB30: - A(pV); - A(pI32); - break; - case OpCode::ReservedC0: - A(pV); - A(pI32); - break; - case OpCode::ReservedC1: - A(pV); - A(pI32); - break; - case OpCode::ReservedC2: - A(pV); - A(pI32); - break; - case OpCode::ReservedC3: - A(pV); - A(pI32); - break; - case OpCode::ReservedC4: - A(pV); - A(pI32); - break; - case OpCode::ReservedC5: - A(pV); - A(pI32); - break; - case OpCode::ReservedC6: - A(pV); - A(pI32); - break; - case OpCode::ReservedC7: - A(pV); - A(pI32); - break; - case OpCode::ReservedC8: - A(pV); - A(pI32); - break; - case OpCode::ReservedC9: - A(pV); - A(pI32); - break; - // Resources case OpCode::RawBufferVectorLoad: RRT(pETy); @@ -6690,20 +6372,6 @@ Function *OP::GetOpFunc(OpCode opCode, Type *pOverloadType) { EXT(1); break; - // - case OpCode::LinAlgMatrixReserved0: - A(pV); - A(pI32); - break; - case OpCode::LinAlgMatrixReserved1: - A(pV); - A(pI32); - break; - case OpCode::LinAlgMatrixReserved2: - A(pV); - A(pI32); - break; - // Debugging case OpCode::DebugBreak: A(pV); @@ -6958,18 +6626,6 @@ llvm::Type *OP::GetOverloadType(OpCode opCode, llvm::Function *F) { case OpCode::AnnotateHandle: case OpCode::CreateHandleFromBinding: case OpCode::CreateHandleFromHeap: - case OpCode::Reserved0: - case OpCode::Reserved1: - case OpCode::Reserved2: - case OpCode::Reserved3: - case OpCode::Reserved4: - case OpCode::Reserved5: - case OpCode::Reserved6: - case OpCode::Reserved7: - case OpCode::Reserved8: - case OpCode::Reserved9: - case OpCode::Reserved10: - case OpCode::Reserved11: case OpCode::AllocateNodeOutputRecords: case OpCode::IncrementOutputCount: case OpCode::OutputComplete: @@ -6986,28 +6642,12 @@ llvm::Type *OP::GetOverloadType(OpCode opCode, llvm::Function *F) { case OpCode::NodeOutputIsValid: case OpCode::GetRemainingRecursionLevels: case OpCode::AllocateRayQuery2: - case OpCode::ReservedA0: - case OpCode::ReservedA1: - case OpCode::ReservedA2: case OpCode::HitObject_FromRayQuery: case OpCode::HitObject_MakeMiss: case OpCode::HitObject_MakeNop: case OpCode::MaybeReorderThread: case OpCode::HitObject_SetShaderTableIndex: case OpCode::HitObject_LoadLocalRootTableConstant: - case OpCode::ReservedB28: - case OpCode::ReservedB29: - case OpCode::ReservedB30: - case OpCode::ReservedC0: - case OpCode::ReservedC1: - case OpCode::ReservedC2: - case OpCode::ReservedC3: - case OpCode::ReservedC4: - case OpCode::ReservedC5: - case OpCode::ReservedC6: - case OpCode::ReservedC7: - case OpCode::ReservedC8: - case OpCode::ReservedC9: case OpCode::ExperimentalNop: case OpCode::GetGroupWaveIndex: case OpCode::GetGroupWaveCount: @@ -7025,9 +6665,6 @@ llvm::Type *OP::GetOverloadType(OpCode opCode, llvm::Function *F) { case OpCode::MatrixAccumulate: case OpCode::MatrixAccumulateToDescriptor: case OpCode::MatrixAccumulateToMemory: - case OpCode::LinAlgMatrixReserved0: - case OpCode::LinAlgMatrixReserved1: - case OpCode::LinAlgMatrixReserved2: case OpCode::DebugBreak: case OpCode::IsDebuggerPresent: return Type::getVoidTy(Ctx); diff --git a/lib/DxilValidation/DxilValidation.cpp b/lib/DxilValidation/DxilValidation.cpp index 624d0b8dc6..7739c105d9 100644 --- a/lib/DxilValidation/DxilValidation.cpp +++ b/lib/DxilValidation/DxilValidation.cpp @@ -3293,10 +3293,13 @@ static void ValidateFunctionBody(Function *F, ValidationContext &ValCtx) { OP::OpCodeTableID TableID; unsigned OpIndex; if (!OP::DecodeOpCode(Opcode, TableID, OpIndex)) { + std::string OpCodeStr = std::to_string(Opcode); + if (OP::IsReservedOpCode(Opcode)) + OpCodeStr += " (reserved opcode)"; ValCtx.EmitInstrFormatError( &I, ValidationRule::InstrIllegalDXILOpCode, {std::to_string((unsigned)DXIL::OpCode::NumOpCodes), - std::to_string(Opcode)}); + OpCodeStr}); continue; } if (TableID != OP::OpCodeTableID::CoreOps && diff --git a/tools/clang/test/LitDXILValidation/reservedDXILOp.ll b/tools/clang/test/LitDXILValidation/reservedDXILOp.ll new file mode 100644 index 0000000000..2c4b569f59 --- /dev/null +++ b/tools/clang/test/LitDXILValidation/reservedDXILOp.ll @@ -0,0 +1,39 @@ +; REQUIRES: dxil-1-10 +; RUN: not %dxv %s 2>&1 | FileCheck %s + +; Make sure that using a reserved DXIL opcode produces an appropriate error. + +; 302 is currently reserved. If it is ever assigned to a valid DXIL op, +; this test should be updated to use a different reserved opcode. +; See "Reserved values:" comment in main DXIL::OpCode definition in +; DxilConstants.h for reserved opcodes. + +; CHECK: error: DXILOpCode must be [0..{{[0-9]+}}] or a supported experimental opcode. 302 (reserved opcode) specified. +; CHECK: note: at 'call void @dx.op.reserved(i32 302)' in block '#0' of function 'main'. + +target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64" +target triple = "dxil-ms-dx" + +define void @main() { + call void @dx.op.reserved(i32 302) + ret void +} + +; Function Attrs: nounwind +declare void @dx.op.reserved(i32) #0 + +attributes #0 = { nounwind} + +!llvm.ident = !{!0} +!dx.version = !{!1} +!dx.valver = !{!1} +!dx.shaderModel = !{!2} +!dx.resources = !{!3} +!dx.entryPoints = !{!4} + +!0 = !{!"hand-crafted"} +!1 = !{i32 1, i32 10} +!2 = !{!"vs", i32 6, i32 10} +!3 = !{null, null, null, null} +!4 = !{void ()* @main, !"main", !5, !3, null} +!5 = !{null, null, null} diff --git a/utils/hct/hctdb.py b/utils/hct/hctdb.py index dd03d00450..1a56396c78 100644 --- a/utils/hct/hctdb.py +++ b/utils/hct/hctdb.py @@ -70,6 +70,8 @@ def __init__(self, value, name, doc): self.name = name # Name (identifier) self.doc = doc # Documentation string self.category = None + # reserved: whether value reserved and excluded from enum definition + self.reserved = False class db_dxil_enum(object): @@ -418,6 +420,15 @@ def __getitem__(self, idx): def __iter__(self): return iter(self.ops) + def get_dxil_ops(self, include_reserved=False): + "Get all DXIL operations; optionally include_reserved." + if include_reserved: + return iter(self.ops) + for i in self.ops: + if i.is_reserved: + continue + yield i + def set_op_count_for_version(self, major, minor): op_count = len(self.ops) self.op_enum.dxil_version_info[(major, minor)] = op_count @@ -432,6 +443,7 @@ def add(self, i): def add_dxil_op( self, name, code_class, doc, oload_types, fn_attr, op_params, **props ): + "Add a new DXIL operation to this table; returns the new op." # The return value is parameter 0, insert the opcode as 1. op_params.insert(1, self.opcode_param) i = db_dxil_inst( @@ -450,14 +462,15 @@ def add_dxil_op( i.props = props return self.add(i) - def add_dxil_op_reserved(self, name): + def add_dxil_op_reserved(self): + "Reserve a DXIL opcode for future use; returns the reserved op." # The return value is parameter 0, insert the opcode as 1. op_params = [db_dxil_param(0, "v", "", "reserved"), self.opcode_param] i = db_dxil_inst( - name, + "Reserved", llvm_id=self.call_instr.llvm_id, llvm_name=self.call_instr.llvm_name, - dxil_op=name, + dxil_op="Reserved", dxil_opid=self._next_id(), dxil_table=self.name, doc="reserved", @@ -468,14 +481,9 @@ def add_dxil_op_reserved(self, name): ) return self.add(i) - def reserve_dxil_op_range(self, group_name, count, start_reserved_id=0): - "Reserve a range of dxil opcodes for future use; returns next id" - return [ - self.add_dxil_op_reserved( - "{0}{1}".format(group_name, start_reserved_id + i) - ) - for i in range(0, count) - ] + def reserve_dxil_ops(self, count=1): + "Reserve dxil opcodes for future use; returns list of reserved ops." + return [self.add_dxil_op_reserved() for i in range(0, count)] class db_dxil(object): @@ -524,18 +532,22 @@ def get_llvm_insts(self): for i in self._llvm_insts: yield i - def get_dxil_ops(self): - "Get all DXIL operations." + def get_dxil_ops(self, include_reserved=False): + "Get all DXIL operations; optionally include_reserved." for table in self.op_tables: for i in table: + if not include_reserved and i.is_reserved: + continue yield i - def get_all_insts(self): - "Get all instructions, including LLVM and DXIL operations." + def get_all_insts(self, include_reserved=False): + "Get all LLVM instructions and DXIL operations; optionally include_reserved." for i in self._llvm_insts: yield i for table in self.op_tables: for i in table: + if not include_reserved and i.is_reserved: + continue yield i def get_insts_by_names(self, *names): @@ -596,8 +608,9 @@ def build_opcode_enum(self): for i in table: v = table.op_enum.add_value(i.dxil_op_index(), i.dxil_op, i.doc) v.category = i.category + v.reserved = i.is_reserved class_dict[i.dxil_class] = i.category - if table != self.core_table: + if table != self.core_table and not i.is_reserved: # // = 0x, U, # Signed id is useful for comparing with IR opcodes, which # are printed as signed i32 values. @@ -1721,7 +1734,7 @@ def populate_CoreOps(self): self.core_table = self.add_dxil_op_table(0, "CoreOps", "Core DXIL operations") op_table = self.core_table add_dxil_op = op_table.add_dxil_op - reserve_dxil_op_range = op_table.reserve_dxil_op_range + reserve_dxil_ops = op_table.reserve_dxil_ops set_op_count_for_version = op_table.set_op_count_for_version # $o in a parameter type means the overload type @@ -5136,8 +5149,7 @@ def UFI(name, **mappings): % op_count ) - # Reserved ops - reserve_dxil_op_range("Reserved", 12) + reserve_dxil_ops(12) # Work Graph add_dxil_op( @@ -5540,8 +5552,7 @@ def UFI(name, **mappings): ], ) - # Reserved block A - reserve_dxil_op_range("ReservedA", 3) + reserve_dxil_ops(3) # Shader Execution Reordering add_dxil_op( @@ -5998,10 +6009,7 @@ def UFI(name, **mappings): ], ) - reserve_dxil_op_range("ReservedB", 3, 28) - - # Reserved block C - reserve_dxil_op_range("ReservedC", 10) + reserve_dxil_ops(13) # Long Vectors add_dxil_op( @@ -6218,6 +6226,7 @@ def populate_ExperimentalOps(self): 0x8000, "ExperimentalOps", "Experimental DXIL operations" ) add_dxil_op = op_table.add_dxil_op + reserve_dxil_ops = op_table.reserve_dxil_ops retvoid_param = db_dxil_param(0, "v", "", "no return value") @@ -6706,7 +6715,7 @@ def populate_ExperimentalOps(self): ], ) - op_table.reserve_dxil_op_range("LinAlgMatrixReserved", 3) + reserve_dxil_ops(3) # Debugging intrinsics add_dxil_op( @@ -9394,6 +9403,8 @@ def add_valrule_msg(self, name, desc, err_msg): ) def add_inst(self, i): + if i.is_reserved: + return i if i.name != "UDiv": # These should not overlap, but UDiv is a known collision. assert i.name not in self.name_idx, f"Duplicate instruction name: {i.name}" diff --git a/utils/hct/hctdb_instrhelp.py b/utils/hct/hctdb_instrhelp.py index 7e2f8b89d7..f238574562 100644 --- a/utils/hct/hctdb_instrhelp.py +++ b/utils/hct/hctdb_instrhelp.py @@ -426,10 +426,10 @@ def print_enum(self, e, **kwargs): print("// %s" % e.doc) print("enum class %s : unsigned {" % e.name) hide_val = kwargs.get("hide_val", False) - sorted_values = e.values + sorted_values = filter(lambda v: not v.reserved, e.values) if kwargs.get("sort_val", True): sorted_values = sorted( - e.values, + sorted_values, key=lambda v: ("" if v.category == None else v.category) + "." + v.name, ) last_category = None @@ -447,6 +447,12 @@ def print_enum(self, e, **kwargs): if v.doc: line_format += " // {doc}" print(line_format.format(name=v.name, value=v.value, doc=v.doc)) + # Print unnamed reserved values separately. + reserved_values = list(filter(lambda v: v.reserved, e.values)) + if len(reserved_values) > 0: + print("") + print(" // Reserved values:") + print(" // " + ", ".join([str(v.value) for v in reserved_values])) if e.last_value_name: lastName = e.last_value_name versioned = [ @@ -462,7 +468,7 @@ def print_enum(self, e, **kwargs): " " + lastName + " = " - + str(len(sorted_values)) + + str(len(e.values)) + ", // exclusive last value of enumeration" ) if e.postfix_lines: @@ -551,11 +557,13 @@ def print_opfunc_props_for_table(self, table): "{" + ",".join(["{0x%x}" % m for m in oloads]) + "}" ) for i in table: + if i.is_reserved: + print(f"ReservedOpCodeProps, // Reserved: 0x{i.dxil_opid:08X}") + continue if last_category != i.category: if last_category != None: print("") - if not i.is_reserved: - print(f" // {i.category}") + print(f" // {i.category}") last_category = i.category scalar_masks = [] vector_masks = [] @@ -1415,7 +1423,7 @@ def get_opcodes_rst(): def get_opcodes_rst_for_table(table): "Create an rst table of opcodes for given opcode table" - instrs = [i for i in table] + instrs = [i for i in table.get_dxil_ops()] rows = [] rows.append(["ID", "Name", "Description"]) for i in instrs: