spirv-reader: ignore NonSemantic. extended instructions

This is the first step in being able to read code generated
by Clspv.

Actively ignore the instructions instead of applying stripping
transform before hand. That way we have a chance at properly counting
instructions, which helps produce better diagnostics.

Bug: tint:3
Change-Id: I82bde88897485380d70dc8b287c3843eae5489b6
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/41641
Auto-Submit: David Neto <dneto@google.com>
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
This commit is contained in:
David Neto 2021-02-16 14:51:48 +00:00 committed by Commit Bot service account
parent c8fa020a5e
commit 909c166034
4 changed files with 95 additions and 3 deletions

View File

@ -3142,6 +3142,12 @@ bool FunctionEmitter::EmitStatement(const spvtools::opt::Instruction& inst) {
case SpvOpFunctionCall:
return EmitFunctionCall(inst);
case SpvOpExtInst:
if (parser_impl_.IsIgnoredExtendedInstruction(inst)) {
return true;
}
break;
default:
break;
}
@ -3246,9 +3252,13 @@ TypedExpression FunctionEmitter::MaybeEmitCombinatorialValue(
}
if (opcode == SpvOpExtInst) {
const auto import = inst.GetSingleWordInOperand(0);
if (parser_impl_.glsl_std_450_imports().count(import) == 0) {
Fail() << "unhandled extended instruction import with ID " << import;
if (parser_impl_.IsIgnoredExtendedInstruction(inst)) {
// Ignore it but don't error out.
return {};
}
if (!parser_impl_.IsGlslExtendedInstruction(inst)) {
Fail() << "unhandled extended instruction import with ID "
<< inst.GetSingleWordInOperand(0);
return {};
}
return EmitGlslStd450ExtInst(inst);

View File

@ -613,6 +613,8 @@ bool ParserImpl::RegisterExtendedInstructionImports() {
// TODO(dneto): Handle other extended instruction sets when needed.
if (name == "GLSL.std.450") {
glsl_std_450_imports_.insert(import.result_id());
} else if (name.find("NonSemantic.") == 0) {
ignored_imports_.insert(import.result_id());
} else {
return Fail() << "Unrecognized extended instruction set: " << name;
}
@ -626,6 +628,12 @@ bool ParserImpl::IsGlslExtendedInstruction(
(glsl_std_450_imports_.count(inst.GetSingleWordInOperand(0)) > 0);
}
bool ParserImpl::IsIgnoredExtendedInstruction(
const spvtools::opt::Instruction& inst) const {
return (inst.opcode() == SpvOpExtInst) &&
(ignored_imports_.count(inst.GetSingleWordInOperand(0)) > 0);
}
bool ParserImpl::RegisterUserAndStructMemberNames() {
if (!success_) {
return false;

View File

@ -242,6 +242,13 @@ class ParserImpl : Reader {
/// @returns true if its an SpvOpExtInst for GLSL.std.450
bool IsGlslExtendedInstruction(const spvtools::opt::Instruction& inst) const;
/// Returns true when the given instruction is an extended instruction
/// from an ignored extended instruction set.
/// @param inst a SPIR-V instruction
/// @returns true if its an SpvOpExtInst for an ignored extended instruction
bool IsIgnoredExtendedInstruction(
const spvtools::opt::Instruction& inst) const;
/// Registers user names for SPIR-V objects, from OpName, and OpMemberName.
/// Also synthesizes struct field names. Ensures uniqueness for names for
/// SPIR-V IDs, and uniqueness of names of fields within any single struct.
@ -596,6 +603,9 @@ class ParserImpl : Reader {
// The set of IDs that are imports of the GLSL.std.450 extended instruction
// sets.
std::unordered_set<uint32_t> glsl_std_450_imports_;
// The set of IDs of imports that are ignored. For example, any
// "NonSemanticInfo." import is ignored.
std::unordered_set<uint32_t> ignored_imports_;
// Maps a SPIR-V type ID to the corresponding Tint type.
std::unordered_map<uint32_t, type::Type*> id_to_type_;

View File

@ -46,6 +46,70 @@ TEST_F(SpvParserTest, Import_ImportGlslStd450) {
EXPECT_THAT(p->glsl_std_450_imports(), ElementsAre(1));
}
TEST_F(SpvParserTest, Import_NonSemantic_IgnoredImport) {
auto p = parser(test::Assemble(
R"(%40 = OpExtInstImport "NonSemantic.ClspvReflection.1")"));
EXPECT_TRUE(p->BuildAndParseInternalModule());
EXPECT_TRUE(p->error().empty());
}
TEST_F(SpvParserTest, Import_NonSemantic_IgnoredExtInsts) {
// This is the clspv-compiled output of this OpenCL C:
// kernel void foo(global int*A) { A=A; }
// It emits NonSemantic.ClspvReflection.1 extended instructions.
// But *tweaked*:
// - to remove gl_WorkgroupSize
// - to move one of the ExtInsts into the globals-and-constants
// section
// - to move one of the ExtInsts into the function body.
auto p = parser(test::Assemble(R"(
OpCapability Shader
OpExtension "SPV_KHR_storage_buffer_storage_class"
OpExtension "SPV_KHR_non_semantic_info"
%20 = OpExtInstImport "NonSemantic.ClspvReflection.1"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %15 "foo"
OpSource OpenCL_C 120
%21 = OpString "foo"
%23 = OpString "A"
OpDecorate %_runtimearr_uint ArrayStride 4
OpMemberDecorate %_struct_3 0 Offset 0
OpDecorate %_struct_3 Block
OpDecorate %12 DescriptorSet 0
OpDecorate %12 Binding 0
OpDecorate %7 SpecId 0
OpDecorate %8 SpecId 1
OpDecorate %9 SpecId 2
%24 = OpExtInst %void %20 ArgumentInfo %23
%uint = OpTypeInt 32 0
%_runtimearr_uint = OpTypeRuntimeArray %uint
%_struct_3 = OpTypeStruct %_runtimearr_uint
%_ptr_StorageBuffer__struct_3 = OpTypePointer StorageBuffer %_struct_3
%v3uint = OpTypeVector %uint 3
%_ptr_Private_v3uint = OpTypePointer Private %v3uint
%7 = OpSpecConstant %uint 1
%8 = OpSpecConstant %uint 1
%9 = OpSpecConstant %uint 1
%void = OpTypeVoid
%14 = OpTypeFunction %void
%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
%uint_0 = OpConstant %uint 0
%uint_1 = OpConstant %uint 1
%uint_2 = OpConstant %uint 2
%12 = OpVariable %_ptr_StorageBuffer__struct_3 StorageBuffer
%15 = OpFunction %void Const %14
%16 = OpLabel
%19 = OpAccessChain %_ptr_StorageBuffer_uint %12 %uint_0 %uint_0
%22 = OpExtInst %void %20 Kernel %15 %21
OpReturn
OpFunctionEnd
%25 = OpExtInst %void %20 ArgumentStorageBuffer %22 %uint_0 %uint_0 %uint_0 %24
%28 = OpExtInst %void %20 SpecConstantWorkgroupSize %uint_0 %uint_1 %uint_2
)"));
EXPECT_TRUE(p->BuildAndParseInternalModule());
EXPECT_TRUE(p->error().empty());
}
// TODO(dneto): We don't currently support other kinds of extended instruction
// imports.