From 0fb97a02bce32e649883d7ec99dd49f2fa7c2ffd Mon Sep 17 00:00:00 2001 From: Andrew Savonichev Date: Fri, 22 May 2026 23:50:29 +0900 Subject: [PATCH 1/4] [mlir][dxsa] Add dcl_function_body --- mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td | 15 +++++++++++++++ mlir/lib/Target/DXSA/BinaryParser.cpp | 13 +++++++++++++ mlir/test/Target/DXSA/dcl_function_body.mlir | 4 ++++ .../Target/DXSA/inputs/dcl_function_body.bin | Bin 0 -> 8 bytes 4 files changed, 32 insertions(+) create mode 100644 mlir/test/Target/DXSA/dcl_function_body.mlir create mode 100644 mlir/test/Target/DXSA/inputs/dcl_function_body.bin diff --git a/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td b/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td index ed5a295a38db..2df13711140f 100644 --- a/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td +++ b/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td @@ -719,4 +719,19 @@ def DXSA_DclOutput : DXSA_Op<"dcl_output"> { let assemblyFormat = "$operand attr-dict"; } +def DXSA_DclFunctionBody : DXSA_Op<"dcl_function_body"> { + let summary = "declares a function body number"; + let description = [{ + The `dxsa.dcl_function_body` declares a unique function body whose index + will appear later in the program at `label #` or `dcl_function_table`. + + Example: + ```mlir + dxsa.dcl_function_body 0 + ``` + }]; + let arguments = (ins I32Attr:$index); + let assemblyFormat = "$index attr-dict"; +} + #endif // DXSA_OPS diff --git a/mlir/lib/Target/DXSA/BinaryParser.cpp b/mlir/lib/Target/DXSA/BinaryParser.cpp index f1c860c758a2..9442adfd9882 100644 --- a/mlir/lib/Target/DXSA/BinaryParser.cpp +++ b/mlir/lib/Target/DXSA/BinaryParser.cpp @@ -635,6 +635,10 @@ class DXBuilder { return dxsa::DclOutput::create(builder, loc, operand); } + Instruction buildDclFunctionBody(uint32_t index, Location loc) { + return dxsa::DclFunctionBody::create(builder, loc, index); + } + private: MLIRContext *context; ModuleOp module; @@ -1174,6 +1178,12 @@ class Parser { return builder.buildDclOutput(*operand, loc); } + FailureOr parseDclFunctionBody(Location loc) { + auto index = parseToken(); + FAILURE_IF_FAILED(index); + return builder.buildDclFunctionBody(*index, loc); + } + OptionalParseResult parseDclInstruction(uint32_t opcodeToken, Location loc, Instruction &out) { FailureOr result; @@ -1220,6 +1230,9 @@ class Parser { case D3D10_SB_OPCODE_DCL_OUTPUT: result = parseDclOutput(loc); break; + case D3D11_SB_OPCODE_DCL_FUNCTION_BODY: + result = parseDclFunctionBody(loc); + break; default: return std::nullopt; } diff --git a/mlir/test/Target/DXSA/dcl_function_body.mlir b/mlir/test/Target/DXSA/dcl_function_body.mlir new file mode 100644 index 000000000000..c666d62c0334 --- /dev/null +++ b/mlir/test/Target/DXSA/dcl_function_body.mlir @@ -0,0 +1,4 @@ +// RUN: mlir-translate --import-dxsa-bin %S/inputs/dcl_function_body.bin | FileCheck %s +// +// CHECK-LABEL: module +// CHECK-NEXT: dxsa.dcl_function_body 1 diff --git a/mlir/test/Target/DXSA/inputs/dcl_function_body.bin b/mlir/test/Target/DXSA/inputs/dcl_function_body.bin new file mode 100644 index 0000000000000000000000000000000000000000..9e5697b45be5fba5deaa1e42ad96d7fb728cf14b GIT binary patch literal 8 PcmbQhz`(@Fz`y_i1eO4l literal 0 HcmV?d00001 From d03dc8a49c15ee5513eb03d86ca940321587fb22 Mon Sep 17 00:00:00 2001 From: Andrew Savonichev Date: Sat, 23 May 2026 00:13:42 +0900 Subject: [PATCH 2/4] [mlir][dxsa] Add dcl_function_table --- mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td | 20 +++++++++++++ mlir/lib/Target/DXSA/BinaryParser.cpp | 28 ++++++++++++++++++ mlir/test/Target/DXSA/dcl_function_table.mlir | 4 +++ .../Target/DXSA/inputs/dcl_function_table.bin | Bin 0 -> 20 bytes 4 files changed, 52 insertions(+) create mode 100644 mlir/test/Target/DXSA/dcl_function_table.mlir create mode 100644 mlir/test/Target/DXSA/inputs/dcl_function_table.bin diff --git a/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td b/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td index 2df13711140f..5b0b03264fa5 100644 --- a/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td +++ b/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td @@ -734,4 +734,24 @@ def DXSA_DclFunctionBody : DXSA_Op<"dcl_function_body"> { let assemblyFormat = "$index attr-dict"; } +def DXSA_DclFunctionTable : DXSA_Op<"dcl_function_table"> { + let summary = "declares a function table"; + let description = [{ + Declare a function table as a set of function bodies that have + been declared earlier. + + This is like a C++ vtable except there is an entry per call site + for an interface instead of per method. + + Example: + ```mlir + dxsa.dcl_function_body 0 + dxsa.dcl_function_body 1 + dxsa.dcl_function_table 0, + ``` + }]; + let arguments = (ins I32Attr:$index, DenseI32ArrayAttr:$functions); + let assemblyFormat = "$index `,` `<` `functions` `=` $functions `>` attr-dict"; +} + #endif // DXSA_OPS diff --git a/mlir/lib/Target/DXSA/BinaryParser.cpp b/mlir/lib/Target/DXSA/BinaryParser.cpp index 9442adfd9882..35a4e9887602 100644 --- a/mlir/lib/Target/DXSA/BinaryParser.cpp +++ b/mlir/lib/Target/DXSA/BinaryParser.cpp @@ -639,6 +639,13 @@ class DXBuilder { return dxsa::DclFunctionBody::create(builder, loc, index); } + Instruction buildDclFunctionTable(uint32_t index, ArrayRef functions, + Location loc) { + auto *ctx = builder.getContext(); + return dxsa::DclFunctionTable::create( + builder, loc, index, DenseI32ArrayAttr::get(ctx, functions)); + } + private: MLIRContext *context; ModuleOp module; @@ -1184,6 +1191,24 @@ class Parser { return builder.buildDclFunctionBody(*index, loc); } + FailureOr parseDclFunctionTable(Location loc) { + auto index = parseToken(); + FAILURE_IF_FAILED(index); + + auto numFunctions = parseToken(); + FAILURE_IF_FAILED(numFunctions); + + SmallVector functions; + functions.resize(*numFunctions); + for (uint32_t i = 0; i < *numFunctions; ++i) { + auto functionIndex = parseToken(); + FAILURE_IF_FAILED(functionIndex); + functions[i] = *functionIndex; + } + + return builder.buildDclFunctionTable(*index, functions, loc); + } + OptionalParseResult parseDclInstruction(uint32_t opcodeToken, Location loc, Instruction &out) { FailureOr result; @@ -1233,6 +1258,9 @@ class Parser { case D3D11_SB_OPCODE_DCL_FUNCTION_BODY: result = parseDclFunctionBody(loc); break; + case D3D11_SB_OPCODE_DCL_FUNCTION_TABLE: + result = parseDclFunctionTable(loc); + break; default: return std::nullopt; } diff --git a/mlir/test/Target/DXSA/dcl_function_table.mlir b/mlir/test/Target/DXSA/dcl_function_table.mlir new file mode 100644 index 000000000000..f493b3637309 --- /dev/null +++ b/mlir/test/Target/DXSA/dcl_function_table.mlir @@ -0,0 +1,4 @@ +// RUN: mlir-translate --import-dxsa-bin %S/inputs/dcl_function_table.bin | FileCheck %s + +// CHECK-LABEL: module +// CHECK-NEXT: dxsa.dcl_function_table 1, diff --git a/mlir/test/Target/DXSA/inputs/dcl_function_table.bin b/mlir/test/Target/DXSA/inputs/dcl_function_table.bin new file mode 100644 index 0000000000000000000000000000000000000000..5f270752e7796d2407e5f39f8e54dfe70e8ee211 GIT binary patch literal 20 VcmbQpz`)ALz`(!+#2^4-0{{!@0Gj{+ literal 0 HcmV?d00001 From 5951d5723682f01c39d1281952b62eeb2bc3db13 Mon Sep 17 00:00:00 2001 From: Andrew Savonichev Date: Fri, 29 May 2026 18:29:56 +0900 Subject: [PATCH 3/4] Handle extended instruction length for dcl_function_table --- mlir/lib/Target/DXSA/BinaryParser.cpp | 21 ++++++++++++++++-- mlir/test/Target/DXSA/dcl_function_table.mlir | 3 +++ .../Target/DXSA/inputs/dcl_function_table.bin | Bin 20 -> 44 bytes 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/mlir/lib/Target/DXSA/BinaryParser.cpp b/mlir/lib/Target/DXSA/BinaryParser.cpp index 35a4e9887602..9ccd9413a93f 100644 --- a/mlir/lib/Target/DXSA/BinaryParser.cpp +++ b/mlir/lib/Target/DXSA/BinaryParser.cpp @@ -1270,6 +1270,18 @@ class Parser { return success(); } + FailureOr> parseExtendedLength(uint32_t opcode) { + std::optional result; + if (opcode != D3D11_SB_OPCODE_DCL_FUNCTION_TABLE) { + return success(result); + } + + Token lengthToken = parseToken(); + FAILURE_IF_FAILED(lengthToken); + result = *lengthToken; + return success(result); + } + FailureOr parseInstruction() { size_t beginOffset = currentTokenOffset; Token token = parseToken(); @@ -1284,11 +1296,16 @@ class Parser { modifier.saturate = DECODE_IS_D3D10_SB_INSTRUCTION_SATURATE_ENABLED(*token); uint32_t length = DECODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(*token); + if (DECODE_IS_D3D10_SB_OPCODE_EXTENDED(*token)) { + auto extLength = parseExtendedLength(opcode); + FAILURE_IF_FAILED(extLength); + if (*extLength) { + length = extLength->value(); + } + } // TODO: extended instructions: // BOOL b51PlusShader = - // BOOL bExtended = DECODE_IS_D3D10_SB_OPCODE_EXTENDED(Token) - // ... if (opcode >= D3D10_SB_NUM_OPCODES) { emitError(getLocation(), "unknown opcode"); diff --git a/mlir/test/Target/DXSA/dcl_function_table.mlir b/mlir/test/Target/DXSA/dcl_function_table.mlir index f493b3637309..cf453b2f0649 100644 --- a/mlir/test/Target/DXSA/dcl_function_table.mlir +++ b/mlir/test/Target/DXSA/dcl_function_table.mlir @@ -2,3 +2,6 @@ // CHECK-LABEL: module // CHECK-NEXT: dxsa.dcl_function_table 1, + +// Test extended instruction length: +// CHECK-NEXT: dxsa.dcl_function_table 2, diff --git a/mlir/test/Target/DXSA/inputs/dcl_function_table.bin b/mlir/test/Target/DXSA/inputs/dcl_function_table.bin index 5f270752e7796d2407e5f39f8e54dfe70e8ee211..48c06636377df7d502501f2bccc064a169a507b3 100644 GIT binary patch delta 29 ccmWg9nIIxDk%6Isje&uI35tOf10xUv05gpO82|tP delta 4 LcmdN9nIHlH0we(C From ea9b7f156f0674d5cc0f1b306054b81e44c6bf03 Mon Sep 17 00:00:00 2001 From: Andrew Savonichev Date: Fri, 29 May 2026 19:05:57 +0900 Subject: [PATCH 4/4] Verify dcl_function_body and dcl_function_table --- mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td | 6 ++++-- mlir/lib/Dialect/DXSA/IR/DXSA.cpp | 10 ++++++++++ mlir/test/Target/DXSA/dcl_function_body_invalid.mlir | 4 ++++ mlir/test/Target/DXSA/dcl_function_table_invalid.mlir | 9 +++++++++ 4 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 mlir/test/Target/DXSA/dcl_function_body_invalid.mlir create mode 100644 mlir/test/Target/DXSA/dcl_function_table_invalid.mlir diff --git a/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td b/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td index 5b0b03264fa5..02047bbc544b 100644 --- a/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td +++ b/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td @@ -730,7 +730,7 @@ def DXSA_DclFunctionBody : DXSA_Op<"dcl_function_body"> { dxsa.dcl_function_body 0 ``` }]; - let arguments = (ins I32Attr:$index); + let arguments = (ins ConfinedAttr:$index); let assemblyFormat = "$index attr-dict"; } @@ -750,8 +750,10 @@ def DXSA_DclFunctionTable : DXSA_Op<"dcl_function_table"> { dxsa.dcl_function_table 0, ``` }]; - let arguments = (ins I32Attr:$index, DenseI32ArrayAttr:$functions); + let arguments = (ins ConfinedAttr:$index, + DenseI32ArrayAttr:$functions); let assemblyFormat = "$index `,` `<` `functions` `=` $functions `>` attr-dict"; + let hasVerifier = 1; } #endif // DXSA_OPS diff --git a/mlir/lib/Dialect/DXSA/IR/DXSA.cpp b/mlir/lib/Dialect/DXSA/IR/DXSA.cpp index e5c94051e3a5..61f44dad7961 100644 --- a/mlir/lib/Dialect/DXSA/IR/DXSA.cpp +++ b/mlir/lib/Dialect/DXSA/IR/DXSA.cpp @@ -41,6 +41,16 @@ void DXSADialect::initialize() { #define GET_OP_CLASSES #include "mlir/Dialect/DXSA/IR/DXSAOps.cpp.inc" +LogicalResult DclFunctionTable::verify() { + for (int32_t functionIndex : getFunctions()) { + if (functionIndex < 0) { + return emitOpError("function body index must not be negative, got ") + << functionIndex; + } + } + return success(); +} + //===----------------------------------------------------------------------===// // TableGen'd attribute method definitions //===----------------------------------------------------------------------===// diff --git a/mlir/test/Target/DXSA/dcl_function_body_invalid.mlir b/mlir/test/Target/DXSA/dcl_function_body_invalid.mlir new file mode 100644 index 000000000000..1f6afa5626a4 --- /dev/null +++ b/mlir/test/Target/DXSA/dcl_function_body_invalid.mlir @@ -0,0 +1,4 @@ +// RUN: mlir-opt %s -split-input-file -verify-diagnostics + +// expected-error@+1 {{'dxsa.dcl_function_body' op attribute 'index' failed to satisfy constraint: 32-bit signless integer attribute whose value is non-negative}} +dxsa.dcl_function_body -1 diff --git a/mlir/test/Target/DXSA/dcl_function_table_invalid.mlir b/mlir/test/Target/DXSA/dcl_function_table_invalid.mlir new file mode 100644 index 000000000000..1852d9eb929e --- /dev/null +++ b/mlir/test/Target/DXSA/dcl_function_table_invalid.mlir @@ -0,0 +1,9 @@ +// RUN: mlir-opt %s -split-input-file -verify-diagnostics + +// expected-error@+1 {{'dxsa.dcl_function_table' op attribute 'index' failed to satisfy constraint: 32-bit signless integer attribute whose value is non-negative}} +dxsa.dcl_function_table -1, + +// ----- + +// expected-error@+1 {{'dxsa.dcl_function_table' op function body index must not be negative, got -1}} +dxsa.dcl_function_table 1,