Skip to content

Commit 04d4dea

Browse files
authored
Add support for SPV_INTEL_inline_assembly (KhronosGroup#6210)
1 parent 3abad50 commit 04d4dea

File tree

5 files changed

+118
-4
lines changed

5 files changed

+118
-4
lines changed

source/opcode.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@ int32_t spvOpcodeIsConstant(const spv::Op opcode) {
144144
case spv::Op::OpSpecConstantCompositeReplicateEXT:
145145
case spv::Op::OpSpecConstantOp:
146146
case spv::Op::OpSpecConstantStringAMDX:
147+
case spv::Op::OpAsmTargetINTEL:
148+
case spv::Op::OpAsmINTEL:
147149
return true;
148150
default:
149151
return false;

source/val/validate_id.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ bool InstructionCanHaveTypeOperand(const Instruction* inst) {
122122
spv::Op::OpCooperativeMatrixLengthKHR,
123123
spv::Op::OpUntypedArrayLengthKHR,
124124
spv::Op::OpFunction,
125+
spv::Op::OpAsmINTEL,
125126
};
126127
const auto opcode = inst->opcode();
127128
bool type_instruction = spvOpcodeGeneratesType(opcode);
@@ -149,6 +150,7 @@ bool InstructionRequiresTypeOperand(const Instruction* inst) {
149150
spv::Op::OpCooperativeMatrixLengthKHR,
150151
spv::Op::OpPhi,
151152
spv::Op::OpUntypedArrayLengthKHR,
153+
spv::Op::OpAsmINTEL,
152154
};
153155
const auto opcode = inst->opcode();
154156
bool debug_instruction = spvOpcodeIsDebug(opcode) || inst->IsDebugInfo();

source/val/validate_type.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -433,10 +433,9 @@ spv_result_t ValidateTypeStruct(ValidationState_t& _, const Instruction* inst) {
433433
<< "Structure <id> " << _.getIdName(member_type_id)
434434
<< " contains members with BuiltIn decoration. Therefore this "
435435
<< "structure may not be contained as a member of another "
436-
<< "structure "
437-
<< "type. Structure <id> " << _.getIdName(struct_id)
438-
<< " contains structure <id> " << _.getIdName(member_type_id)
439-
<< ".";
436+
<< "structure " << "type. Structure <id> "
437+
<< _.getIdName(struct_id) << " contains structure <id> "
438+
<< _.getIdName(member_type_id) << ".";
440439
}
441440

442441
if (spvIsVulkanEnv(_.context()->target_env) &&
@@ -617,6 +616,7 @@ spv_result_t ValidateTypeFunction(ValidationState_t& _,
617616
for (auto& pair : inst->uses()) {
618617
const auto* use = pair.first;
619618
if (use->opcode() != spv::Op::OpFunction &&
619+
use->opcode() != spv::Op::OpAsmINTEL &&
620620
!spvOpcodeIsDebug(use->opcode()) && !use->IsNonSemantic() &&
621621
!spvOpcodeIsDecoration(use->opcode())) {
622622
return _.diag(SPV_ERROR_INVALID_ID, use)

test/val/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ add_spvtools_unittest(TARGET val_abcde
4848
val_extension_spv_khr_terminate_invocation_test.cpp
4949
val_extension_spv_khr_subgroup_rotate_test.cpp
5050
val_extension_spv_nv_raw_access_chains.cpp
51+
val_extension_spv_intel_inline_assembly.cpp
5152
val_ext_inst_test.cpp
5253
val_ext_inst_debug_test.cpp
5354
${VAL_TEST_COMMON_SRCS}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
// Copyright 2025 The Khronos Group Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
// Tests for SPV_INTEL_inline_assembly
16+
17+
#include <string>
18+
19+
#include "gmock/gmock.h"
20+
#include "test/val/val_fixtures.h"
21+
22+
namespace spvtools {
23+
namespace val {
24+
namespace {
25+
26+
using ::testing::HasSubstr;
27+
28+
using ValidateSpvINTELInlineAssembly = spvtest::ValidateBase<bool>;
29+
30+
TEST_F(ValidateSpvINTELInlineAssembly, Valid) {
31+
const std::string str = R"(
32+
OpCapability Kernel
33+
OpCapability Addresses
34+
OpCapability Linkage
35+
OpCapability AsmINTEL
36+
OpExtension "SPV_INTEL_inline_assembly"
37+
OpMemoryModel Physical32 OpenCL
38+
OpDecorate %1 SideEffectsINTEL
39+
%2 = OpTypeVoid
40+
%3 = OpTypeFunction %2
41+
%4 = OpAsmTargetINTEL "spirv64-unknown-unknown"
42+
%1 = OpAsmINTEL %2 %3 %4 "nop" ""
43+
%5 = OpFunction %2 None %3
44+
%6 = OpLabel
45+
%7 = OpAsmCallINTEL %2 %1
46+
OpReturn
47+
OpFunctionEnd
48+
)";
49+
CompileSuccessfully(str.c_str());
50+
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
51+
}
52+
53+
TEST_F(ValidateSpvINTELInlineAssembly, RequiresExtension) {
54+
const std::string str = R"(
55+
OpCapability Kernel
56+
OpCapability Addresses
57+
OpCapability Linkage
58+
OpCapability AsmINTEL
59+
OpMemoryModel Physical32 OpenCL
60+
OpDecorate %1 SideEffectsINTEL
61+
%2 = OpTypeVoid
62+
%3 = OpTypeFunction %2
63+
%4 = OpAsmTargetINTEL "spirv64-unknown-unknown"
64+
%1 = OpAsmINTEL %2 %3 %4 "nop" ""
65+
%5 = OpFunction %2 None %3
66+
%6 = OpLabel
67+
%7 = OpAsmCallINTEL %2 %1
68+
OpReturn
69+
OpFunctionEnd
70+
)";
71+
CompileSuccessfully(str.c_str());
72+
EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
73+
const std::string diag = getDiagnosticString();
74+
EXPECT_THAT(
75+
diag,
76+
HasSubstr("1st operand of Capability: operand AsmINTEL(5606) requires "
77+
"one of these extensions: SPV_INTEL_inline_assembly"));
78+
EXPECT_THAT(diag, HasSubstr("OpCapability AsmINTEL"));
79+
}
80+
81+
TEST_F(ValidateSpvINTELInlineAssembly, RequiresCapability) {
82+
const std::string str = R"(
83+
OpCapability Kernel
84+
OpCapability Addresses
85+
OpCapability Linkage
86+
OpExtension "SPV_INTEL_inline_assembly"
87+
OpMemoryModel Physical32 OpenCL
88+
OpDecorate %1 SideEffectsINTEL
89+
%2 = OpTypeVoid
90+
%3 = OpTypeFunction %2
91+
%4 = OpAsmTargetINTEL "spirv64-unknown-unknown"
92+
%1 = OpAsmINTEL %2 %3 %4 "nop" ""
93+
%5 = OpFunction %2 None %3
94+
%6 = OpLabel
95+
%7 = OpAsmCallINTEL %2 %1
96+
OpReturn
97+
OpFunctionEnd
98+
)";
99+
CompileSuccessfully(str.c_str());
100+
EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
101+
const std::string diag = getDiagnosticString();
102+
EXPECT_THAT(diag, HasSubstr("Operand 2 of Decorate requires one of these "
103+
"capabilities: AsmINTEL"));
104+
EXPECT_THAT(diag, HasSubstr("OpDecorate %1 SideEffectsINTEL"));
105+
}
106+
107+
} // namespace
108+
} // namespace val
109+
} // namespace spvtools

0 commit comments

Comments
 (0)