mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-11-23 04:00:05 +00:00
Optimization: Add type manager.
Type manager will construct a map of types gradually from instructions.
This commit is contained in:
parent
6d4d15b9d0
commit
c562e231e3
@ -11,6 +11,7 @@ add_library(SPIRV-Tools-opt
|
||||
passes.h
|
||||
pass_manager.h
|
||||
types.h
|
||||
type_manager.h
|
||||
|
||||
def_use_manager.cpp
|
||||
function.cpp
|
||||
@ -20,6 +21,7 @@ add_library(SPIRV-Tools-opt
|
||||
module.cpp
|
||||
passes.cpp
|
||||
types.cpp
|
||||
type_manager.cpp
|
||||
)
|
||||
|
||||
spvtools_default_compile_options(SPIRV-Tools-opt)
|
||||
|
@ -30,7 +30,7 @@
|
||||
namespace spvtools {
|
||||
namespace ir {
|
||||
|
||||
std::vector<Instruction*> Module::types() {
|
||||
std::vector<Instruction*> Module::GetTypes() {
|
||||
std::vector<Instruction*> insts;
|
||||
for (uint32_t i = 0; i < types_values_.size(); ++i) {
|
||||
if (IsTypeInst(types_values_[i]->opcode()))
|
||||
@ -39,6 +39,15 @@ std::vector<Instruction*> Module::types() {
|
||||
return insts;
|
||||
};
|
||||
|
||||
std::vector<const Instruction*> Module::GetTypes() const {
|
||||
std::vector<const Instruction*> insts;
|
||||
for (uint32_t i = 0; i < types_values_.size(); ++i) {
|
||||
if (IsTypeInst(types_values_[i]->opcode()))
|
||||
insts.push_back(types_values_[i].get());
|
||||
}
|
||||
return insts;
|
||||
};
|
||||
|
||||
std::vector<Instruction*> Module::GetConstants() {
|
||||
std::vector<Instruction*> insts;
|
||||
for (uint32_t i = 0; i < types_values_.size(); ++i) {
|
||||
|
@ -83,7 +83,8 @@ class Module {
|
||||
|
||||
// Returns a vector of pointers to type-declaration instructions in this
|
||||
// module.
|
||||
std::vector<Instruction*> types();
|
||||
std::vector<Instruction*> GetTypes();
|
||||
std::vector<const Instruction*> GetTypes() const;
|
||||
// Returns the constant-defining instructions.
|
||||
std::vector<Instruction*> GetConstants();
|
||||
const std::vector<std::unique_ptr<Instruction>>& debugs() const {
|
||||
|
226
source/opt/type_manager.cpp
Normal file
226
source/opt/type_manager.cpp
Normal file
@ -0,0 +1,226 @@
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
|
||||
#include "reflect.h"
|
||||
#include "type_manager.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
namespace analysis {
|
||||
|
||||
Type* TypeManager::GetType(uint32_t id) const {
|
||||
if (id_to_type_.count(id) != 0) return id_to_type_.at(id).get();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ForwardPointer* TypeManager::GetForwardPointer(uint32_t index) const {
|
||||
if (index >= forward_pointers_.size()) return nullptr;
|
||||
return forward_pointers_.at(index).get();
|
||||
}
|
||||
|
||||
void TypeManager::AnalyzeType(const spvtools::ir::Module& module) {
|
||||
for (const auto* inst : module.GetTypes()) RecordIfTypeDefinition(*inst);
|
||||
for (const auto& inst : module.annotations()) AttachIfTypeDecoration(*inst);
|
||||
}
|
||||
|
||||
Type* TypeManager::RecordIfTypeDefinition(const spvtools::ir::Instruction& inst) {
|
||||
if (!spvtools::ir::IsTypeInst(inst.opcode())) return nullptr;
|
||||
|
||||
Type* type = nullptr;
|
||||
switch (inst.opcode()) {
|
||||
case SpvOpTypeVoid:
|
||||
type = new Void();
|
||||
break;
|
||||
case SpvOpTypeBool:
|
||||
type = new Bool();
|
||||
break;
|
||||
case SpvOpTypeInt:
|
||||
type = new Integer(inst.GetSingleWordInOperand(0),
|
||||
inst.GetSingleWordInOperand(1));
|
||||
break;
|
||||
case SpvOpTypeFloat:
|
||||
type = new Float(inst.GetSingleWordInOperand(0));
|
||||
break;
|
||||
case SpvOpTypeVector:
|
||||
type = new Vector(GetType(inst.GetSingleWordInOperand(0)),
|
||||
inst.GetSingleWordInOperand(1));
|
||||
break;
|
||||
case SpvOpTypeMatrix:
|
||||
type = new Matrix(GetType(inst.GetSingleWordInOperand(0)),
|
||||
inst.GetSingleWordInOperand(1));
|
||||
break;
|
||||
case SpvOpTypeImage: {
|
||||
const SpvAccessQualifier access =
|
||||
inst.NumInOperands() < 8
|
||||
? SpvAccessQualifierReadOnly
|
||||
: static_cast<SpvAccessQualifier>(inst.GetSingleWordInOperand(7));
|
||||
type = new Image(
|
||||
GetType(inst.GetSingleWordInOperand(0)),
|
||||
static_cast<SpvDim>(inst.GetSingleWordInOperand(1)),
|
||||
inst.GetSingleWordInOperand(2), inst.GetSingleWordInOperand(3),
|
||||
inst.GetSingleWordInOperand(4), inst.GetSingleWordInOperand(5),
|
||||
static_cast<SpvImageFormat>(inst.GetSingleWordInOperand(6)), access);
|
||||
} break;
|
||||
case SpvOpTypeSampler:
|
||||
type = new Sampler();
|
||||
break;
|
||||
case SpvOpTypeSampledImage:
|
||||
type = new SampledImage(GetType(inst.GetSingleWordInOperand(0)));
|
||||
break;
|
||||
case SpvOpTypeArray:
|
||||
type = new Array(GetType(inst.GetSingleWordInOperand(0)),
|
||||
inst.GetSingleWordInOperand(1));
|
||||
break;
|
||||
case SpvOpTypeRuntimeArray:
|
||||
type = new RuntimeArray(GetType(inst.GetSingleWordInOperand(0)));
|
||||
break;
|
||||
case SpvOpTypeStruct: {
|
||||
std::vector<Type*> element_types;
|
||||
for (uint32_t i = 0; i < inst.NumInOperands(); ++i) {
|
||||
element_types.push_back(GetType(inst.GetSingleWordInOperand(i)));
|
||||
}
|
||||
type = new Struct(element_types);
|
||||
} break;
|
||||
case SpvOpTypeOpaque: {
|
||||
const uint32_t* data = inst.GetInOperand(0).words.data();
|
||||
type = new Opaque(reinterpret_cast<const char*>(data));
|
||||
} break;
|
||||
case SpvOpTypePointer: {
|
||||
auto* ptr = new Pointer(
|
||||
GetType(inst.GetSingleWordInOperand(1)),
|
||||
static_cast<SpvStorageClass>(inst.GetSingleWordInOperand(0)));
|
||||
// Let's see if somebody forward references this pointer.
|
||||
for (auto* fp : unresolved_forward_pointers_) {
|
||||
if (fp->target_id() == inst.result_id()) {
|
||||
fp->SetTargetPointer(ptr);
|
||||
unresolved_forward_pointers_.erase(fp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
type = ptr;
|
||||
} break;
|
||||
case SpvOpTypeFunction: {
|
||||
Type* return_type = GetType(inst.GetSingleWordInOperand(0));
|
||||
std::vector<Type*> param_types;
|
||||
for (uint32_t i = 1; i < inst.NumInOperands(); ++i) {
|
||||
param_types.push_back(GetType(inst.GetSingleWordInOperand(i)));
|
||||
}
|
||||
type = new Function(return_type, param_types);
|
||||
} break;
|
||||
case SpvOpTypeEvent:
|
||||
type = new Event();
|
||||
break;
|
||||
case SpvOpTypeDeviceEvent:
|
||||
type = new DeviceEvent();
|
||||
break;
|
||||
case SpvOpTypeReserveId:
|
||||
type = new ReserveId();
|
||||
break;
|
||||
case SpvOpTypeQueue:
|
||||
type = new Queue();
|
||||
break;
|
||||
case SpvOpTypePipe:
|
||||
type = new Pipe(
|
||||
static_cast<SpvAccessQualifier>(inst.GetSingleWordInOperand(0)));
|
||||
break;
|
||||
case SpvOpTypeForwardPointer: {
|
||||
// Handling of forward pointers is different from the other types.
|
||||
auto* fp = new ForwardPointer(
|
||||
inst.GetSingleWordInOperand(0),
|
||||
static_cast<SpvStorageClass>(inst.GetSingleWordInOperand(1)));
|
||||
forward_pointers_.emplace_back(fp);
|
||||
unresolved_forward_pointers_.insert(fp);
|
||||
return fp;
|
||||
}
|
||||
case SpvOpTypePipeStorage:
|
||||
type = new PipeStorage();
|
||||
break;
|
||||
case SpvOpTypeNamedBarrier:
|
||||
type = new NamedBarrier();
|
||||
break;
|
||||
default:
|
||||
assert(0 && "unhandled type found");
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t id = inst.result_id();
|
||||
if (id == 0) {
|
||||
assert(inst.opcode() == SpvOpTypeForwardPointer &&
|
||||
"instruction without result id found");
|
||||
} else {
|
||||
assert(type != nullptr && "type should not be nullptr at this point");
|
||||
id_to_type_[id].reset(type);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
void TypeManager::AttachIfTypeDecoration(const ir::Instruction& inst) {
|
||||
const SpvOp opcode = inst.opcode();
|
||||
if (!ir::IsAnnotationInst(opcode)) return;
|
||||
const uint32_t id = inst.GetSingleWordOperand(0);
|
||||
// Do nothing if the id to be decorated is not for a known type.
|
||||
if (!id_to_type_.count(id)) return;
|
||||
|
||||
Type* target_type = id_to_type_[id].get();
|
||||
switch (opcode) {
|
||||
case SpvOpDecorate: {
|
||||
const auto count = inst.NumOperands();
|
||||
std::vector<uint32_t> data;
|
||||
for (uint32_t i = 1; i < count; ++i) {
|
||||
data.push_back(inst.GetSingleWordOperand(i));
|
||||
}
|
||||
target_type->AddDecoration(std::move(data));
|
||||
} break;
|
||||
case SpvOpMemberDecorate: {
|
||||
const auto count = inst.NumOperands();
|
||||
const uint32_t index = inst.GetSingleWordOperand(1);
|
||||
std::vector<uint32_t> data;
|
||||
for (uint32_t i = 2; i < count; ++i) {
|
||||
data.push_back(inst.GetSingleWordOperand(i));
|
||||
}
|
||||
if (Struct* st = target_type->AsStruct()) {
|
||||
st->AddMemeberDecoration(index, std::move(data));
|
||||
} else {
|
||||
assert(0 && "OpMemberDecorate on non-struct type");
|
||||
}
|
||||
} break;
|
||||
case SpvOpDecorationGroup:
|
||||
case SpvOpGroupDecorate:
|
||||
case SpvOpGroupMemberDecorate:
|
||||
assert(0 && "unhandled decoration");
|
||||
break;
|
||||
default:
|
||||
assert(0 && "unreachable");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace analysis
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
86
source/opt/type_manager.h
Normal file
86
source/opt/type_manager.h
Normal file
@ -0,0 +1,86 @@
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#ifndef LIBSPIRV_OPT_TYPE_MANAGER_H_
|
||||
#define LIBSPIRV_OPT_TYPE_MANAGER_H_
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "module.h"
|
||||
#include "types.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
namespace analysis {
|
||||
|
||||
// A class for managing the SPIR-V type hierarchy.
|
||||
class TypeManager {
|
||||
public:
|
||||
using IdToTypeMap = std::unordered_map<uint32_t, std::unique_ptr<Type>>;
|
||||
using ForwardPointerVector = std::vector<std::unique_ptr<ForwardPointer>>;
|
||||
|
||||
TypeManager() = default;
|
||||
TypeManager(const TypeManager&) = delete;
|
||||
TypeManager(TypeManager&&) = delete;
|
||||
TypeManager& operator=(const TypeManager&) = delete;
|
||||
TypeManager& operator=(TypeManager&&) = delete;
|
||||
|
||||
// Returns the type for the given type |id|. Returns nullptr if the given |id|
|
||||
// does not define a type.
|
||||
Type* GetType(uint32_t id) const;
|
||||
// Returns the number of types hold in this manager.
|
||||
size_t NumTypes() const { return id_to_type_.size(); }
|
||||
|
||||
// Returns the forward pointer type at the given |index|.
|
||||
ForwardPointer* GetForwardPointer(uint32_t index) const;
|
||||
// Returns the number of forward pointer types hold in this manager.
|
||||
size_t NumForwardPointers() const { return forward_pointers_.size(); }
|
||||
|
||||
// Analyzes the types and decorations on types in the given |module|.
|
||||
void AnalyzeType(const spvtools::ir::Module& module);
|
||||
|
||||
private:
|
||||
// Creates and returns a type from the given SPIR-V |inst|. Returns nullptr if
|
||||
// the given instruction is not for defining a type.
|
||||
Type* RecordIfTypeDefinition(const spvtools::ir::Instruction& inst);
|
||||
// Attaches the decoration encoded in |inst| to a type. Does nothing if the
|
||||
// given instruction is not a decoration instruction or not decorating a type.
|
||||
void AttachIfTypeDecoration(const spvtools::ir::Instruction& inst);
|
||||
|
||||
IdToTypeMap id_to_type_; // Mapping from ids to their type representations.
|
||||
ForwardPointerVector forward_pointers_; // All forward pointer declarations.
|
||||
// All unresolved forward pointer declarations.
|
||||
// Refers the contents in the above vector.
|
||||
std::unordered_set<ForwardPointer*> unresolved_forward_pointers_;
|
||||
};
|
||||
|
||||
} // namespace analysis
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
||||
|
||||
#endif // LIBSPIRV_OPT_TYPE_MANAGER_H_
|
@ -68,3 +68,8 @@ add_spvtools_unittest(TARGET types
|
||||
SRCS test_types.cpp
|
||||
LIBS SPIRV-Tools-opt
|
||||
)
|
||||
|
||||
add_spvtools_unittest(TARGET type_manager
|
||||
SRCS test_type_manager.cpp
|
||||
LIBS SPIRV-Tools-opt ${SPIRV_TOOLS}
|
||||
)
|
||||
|
212
test/opt/test_type_manager.cpp
Normal file
212
test/opt/test_type_manager.cpp
Normal file
@ -0,0 +1,212 @@
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "opt/instruction.h"
|
||||
#include "opt/libspirv.hpp"
|
||||
#include "opt/type_manager.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace spvtools;
|
||||
|
||||
TEST(TypeManager, TypeStrings) {
|
||||
const std::string text = R"(
|
||||
OpTypeForwardPointer !20 !2 ; id for %p is 20, Uniform is 2
|
||||
OpTypeForwardPointer !10000 !1
|
||||
%void = OpTypeVoid
|
||||
%bool = OpTypeBool
|
||||
%u32 = OpTypeInt 32 0
|
||||
%id4 = OpConstant %u32 4
|
||||
%s32 = OpTypeInt 32 1
|
||||
%f64 = OpTypeFloat 64
|
||||
%v3u32 = OpTypeVector %u32 3
|
||||
%m3x3 = OpTypeMatrix %v3u32 3
|
||||
%img1 = OpTypeImage %s32 Cube 0 1 1 0 R32f ReadWrite
|
||||
%img2 = OpTypeImage %s32 Cube 0 1 1 0 R32f
|
||||
%sampler = OpTypeSampler
|
||||
%si1 = OpTypeSampledImage %img1
|
||||
%si2 = OpTypeSampledImage %img2
|
||||
%a5u32 = OpTypeArray %u32 %id4
|
||||
%af64 = OpTypeRuntimeArray %f64
|
||||
%st1 = OpTypeStruct %u32
|
||||
%st2 = OpTypeStruct %f64 %s32 %v3u32
|
||||
%opaque1 = OpTypeOpaque ""
|
||||
%opaque2 = OpTypeOpaque "opaque"
|
||||
%p = OpTypePointer Uniform %st1
|
||||
%f = OpTypeFunction %void %u32 %u32
|
||||
%event = OpTypeEvent
|
||||
%de = OpTypeDeviceEvent
|
||||
%ri = OpTypeReserveId
|
||||
%queue = OpTypeQueue
|
||||
%pipe = OpTypePipe ReadOnly
|
||||
%ps = OpTypePipeStorage
|
||||
%nb = OpTypeNamedBarrier
|
||||
)";
|
||||
|
||||
std::vector<std::pair<uint32_t, std::string>> type_id_strs = {
|
||||
{1, "void"},
|
||||
{2, "bool"},
|
||||
{3, "uint32"},
|
||||
// Id 4 is used by the constant.
|
||||
{5, "sint32"},
|
||||
{6, "float64"},
|
||||
{7, "<uint32, 3>"},
|
||||
{8, "<<uint32, 3>, 3>"},
|
||||
{9, "image(sint32, 3, 0, 1, 1, 0, 3, 2)"},
|
||||
{10, "image(sint32, 3, 0, 1, 1, 0, 3, 0)"},
|
||||
{11, "sampler"},
|
||||
{12, "sampled_image(image(sint32, 3, 0, 1, 1, 0, 3, 2))"},
|
||||
{13, "sampled_image(image(sint32, 3, 0, 1, 1, 0, 3, 0))"},
|
||||
{14, "[uint32, id(4)]"},
|
||||
{15, "[float64]"},
|
||||
{16, "{uint32}"},
|
||||
{17, "{float64, sint32, <uint32, 3>}"},
|
||||
{18, "opaque('')"},
|
||||
{19, "opaque('opaque')"},
|
||||
{20, "{uint32}*"},
|
||||
{21, "(uint32, uint32) -> void"},
|
||||
{22, "event"},
|
||||
{23, "device_event"},
|
||||
{24, "reserve_id"},
|
||||
{25, "queue"},
|
||||
{26, "pipe(0)"},
|
||||
{27, "pipe_storage"},
|
||||
{28, "named_barrier"},
|
||||
};
|
||||
|
||||
opt::analysis::TypeManager manager;
|
||||
std::unique_ptr<ir::Module> module =
|
||||
SpvTools(SPV_ENV_UNIVERSAL_1_1).BuildModule(text);
|
||||
manager.AnalyzeType(*module);
|
||||
|
||||
EXPECT_EQ(type_id_strs.size(), manager.NumTypes());
|
||||
EXPECT_EQ(2u, manager.NumForwardPointers());
|
||||
|
||||
for (const auto& p : type_id_strs) {
|
||||
EXPECT_EQ(p.second, manager.GetType(p.first)->str());
|
||||
}
|
||||
EXPECT_EQ("forward_pointer({uint32}*)", manager.GetForwardPointer(0)->str());
|
||||
EXPECT_EQ("forward_pointer(10000)", manager.GetForwardPointer(1)->str());
|
||||
}
|
||||
|
||||
TEST(Struct, DecorationOnStruct) {
|
||||
const std::string text = R"(
|
||||
OpDecorate %struct1 Block
|
||||
OpDecorate %struct2 Block
|
||||
OpDecorate %struct3 Block
|
||||
OpDecorate %struct4 Block
|
||||
|
||||
%u32 = OpTypeInt 32 0 ; id: 5
|
||||
%f32 = OpTypeFloat 32 ; id: 6
|
||||
%struct1 = OpTypeStruct %u32 %f32 ; base
|
||||
%struct2 = OpTypeStruct %f32 %u32 ; different member order
|
||||
%struct3 = OpTypeStruct %f32 ; different member list
|
||||
%struct4 = OpTypeStruct %u32 %f32 ; the same
|
||||
%struct7 = OpTypeStruct %f32 ; no decoration
|
||||
)";
|
||||
opt::analysis::TypeManager manager;
|
||||
std::unique_ptr<ir::Module> module =
|
||||
SpvTools(SPV_ENV_UNIVERSAL_1_1).BuildModule(text);
|
||||
manager.AnalyzeType(*module);
|
||||
|
||||
ASSERT_EQ(7u, manager.NumTypes());
|
||||
ASSERT_EQ(0u, manager.NumForwardPointers());
|
||||
// Make sure we get ids correct.
|
||||
ASSERT_EQ("uint32", manager.GetType(5)->str());
|
||||
ASSERT_EQ("float32", manager.GetType(6)->str());
|
||||
|
||||
// Try all combinations of pairs. Expect to be the same type only when the
|
||||
// same id or (1, 4).
|
||||
for (const auto id1 : {1, 2, 3, 4, 7}) {
|
||||
for (const auto id2 : {1, 2, 3, 4, 7}) {
|
||||
if (id1 == id2 || (id1 == 1 && id2 == 4) || (id1 == 4 && id2 == 1)) {
|
||||
EXPECT_TRUE(manager.GetType(id1)->IsSame(manager.GetType(id2)))
|
||||
<< "%struct" << id1 << " is expected to be the same as %struct"
|
||||
<< id2;
|
||||
} else {
|
||||
EXPECT_FALSE(manager.GetType(id1)->IsSame(manager.GetType(id2)))
|
||||
<< "%struct" << id1 << " is expected to be different with %struct"
|
||||
<< id2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Struct, DecorationOnMember) {
|
||||
const std::string text = R"(
|
||||
OpMemberDecorate %struct1 0 Offset 0
|
||||
OpMemberDecorate %struct2 0 Offset 0
|
||||
OpMemberDecorate %struct3 0 Offset 0
|
||||
OpMemberDecorate %struct4 0 Offset 0
|
||||
OpMemberDecorate %struct5 1 Offset 0
|
||||
OpMemberDecorate %struct6 0 Offset 4
|
||||
|
||||
OpDecorate %struct7 Block
|
||||
OpMemberDecorate %struct7 0 Offset 0
|
||||
|
||||
%u32 = OpTypeInt 32 0 ; id: 8
|
||||
%f32 = OpTypeFloat 32 ; id: 9
|
||||
%struct1 = OpTypeStruct %u32 %f32 ; base
|
||||
%struct2 = OpTypeStruct %f32 %u32 ; different member order
|
||||
%struct3 = OpTypeStruct %f32 ; different member list
|
||||
%struct4 = OpTypeStruct %u32 %f32 ; the same
|
||||
%struct5 = OpTypeStruct %u32 %f32 ; member decorate different field
|
||||
%struct6 = OpTypeStruct %u32 %f32 ; different member decoration parameter
|
||||
%struct7 = OpTypeStruct %u32 %f32 ; extra decoration on the struct
|
||||
%struct10 = OpTypeStruct %u32 %f32 ; no member decoration
|
||||
)";
|
||||
opt::analysis::TypeManager manager;
|
||||
std::unique_ptr<ir::Module> module =
|
||||
SpvTools(SPV_ENV_UNIVERSAL_1_1).BuildModule(text);
|
||||
manager.AnalyzeType(*module);
|
||||
|
||||
ASSERT_EQ(10u, manager.NumTypes());
|
||||
ASSERT_EQ(0u, manager.NumForwardPointers());
|
||||
// Make sure we get ids correct.
|
||||
ASSERT_EQ("uint32", manager.GetType(8)->str());
|
||||
ASSERT_EQ("float32", manager.GetType(9)->str());
|
||||
|
||||
// Try all combinations of pairs. Expect to be the same type only when the
|
||||
// same id or (1, 4).
|
||||
for (const auto id1 : {1, 2, 3, 4, 5, 6, 7, 10}) {
|
||||
for (const auto id2 : {1, 2, 3, 4, 5, 6, 7, 10}) {
|
||||
if (id1 == id2 || (id1 == 1 && id2 == 4) || (id1 == 4 && id2 == 1)) {
|
||||
EXPECT_TRUE(manager.GetType(id1)->IsSame(manager.GetType(id2)))
|
||||
<< "%struct" << id1 << " is expected to be the same as %struct"
|
||||
<< id2;
|
||||
} else {
|
||||
EXPECT_FALSE(manager.GetType(id1)->IsSame(manager.GetType(id2)))
|
||||
<< "%struct" << id1 << " is expected to be different with %struct"
|
||||
<< id2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
Loading…
Reference in New Issue
Block a user