Add reader::spirv::ParserImpl::ConvertType
For now, it only handles scalar types Bug: tint:3 Change-Id: Ic20e18a4f80790e6cd10d4c06dd2abfd8f67a304 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/17700 Reviewed-by: dan sinclair <dsinclair@google.com>
This commit is contained in:
parent
69b9c1b8e0
commit
71e1d81654
|
@ -319,6 +319,7 @@ if(${TINT_BUILD_SPV_READER})
|
|||
reader/spirv/enum_converter_test.cc
|
||||
reader/spirv/fail_stream_test.cc
|
||||
reader/spirv/namer_test.cc
|
||||
reader/spirv/parser_impl_convert_type_test.cc
|
||||
reader/spirv/parser_impl_entry_point_test.cc
|
||||
reader/spirv/parser_impl_import_test.cc
|
||||
reader/spirv/parser_impl_user_name_test.cc
|
||||
|
|
|
@ -15,13 +15,22 @@
|
|||
#include "src/reader/spirv/parser_impl.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "source/opt/build_module.h"
|
||||
#include "source/opt/instruction.h"
|
||||
#include "source/opt/module.h"
|
||||
#include "source/opt/type_manager.h"
|
||||
#include "spirv-tools/libspirv.hpp"
|
||||
#include "src/ast/type/bool_type.h"
|
||||
#include "src/ast/type/f32_type.h"
|
||||
#include "src/ast/type/i32_type.h"
|
||||
#include "src/ast/type/type.h"
|
||||
#include "src/ast/type/u32_type.h"
|
||||
#include "src/ast/type/void_type.h"
|
||||
#include "src/type_manager.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
|
@ -92,6 +101,77 @@ ast::Module ParserImpl::module() {
|
|||
return std::move(ast_module_);
|
||||
}
|
||||
|
||||
const ast::type::Type* ParserImpl::ConvertType(uint32_t type_id) {
|
||||
if (!success_) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (type_mgr_ == nullptr) {
|
||||
Fail() << "ConvertType called when the internal module has not been built.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto where = id_to_type_.find(type_id);
|
||||
if (where != id_to_type_.end()) {
|
||||
return where->second;
|
||||
}
|
||||
|
||||
auto* spirv_type = type_mgr_->GetType(type_id);
|
||||
if (spirv_type == nullptr) {
|
||||
Fail() << "ID is not a SPIR-V type: " << type_id;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const ast::type::Type* result = nullptr;
|
||||
TypeManager* tint_tm = TypeManager::Instance();
|
||||
|
||||
switch (spirv_type->kind()) {
|
||||
case spvtools::opt::analysis::Type::kVoid:
|
||||
result = tint_tm->Get(std::make_unique<ast::type::VoidType>());
|
||||
break;
|
||||
case spvtools::opt::analysis::Type::kBool:
|
||||
result = tint_tm->Get(std::make_unique<ast::type::BoolType>());
|
||||
break;
|
||||
case spvtools::opt::analysis::Type::kInteger: {
|
||||
const auto* int_ty = spirv_type->AsInteger();
|
||||
if (int_ty->width() == 32) {
|
||||
if (int_ty->IsSigned()) {
|
||||
result = tint_tm->Get(std::make_unique<ast::type::I32Type>());
|
||||
} else {
|
||||
result = tint_tm->Get(std::make_unique<ast::type::U32Type>());
|
||||
}
|
||||
} else {
|
||||
Fail() << "unhandled integer width: " << int_ty->width();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case spvtools::opt::analysis::Type::kFloat: {
|
||||
const auto* float_ty = spirv_type->AsFloat();
|
||||
if (float_ty->width() == 32) {
|
||||
result = tint_tm->Get(std::make_unique<ast::type::F32Type>());
|
||||
} else {
|
||||
Fail() << "unhandled float width: " << float_ty->width();
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// The error diagnostic will be generated below because result is still
|
||||
// nullptr.
|
||||
break;
|
||||
}
|
||||
|
||||
if (result == nullptr) {
|
||||
if (success_) {
|
||||
// Only emit a new diagnostic if we haven't already emitted a more
|
||||
// specific one.
|
||||
Fail() << "unknown SPIR-V type: " << type_id;
|
||||
}
|
||||
} else {
|
||||
id_to_type_[type_id] = result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ParserImpl::BuildInternalModule() {
|
||||
tools_.SetMessageConsumer(message_consumer_);
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "spirv-tools/libspirv.hpp"
|
||||
#include "src/ast/import.h"
|
||||
#include "src/ast/module.h"
|
||||
#include "src/ast/type/type.h"
|
||||
#include "src/reader/reader.h"
|
||||
#include "src/reader/spirv/enum_converter.h"
|
||||
#include "src/reader/spirv/fail_stream.h"
|
||||
|
@ -82,6 +83,14 @@ class ParserImpl : Reader {
|
|||
return glsl_std_450_imports_;
|
||||
}
|
||||
|
||||
/// Converts a SPIR-V type to a Tint type.
|
||||
/// On failure, logs an error and returns null.
|
||||
/// This should only be called after the internal
|
||||
/// representation of the module has been built.
|
||||
/// @param type_id the SPIR-V ID of a type.
|
||||
/// @returns a Tint type, or nullptr
|
||||
const ast::type::Type* ConvertType(uint32_t type_id);
|
||||
|
||||
/// @returns the namer object
|
||||
Namer& namer() { return namer_; }
|
||||
|
||||
|
@ -147,6 +156,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_;
|
||||
|
||||
// Maps a SPIR-V type ID to a Tint type.
|
||||
std::unordered_map<uint32_t, const ast::type::Type*> id_to_type_;
|
||||
};
|
||||
|
||||
} // namespace spirv
|
||||
|
|
|
@ -0,0 +1,136 @@
|
|||
// 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 "src/reader/spirv/parser_impl.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "src/reader/spirv/spirv_tools_helpers_test.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace spirv {
|
||||
namespace {
|
||||
|
||||
using ::testing::Eq;
|
||||
|
||||
using SpvParserTest_ConvertType = ::testing::Test;
|
||||
|
||||
TEST_F(SpvParserTest_ConvertType, PreservesExistingFailure) {
|
||||
ParserImpl p(std::vector<uint32_t>{});
|
||||
p.Fail() << "boing";
|
||||
const auto* type = p.ConvertType(10);
|
||||
EXPECT_EQ(type, nullptr);
|
||||
EXPECT_THAT(p.error(), Eq("boing"));
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest_ConvertType, NotAnId) {
|
||||
ParserImpl p(test::Assemble("%1 = OpExtInstImport \"GLSL.std.450\""));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule()) << p.error();
|
||||
|
||||
const auto* type = p.ConvertType(10);
|
||||
EXPECT_EQ(type, nullptr);
|
||||
EXPECT_EQ(nullptr, type);
|
||||
EXPECT_THAT(p.error(), Eq("ID is not a SPIR-V type: 10"));
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest_ConvertType, IdExistsButIsNotAType) {
|
||||
ParserImpl p(test::Assemble("%1 = OpExtInstImport \"GLSL.std.450\""));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
|
||||
const auto* type = p.ConvertType(1);
|
||||
EXPECT_EQ(nullptr, type);
|
||||
EXPECT_THAT(p.error(), Eq("ID is not a SPIR-V type: 1"));
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest_ConvertType, UnhandledType) {
|
||||
// Pipes are an OpenCL type. Tint doesn't support them.
|
||||
ParserImpl p(test::Assemble("%70 = OpTypePipe WriteOnly"));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
|
||||
const auto* type = p.ConvertType(70);
|
||||
EXPECT_EQ(nullptr, type);
|
||||
EXPECT_THAT(p.error(), Eq("unknown SPIR-V type: 70"));
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest_ConvertType, Void) {
|
||||
ParserImpl p(test::Assemble("%1 = OpTypeVoid"));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
|
||||
const auto* type = p.ConvertType(1);
|
||||
EXPECT_TRUE(type->IsVoid());
|
||||
EXPECT_TRUE(p.error().empty());
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest_ConvertType, Bool) {
|
||||
ParserImpl p(test::Assemble("%100 = OpTypeBool"));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
|
||||
const auto* type = p.ConvertType(100);
|
||||
EXPECT_TRUE(type->IsBool());
|
||||
EXPECT_TRUE(p.error().empty());
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest_ConvertType, I32) {
|
||||
ParserImpl p(test::Assemble("%2 = OpTypeInt 32 1"));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
|
||||
const auto* type = p.ConvertType(2);
|
||||
EXPECT_TRUE(type->IsI32());
|
||||
EXPECT_TRUE(p.error().empty());
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest_ConvertType, U32) {
|
||||
ParserImpl p(test::Assemble("%3 = OpTypeInt 32 0"));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
|
||||
const auto* type = p.ConvertType(3);
|
||||
EXPECT_TRUE(type->IsU32());
|
||||
EXPECT_TRUE(p.error().empty());
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest_ConvertType, F32) {
|
||||
ParserImpl p(test::Assemble("%4 = OpTypeFloat 32"));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
|
||||
const auto* type = p.ConvertType(4);
|
||||
EXPECT_TRUE(type->IsF32());
|
||||
EXPECT_TRUE(p.error().empty());
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest_ConvertType, BadIntWidth) {
|
||||
ParserImpl p(test::Assemble("%5 = OpTypeInt 17 1"));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
|
||||
const auto* type = p.ConvertType(5);
|
||||
EXPECT_EQ(type, nullptr);
|
||||
EXPECT_THAT(p.error(), Eq("unhandled integer width: 17"));
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest_ConvertType, BadFloatWidth) {
|
||||
ParserImpl p(test::Assemble("%6 = OpTypeFloat 19"));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
|
||||
const auto* type = p.ConvertType(6);
|
||||
EXPECT_EQ(type, nullptr);
|
||||
EXPECT_THAT(p.error(), Eq("unhandled float width: 19"));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace spirv
|
||||
} // namespace reader
|
||||
} // namespace tint
|
Loading…
Reference in New Issue