reader::spirv::Parser: register user names
Bug: tint:3 Change-Id: I4391aa733079d24fb19ff2cba9f612406e63a203 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/17580 Reviewed-by: dan sinclair <dsinclair@google.com>
This commit is contained in:
parent
dc200f7d1d
commit
1ae8e85144
|
@ -317,6 +317,7 @@ if(${TINT_BUILD_SPV_READER})
|
||||||
reader/spirv/fail_stream_test.cc
|
reader/spirv/fail_stream_test.cc
|
||||||
reader/spirv/namer_test.cc
|
reader/spirv/namer_test.cc
|
||||||
reader/spirv/parser_impl_import_test.cc
|
reader/spirv/parser_impl_import_test.cc
|
||||||
|
reader/spirv/parser_impl_user_name_test.cc
|
||||||
reader/spirv/parser_impl_test.cc
|
reader/spirv/parser_impl_test.cc
|
||||||
reader/spirv/parser_test.cc
|
reader/spirv/parser_test.cc
|
||||||
reader/spirv/spirv_tools_helpers_test.cc
|
reader/spirv/spirv_tools_helpers_test.cc
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "source/opt/build_module.h"
|
#include "source/opt/build_module.h"
|
||||||
|
#include "source/opt/instruction.h"
|
||||||
|
#include "source/opt/module.h"
|
||||||
#include "spirv-tools/libspirv.hpp"
|
#include "spirv-tools/libspirv.hpp"
|
||||||
|
|
||||||
namespace tint {
|
namespace tint {
|
||||||
|
@ -35,6 +37,7 @@ ParserImpl::ParserImpl(const std::vector<uint32_t>& spv_binary)
|
||||||
: Reader(),
|
: Reader(),
|
||||||
spv_binary_(spv_binary),
|
spv_binary_(spv_binary),
|
||||||
fail_stream_(&success_, &errors_),
|
fail_stream_(&success_, &errors_),
|
||||||
|
namer_(fail_stream_),
|
||||||
tools_context_(kTargetEnv),
|
tools_context_(kTargetEnv),
|
||||||
tools_(kTargetEnv) {
|
tools_(kTargetEnv) {
|
||||||
// Create a message consumer to propagate error messages from SPIRV-Tools
|
// Create a message consumer to propagate error messages from SPIRV-Tools
|
||||||
|
@ -120,7 +123,7 @@ void ParserImpl::ResetInternalModule() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ParserImpl::ParseInternalModule() {
|
bool ParserImpl::ParseInternalModule() {
|
||||||
return RegisterExtendedInstructionImports();
|
return RegisterExtendedInstructionImports() && RegisterUserNames();
|
||||||
// TODO(dneto): fill in the rest
|
// TODO(dneto): fill in the rest
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,6 +149,35 @@ bool ParserImpl::RegisterExtendedInstructionImports() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ParserImpl::RegisterUserNames() {
|
||||||
|
// Register names from OpName and OpMemberName
|
||||||
|
for (const auto& inst : module_->debugs2()) {
|
||||||
|
switch (inst.opcode()) {
|
||||||
|
case SpvOpName:
|
||||||
|
namer_.SuggestSanitizedName(inst.GetSingleWordInOperand(0),
|
||||||
|
inst.GetInOperand(1).AsString());
|
||||||
|
break;
|
||||||
|
case SpvOpMemberName:
|
||||||
|
namer_.SuggestSanitizedMemberName(inst.GetSingleWordInOperand(0),
|
||||||
|
inst.GetSingleWordInOperand(1),
|
||||||
|
inst.GetInOperand(2).AsString());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill in struct member names, and disambiguate them.
|
||||||
|
for (const auto* type_inst : module_->GetTypes()) {
|
||||||
|
if (type_inst->opcode() == SpvOpTypeStruct) {
|
||||||
|
namer_.ResolveMemberNamesForStruct(type_inst->result_id(),
|
||||||
|
type_inst->NumInOperands());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace spirv
|
} // namespace spirv
|
||||||
} // namespace reader
|
} // namespace reader
|
||||||
} // namespace tint
|
} // namespace tint
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include "src/ast/module.h"
|
#include "src/ast/module.h"
|
||||||
#include "src/reader/reader.h"
|
#include "src/reader/reader.h"
|
||||||
#include "src/reader/spirv/fail_stream.h"
|
#include "src/reader/spirv/fail_stream.h"
|
||||||
|
#include "src/reader/spirv/namer.h"
|
||||||
|
|
||||||
namespace tint {
|
namespace tint {
|
||||||
namespace reader {
|
namespace reader {
|
||||||
|
@ -80,6 +81,9 @@ class ParserImpl : Reader {
|
||||||
return glsl_std_450_imports_;
|
return glsl_std_450_imports_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @returns the namer object
|
||||||
|
Namer& namer() { return namer_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Builds the internal representation of the SPIR-V module.
|
/// Builds the internal representation of the SPIR-V module.
|
||||||
/// Assumes the module is somewhat well-formed. Normally you
|
/// Assumes the module is somewhat well-formed. Normally you
|
||||||
|
@ -99,6 +103,11 @@ class ParserImpl : Reader {
|
||||||
/// Registers extended instruction imports. Only "GLSL.std.450" is supported.
|
/// Registers extended instruction imports. Only "GLSL.std.450" is supported.
|
||||||
bool RegisterExtendedInstructionImports();
|
bool RegisterExtendedInstructionImports();
|
||||||
|
|
||||||
|
/// 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.
|
||||||
|
bool RegisterUserNames();
|
||||||
|
|
||||||
// The SPIR-V binary we're parsing
|
// The SPIR-V binary we're parsing
|
||||||
std::vector<uint32_t> spv_binary_;
|
std::vector<uint32_t> spv_binary_;
|
||||||
|
|
||||||
|
@ -112,6 +121,9 @@ class ParserImpl : Reader {
|
||||||
FailStream fail_stream_;
|
FailStream fail_stream_;
|
||||||
spvtools::MessageConsumer message_consumer_;
|
spvtools::MessageConsumer message_consumer_;
|
||||||
|
|
||||||
|
// An object used to store and generate names for SPIR-V objects.
|
||||||
|
Namer namer_;
|
||||||
|
|
||||||
// The internal representation of the SPIR-V module and its context.
|
// The internal representation of the SPIR-V module and its context.
|
||||||
spvtools::Context tools_context_;
|
spvtools::Context tools_context_;
|
||||||
spvtools::SpirvTools tools_;
|
spvtools::SpirvTools tools_;
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
// Copyright 2020 The Tint Authors.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "gmock/gmock.h"
|
||||||
|
#include "src/reader/spirv/parser_impl.h"
|
||||||
|
#include "src/reader/spirv/spirv_tools_helpers_test.h"
|
||||||
|
|
||||||
|
namespace tint {
|
||||||
|
namespace reader {
|
||||||
|
namespace spirv {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using ::testing::Eq;
|
||||||
|
|
||||||
|
using SpvParseUserNameTest = ::testing::Test;
|
||||||
|
|
||||||
|
TEST_F(SpvParseUserNameTest, RespectOpName) {
|
||||||
|
ParserImpl p(test::Assemble(R"(
|
||||||
|
OpName %1 "the_void_type"
|
||||||
|
%1 = OpTypeVoid
|
||||||
|
)"));
|
||||||
|
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||||
|
EXPECT_THAT(p.namer().GetName(1), Eq("the_void_type"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParseUserNameTest, DistinguishDuplicateSuggestion) {
|
||||||
|
ParserImpl p(test::Assemble(R"(
|
||||||
|
OpName %1 "vanilla"
|
||||||
|
OpName %2 "vanilla"
|
||||||
|
%1 = OpTypeVoid
|
||||||
|
%2 = OpTypeInt 32 0
|
||||||
|
)"));
|
||||||
|
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||||
|
EXPECT_THAT(p.namer().GetName(1), Eq("vanilla"));
|
||||||
|
EXPECT_THAT(p.namer().GetName(2), Eq("vanilla_1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParseUserNameTest, RespectOpMemberName) {
|
||||||
|
ParserImpl p(test::Assemble(R"(
|
||||||
|
OpMemberName %3 0 "strawberry"
|
||||||
|
OpMemberName %3 1 "vanilla"
|
||||||
|
OpMemberName %3 2 "chocolate"
|
||||||
|
%2 = OpTypeInt 32 0
|
||||||
|
%3 = OpTypeStruct %2 %2 %2
|
||||||
|
)"));
|
||||||
|
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||||
|
EXPECT_THAT(p.namer().GetMemberName(3, 0), Eq("strawberry"));
|
||||||
|
EXPECT_THAT(p.namer().GetMemberName(3, 1), Eq("vanilla"));
|
||||||
|
EXPECT_THAT(p.namer().GetMemberName(3, 2), Eq("chocolate"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParseUserNameTest, SynthesizeMemberNames) {
|
||||||
|
ParserImpl p(test::Assemble(R"(
|
||||||
|
%2 = OpTypeInt 32 0
|
||||||
|
%3 = OpTypeStruct %2 %2 %2
|
||||||
|
)"));
|
||||||
|
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||||
|
EXPECT_THAT(p.namer().GetMemberName(3, 0), Eq("field0"));
|
||||||
|
EXPECT_THAT(p.namer().GetMemberName(3, 1), Eq("field1"));
|
||||||
|
EXPECT_THAT(p.namer().GetMemberName(3, 2), Eq("field2"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParseUserNameTest, MemberNamesMixUserAndSynthesized) {
|
||||||
|
ParserImpl p(test::Assemble(R"(
|
||||||
|
OpMemberName %3 1 "vanilla"
|
||||||
|
%2 = OpTypeInt 32 0
|
||||||
|
%3 = OpTypeStruct %2 %2 %2
|
||||||
|
)"));
|
||||||
|
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||||
|
EXPECT_THAT(p.namer().GetMemberName(3, 0), Eq("field0"));
|
||||||
|
EXPECT_THAT(p.namer().GetMemberName(3, 1), Eq("vanilla"));
|
||||||
|
EXPECT_THAT(p.namer().GetMemberName(3, 2), Eq("field2"));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
} // namespace spirv
|
||||||
|
} // namespace reader
|
||||||
|
} // namespace tint
|
Loading…
Reference in New Issue