Add ability to clone types.
This CL adds a `Clone` method into the type base classes. This allows the IR to clone types provided by the program into the IR context. Bug: tint:1718 Change-Id: Ieebf011dcf40bedc98bf5acebd3888acfde863bc Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/116362 Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: Dan Sinclair <dsinclair@chromium.org> Reviewed-by: Ben Clayton <bclayton@google.com>
This commit is contained in:
parent
0300dd0813
commit
f8abdc7aef
|
@ -563,6 +563,7 @@ libtint_source_set("libtint_core_all_src") {
|
|||
"type/array_count.h",
|
||||
"type/atomic.h",
|
||||
"type/bool.h",
|
||||
"type/clone_context.h",
|
||||
"type/depth_multisampled_texture.h",
|
||||
"type/depth_texture.h",
|
||||
"type/external_texture.h",
|
||||
|
@ -715,6 +716,7 @@ libtint_source_set("libtint_type_src") {
|
|||
"type/atomic.h",
|
||||
"type/bool.cc",
|
||||
"type/bool.h",
|
||||
"type/clone_context.h",
|
||||
"type/depth_multisampled_texture.cc",
|
||||
"type/depth_multisampled_texture.h",
|
||||
"type/depth_texture.cc",
|
||||
|
|
|
@ -476,6 +476,7 @@ list(APPEND TINT_LIB_SRCS
|
|||
type/atomic.h
|
||||
type/bool.cc
|
||||
type/bool.h
|
||||
type/clone_context.h
|
||||
type/depth_multisampled_texture.cc
|
||||
type/depth_multisampled_texture.h
|
||||
type/depth_texture.cc
|
||||
|
@ -951,7 +952,7 @@ if(TINT_BUILD_TESTS)
|
|||
traits_test.cc
|
||||
transform/transform_test.cc
|
||||
type/array_test.cc
|
||||
type/atomic.cc
|
||||
type/atomic_test.cc
|
||||
type/bool_test.cc
|
||||
type/depth_multisampled_texture_test.cc
|
||||
type/depth_texture_test.cc
|
||||
|
|
|
@ -83,7 +83,9 @@ bool IsConnected(const FlowNode* b) {
|
|||
|
||||
} // namespace
|
||||
|
||||
BuilderImpl::BuilderImpl(const Program* program) : builder(program) {}
|
||||
BuilderImpl::BuilderImpl(const Program* program)
|
||||
: builder(program),
|
||||
type_clone_ctx_{{&program->Symbols()}, {&builder.ir.symbols, &builder.ir.types}} {}
|
||||
|
||||
BuilderImpl::~BuilderImpl() = default;
|
||||
|
||||
|
@ -565,61 +567,63 @@ utils::Result<Value*> BuilderImpl::EmitBinary(const ast::BinaryExpression* expr)
|
|||
}
|
||||
|
||||
auto* sem = builder.ir.program->Sem().Get(expr);
|
||||
auto* ty = sem->Type()->Clone(type_clone_ctx_);
|
||||
|
||||
Binary* instr = nullptr;
|
||||
switch (expr->op) {
|
||||
case ast::BinaryOp::kAnd:
|
||||
instr = builder.And(sem->Type(), lhs.Get(), rhs.Get());
|
||||
instr = builder.And(ty, lhs.Get(), rhs.Get());
|
||||
break;
|
||||
case ast::BinaryOp::kOr:
|
||||
instr = builder.Or(sem->Type(), lhs.Get(), rhs.Get());
|
||||
instr = builder.Or(ty, lhs.Get(), rhs.Get());
|
||||
break;
|
||||
case ast::BinaryOp::kXor:
|
||||
instr = builder.Xor(sem->Type(), lhs.Get(), rhs.Get());
|
||||
instr = builder.Xor(ty, lhs.Get(), rhs.Get());
|
||||
break;
|
||||
case ast::BinaryOp::kLogicalAnd:
|
||||
instr = builder.LogicalAnd(sem->Type(), lhs.Get(), rhs.Get());
|
||||
instr = builder.LogicalAnd(ty, lhs.Get(), rhs.Get());
|
||||
break;
|
||||
case ast::BinaryOp::kLogicalOr:
|
||||
instr = builder.LogicalOr(sem->Type(), lhs.Get(), rhs.Get());
|
||||
instr = builder.LogicalOr(ty, lhs.Get(), rhs.Get());
|
||||
break;
|
||||
case ast::BinaryOp::kEqual:
|
||||
instr = builder.Equal(sem->Type(), lhs.Get(), rhs.Get());
|
||||
instr = builder.Equal(ty, lhs.Get(), rhs.Get());
|
||||
break;
|
||||
case ast::BinaryOp::kNotEqual:
|
||||
instr = builder.NotEqual(sem->Type(), lhs.Get(), rhs.Get());
|
||||
instr = builder.NotEqual(ty, lhs.Get(), rhs.Get());
|
||||
break;
|
||||
case ast::BinaryOp::kLessThan:
|
||||
instr = builder.LessThan(sem->Type(), lhs.Get(), rhs.Get());
|
||||
instr = builder.LessThan(ty, lhs.Get(), rhs.Get());
|
||||
break;
|
||||
case ast::BinaryOp::kGreaterThan:
|
||||
instr = builder.GreaterThan(sem->Type(), lhs.Get(), rhs.Get());
|
||||
instr = builder.GreaterThan(ty, lhs.Get(), rhs.Get());
|
||||
break;
|
||||
case ast::BinaryOp::kLessThanEqual:
|
||||
instr = builder.LessThanEqual(sem->Type(), lhs.Get(), rhs.Get());
|
||||
instr = builder.LessThanEqual(ty, lhs.Get(), rhs.Get());
|
||||
break;
|
||||
case ast::BinaryOp::kGreaterThanEqual:
|
||||
instr = builder.GreaterThanEqual(sem->Type(), lhs.Get(), rhs.Get());
|
||||
instr = builder.GreaterThanEqual(ty, lhs.Get(), rhs.Get());
|
||||
break;
|
||||
case ast::BinaryOp::kShiftLeft:
|
||||
instr = builder.ShiftLeft(sem->Type(), lhs.Get(), rhs.Get());
|
||||
instr = builder.ShiftLeft(ty, lhs.Get(), rhs.Get());
|
||||
break;
|
||||
case ast::BinaryOp::kShiftRight:
|
||||
instr = builder.ShiftRight(sem->Type(), lhs.Get(), rhs.Get());
|
||||
instr = builder.ShiftRight(ty, lhs.Get(), rhs.Get());
|
||||
break;
|
||||
case ast::BinaryOp::kAdd:
|
||||
instr = builder.Add(sem->Type(), lhs.Get(), rhs.Get());
|
||||
instr = builder.Add(ty, lhs.Get(), rhs.Get());
|
||||
break;
|
||||
case ast::BinaryOp::kSubtract:
|
||||
instr = builder.Subtract(sem->Type(), lhs.Get(), rhs.Get());
|
||||
instr = builder.Subtract(ty, lhs.Get(), rhs.Get());
|
||||
break;
|
||||
case ast::BinaryOp::kMultiply:
|
||||
instr = builder.Multiply(sem->Type(), lhs.Get(), rhs.Get());
|
||||
instr = builder.Multiply(ty, lhs.Get(), rhs.Get());
|
||||
break;
|
||||
case ast::BinaryOp::kDivide:
|
||||
instr = builder.Divide(sem->Type(), lhs.Get(), rhs.Get());
|
||||
instr = builder.Divide(ty, lhs.Get(), rhs.Get());
|
||||
break;
|
||||
case ast::BinaryOp::kModulo:
|
||||
instr = builder.Modulo(sem->Type(), lhs.Get(), rhs.Get());
|
||||
instr = builder.Modulo(ty, lhs.Get(), rhs.Get());
|
||||
break;
|
||||
case ast::BinaryOp::kNone:
|
||||
TINT_ICE(IR, diagnostics_) << "missing binary operand type";
|
||||
|
@ -637,7 +641,8 @@ utils::Result<Value*> BuilderImpl::EmitBitcast(const ast::BitcastExpression* exp
|
|||
}
|
||||
|
||||
auto* sem = builder.ir.program->Sem().Get(expr);
|
||||
auto* instr = builder.Bitcast(sem->Type(), val.Get());
|
||||
auto* ty = sem->Type()->Clone(type_clone_ctx_);
|
||||
auto* instr = builder.Bitcast(ty, val.Get());
|
||||
|
||||
current_flow_block->instructions.Push(instr);
|
||||
return instr->Result();
|
||||
|
|
|
@ -212,6 +212,8 @@ class BuilderImpl {
|
|||
/// Map from ast nodes to flow nodes, used to retrieve the flow node for a given AST node.
|
||||
/// Used for testing purposes.
|
||||
std::unordered_map<const ast::Node*, const FlowNode*> ast_to_flow_;
|
||||
|
||||
type::CloneContext type_clone_ctx_;
|
||||
};
|
||||
|
||||
} // namespace tint::ir
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#include "src/tint/ir/function.h"
|
||||
#include "src/tint/ir/instruction.h"
|
||||
#include "src/tint/ir/value.h"
|
||||
#include "src/tint/program_id.h"
|
||||
#include "src/tint/symbol_table.h"
|
||||
#include "src/tint/type/manager.h"
|
||||
#include "src/tint/utils/block_allocator.h"
|
||||
#include "src/tint/utils/result.h"
|
||||
|
@ -68,6 +70,11 @@ class Module {
|
|||
/// (Note, this will probably turn into a utils::Result, just stubbing for now)
|
||||
const Program* ToProgram() const;
|
||||
|
||||
private:
|
||||
/// Program Id required to create other components
|
||||
ProgramID prog_id_;
|
||||
|
||||
public:
|
||||
/// The flow node allocator
|
||||
utils::BlockAllocator<FlowNode> flow_nodes;
|
||||
/// The constant allocator
|
||||
|
@ -87,6 +94,9 @@ class Module {
|
|||
|
||||
/// The type manager for the module
|
||||
type::Manager types;
|
||||
|
||||
/// The symbol table for the module
|
||||
SymbolTable symbols{prog_id_};
|
||||
};
|
||||
|
||||
} // namespace tint::ir
|
||||
|
|
|
@ -63,6 +63,7 @@ class Any final : public Castable<Any, type::Type> {
|
|||
// Stub implementations for type::Type conformance.
|
||||
bool Equals(const type::UniqueNode&) const override { return false; }
|
||||
std::string FriendlyName(const SymbolTable&) const override { return "<any>"; }
|
||||
type::Type* Clone(type::CloneContext&) const override { return nullptr; }
|
||||
};
|
||||
|
||||
/// Number is an 32 bit unsigned integer, which can be in one of three states:
|
||||
|
|
|
@ -35,6 +35,11 @@ std::string NamedOverrideArrayCount::FriendlyName(const SymbolTable& symbols) co
|
|||
return symbols.NameFor(variable->Declaration()->symbol);
|
||||
}
|
||||
|
||||
type::ArrayCount* NamedOverrideArrayCount::Clone(type::CloneContext&) const {
|
||||
TINT_ASSERT(Type, false && "Named override array count clone not available");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UnnamedOverrideArrayCount::UnnamedOverrideArrayCount(const Expression* e)
|
||||
: Base(static_cast<size_t>(TypeInfo::Of<UnnamedOverrideArrayCount>().full_hashcode)), expr(e) {}
|
||||
UnnamedOverrideArrayCount::~UnnamedOverrideArrayCount() = default;
|
||||
|
@ -50,4 +55,9 @@ std::string UnnamedOverrideArrayCount::FriendlyName(const SymbolTable&) const {
|
|||
return "[unnamed override-expression]";
|
||||
}
|
||||
|
||||
type::ArrayCount* UnnamedOverrideArrayCount::Clone(type::CloneContext&) const {
|
||||
TINT_ASSERT(Type, false && "Unnamed override array count clone not available");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace tint::sem
|
||||
|
|
|
@ -44,6 +44,10 @@ class NamedOverrideArrayCount final : public Castable<NamedOverrideArrayCount, t
|
|||
/// @returns the friendly name for this array count
|
||||
std::string FriendlyName(const SymbolTable& symbols) const override;
|
||||
|
||||
/// @param ctx the clone context
|
||||
/// @returns a clone of this type
|
||||
type::ArrayCount* Clone(type::CloneContext& ctx) const override;
|
||||
|
||||
/// The `override` variable.
|
||||
const GlobalVariable* variable;
|
||||
};
|
||||
|
@ -70,6 +74,10 @@ class UnnamedOverrideArrayCount final
|
|||
/// @returns the friendly name for this array count
|
||||
std::string FriendlyName(const SymbolTable& symbols) const override;
|
||||
|
||||
/// @param ctx the clone context
|
||||
/// @returns a clone of this type
|
||||
type::ArrayCount* Clone(type::CloneContext& ctx) const override;
|
||||
|
||||
/// The unnamed override expression.
|
||||
/// Note: Each AST expression gets a unique semantic expression node, so two equivalent AST
|
||||
/// expressions will not result in the same `expr` pointer. This property is important to ensure
|
||||
|
|
|
@ -52,7 +52,7 @@ class SymbolTable {
|
|||
|
||||
/// Returns the symbol for the given `name`
|
||||
/// @param name the name to lookup
|
||||
/// @returns the symbol for the name or symbol::kUndefined if not found.
|
||||
/// @returns the symbol for the name or Symbol() if not found.
|
||||
Symbol Get(const std::string& name) const;
|
||||
|
||||
/// Returns the name for the given symbol
|
||||
|
|
|
@ -32,4 +32,8 @@ std::string AbstractFloat::FriendlyName(const SymbolTable&) const {
|
|||
return "abstract-float";
|
||||
}
|
||||
|
||||
AbstractFloat* AbstractFloat::Clone(CloneContext& ctx) const {
|
||||
return ctx.dst.mgr->Get<AbstractFloat>();
|
||||
}
|
||||
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -38,6 +38,10 @@ class AbstractFloat final : public Castable<AbstractFloat, AbstractNumeric> {
|
|||
/// @param symbols the program's symbol table
|
||||
/// @returns the name for this type when printed in diagnostics.
|
||||
std::string FriendlyName(const SymbolTable& symbols) const override;
|
||||
|
||||
/// @param ctx the clone context
|
||||
/// @returns a clone of this type
|
||||
AbstractFloat* Clone(CloneContext& ctx) const override;
|
||||
};
|
||||
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -33,4 +33,8 @@ std::string AbstractInt::FriendlyName(const SymbolTable&) const {
|
|||
return "abstract-int";
|
||||
}
|
||||
|
||||
AbstractInt* AbstractInt::Clone(CloneContext& ctx) const {
|
||||
return ctx.dst.mgr->Get<AbstractInt>();
|
||||
}
|
||||
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -38,6 +38,10 @@ class AbstractInt final : public Castable<AbstractInt, AbstractNumeric> {
|
|||
/// @param symbols the program's symbol table
|
||||
/// @returns the name for this type when printed in diagnostics.
|
||||
std::string FriendlyName(const SymbolTable& symbols) const override;
|
||||
|
||||
/// @param ctx the clone context
|
||||
/// @returns a clone of this type
|
||||
AbstractInt* Clone(CloneContext& ctx) const override;
|
||||
};
|
||||
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "src/tint/ast/variable.h"
|
||||
#include "src/tint/debug.h"
|
||||
#include "src/tint/symbol_table.h"
|
||||
#include "src/tint/type/manager.h"
|
||||
#include "src/tint/utils/hash.h"
|
||||
|
||||
TINT_INSTANTIATE_TYPEINFO(tint::type::Array);
|
||||
|
@ -103,4 +104,11 @@ uint32_t Array::Size() const {
|
|||
return size_;
|
||||
}
|
||||
|
||||
Array* Array::Clone(CloneContext& ctx) const {
|
||||
auto* elem_ty = element_->Clone(ctx);
|
||||
auto* count = count_->Clone(ctx);
|
||||
|
||||
return ctx.dst.mgr->Get<Array>(elem_ty, count, align_, size_, stride_, implicit_stride_);
|
||||
}
|
||||
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -98,6 +98,10 @@ class Array final : public Castable<Array, Type> {
|
|||
/// declared in WGSL.
|
||||
std::string FriendlyName(const SymbolTable& symbols) const override;
|
||||
|
||||
/// @param ctx the clone context
|
||||
/// @returns a clone of this type
|
||||
Array* Clone(CloneContext& ctx) const override;
|
||||
|
||||
private:
|
||||
Type const* const element_;
|
||||
const ArrayCount* count_;
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
|
||||
#include "src/tint/type/array_count.h"
|
||||
|
||||
#include "src/tint/type/manager.h"
|
||||
|
||||
TINT_INSTANTIATE_TYPEINFO(tint::type::ArrayCount);
|
||||
TINT_INSTANTIATE_TYPEINFO(tint::type::ConstantArrayCount);
|
||||
TINT_INSTANTIATE_TYPEINFO(tint::type::RuntimeArrayCount);
|
||||
|
@ -38,6 +40,10 @@ std::string ConstantArrayCount::FriendlyName(const SymbolTable&) const {
|
|||
return std::to_string(value);
|
||||
}
|
||||
|
||||
ConstantArrayCount* ConstantArrayCount::Clone(CloneContext& ctx) const {
|
||||
return ctx.dst.mgr->Get<ConstantArrayCount>(value);
|
||||
}
|
||||
|
||||
RuntimeArrayCount::RuntimeArrayCount()
|
||||
: Base(static_cast<size_t>(TypeInfo::Of<RuntimeArrayCount>().full_hashcode)) {}
|
||||
RuntimeArrayCount::~RuntimeArrayCount() = default;
|
||||
|
@ -50,4 +56,8 @@ std::string RuntimeArrayCount::FriendlyName(const SymbolTable&) const {
|
|||
return "";
|
||||
}
|
||||
|
||||
RuntimeArrayCount* RuntimeArrayCount::Clone(CloneContext& ctx) const {
|
||||
return ctx.dst.mgr->Get<RuntimeArrayCount>();
|
||||
}
|
||||
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <string>
|
||||
|
||||
#include "src/tint/symbol_table.h"
|
||||
#include "src/tint/type/clone_context.h"
|
||||
#include "src/tint/type/unique_node.h"
|
||||
|
||||
namespace tint::type {
|
||||
|
@ -32,6 +33,10 @@ class ArrayCount : public Castable<ArrayCount, UniqueNode> {
|
|||
/// @returns the friendly name for this array count
|
||||
virtual std::string FriendlyName(const SymbolTable& symbols) const = 0;
|
||||
|
||||
/// @param ctx the clone context
|
||||
/// @returns a clone of this type
|
||||
virtual ArrayCount* Clone(CloneContext& ctx) const = 0;
|
||||
|
||||
protected:
|
||||
/// Constructor
|
||||
/// @param hash the unique hash of the node
|
||||
|
@ -59,6 +64,10 @@ class ConstantArrayCount final : public Castable<ConstantArrayCount, ArrayCount>
|
|||
/// @returns the friendly name for this array count
|
||||
std::string FriendlyName(const SymbolTable& symbols) const override;
|
||||
|
||||
/// @param ctx the clone context
|
||||
/// @returns a clone of this type
|
||||
ConstantArrayCount* Clone(CloneContext& ctx) const override;
|
||||
|
||||
/// The array count constant-expression value.
|
||||
uint32_t value;
|
||||
};
|
||||
|
@ -81,6 +90,10 @@ class RuntimeArrayCount final : public Castable<RuntimeArrayCount, ArrayCount> {
|
|||
/// @param symbols the symbol table
|
||||
/// @returns the friendly name for this array count
|
||||
std::string FriendlyName(const SymbolTable& symbols) const override;
|
||||
|
||||
/// @param ctx the clone context
|
||||
/// @returns a clone of this type
|
||||
RuntimeArrayCount* Clone(CloneContext& ctx) const override;
|
||||
};
|
||||
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -164,5 +164,41 @@ TEST_F(ArrayTest, HasFixedFootprint) {
|
|||
EXPECT_FALSE(runtime_sized->HasFixedFootprint());
|
||||
}
|
||||
|
||||
TEST_F(ArrayTest, CloneSizedArray) {
|
||||
auto* ary = create<Array>(create<U32>(), create<ConstantArrayCount>(2u), 4u, 8u, 32u, 16u);
|
||||
|
||||
type::Manager mgr;
|
||||
type::CloneContext ctx{{nullptr}, {nullptr, &mgr}};
|
||||
|
||||
auto* val = ary->Clone(ctx);
|
||||
|
||||
ASSERT_NE(val, nullptr);
|
||||
EXPECT_TRUE(val->ElemType()->Is<U32>());
|
||||
EXPECT_TRUE(val->Count()->Is<ConstantArrayCount>());
|
||||
EXPECT_EQ(val->Count()->As<ConstantArrayCount>()->value, 2u);
|
||||
EXPECT_EQ(val->Align(), 4u);
|
||||
EXPECT_EQ(val->Size(), 8u);
|
||||
EXPECT_EQ(val->Stride(), 32u);
|
||||
EXPECT_EQ(val->ImplicitStride(), 16u);
|
||||
EXPECT_FALSE(val->IsStrideImplicit());
|
||||
}
|
||||
|
||||
TEST_F(ArrayTest, CloneRuntimeArray) {
|
||||
auto* ary = create<Array>(create<U32>(), create<RuntimeArrayCount>(), 4u, 8u, 32u, 32u);
|
||||
|
||||
type::Manager mgr;
|
||||
type::CloneContext ctx{{nullptr}, {nullptr, &mgr}};
|
||||
|
||||
auto* val = ary->Clone(ctx);
|
||||
ASSERT_NE(val, nullptr);
|
||||
EXPECT_TRUE(val->ElemType()->Is<U32>());
|
||||
EXPECT_TRUE(val->Count()->Is<RuntimeArrayCount>());
|
||||
EXPECT_EQ(val->Align(), 4u);
|
||||
EXPECT_EQ(val->Size(), 8u);
|
||||
EXPECT_EQ(val->Stride(), 32u);
|
||||
EXPECT_EQ(val->ImplicitStride(), 32u);
|
||||
EXPECT_TRUE(val->IsStrideImplicit());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -55,4 +55,9 @@ uint32_t Atomic::Align() const {
|
|||
|
||||
Atomic::~Atomic() = default;
|
||||
|
||||
Atomic* Atomic::Clone(CloneContext& ctx) const {
|
||||
auto* ty = subtype_->Clone(ctx);
|
||||
return ctx.dst.mgr->Get<Atomic>(ty);
|
||||
}
|
||||
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -49,6 +49,10 @@ class Atomic final : public Castable<Atomic, Type> {
|
|||
/// @returns the alignment in bytes of the type.
|
||||
uint32_t Align() const override;
|
||||
|
||||
/// @param ctx the clone context
|
||||
/// @returns a clone of this type
|
||||
Atomic* Clone(CloneContext& ctx) const override;
|
||||
|
||||
private:
|
||||
type::Type const* const subtype_;
|
||||
};
|
||||
|
|
|
@ -50,5 +50,15 @@ TEST_F(AtomicTest, FriendlyName) {
|
|||
EXPECT_EQ(a->FriendlyName(Symbols()), "atomic<i32>");
|
||||
}
|
||||
|
||||
TEST_F(AtomicTest, Clone) {
|
||||
auto* atomic = create<Atomic>(create<I32>());
|
||||
|
||||
type::Manager mgr;
|
||||
type::CloneContext ctx{{nullptr}, {nullptr, &mgr}};
|
||||
|
||||
auto* val = atomic->Clone(ctx);
|
||||
EXPECT_TRUE(val->Type()->Is<I32>());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -46,4 +46,8 @@ uint32_t Bool::Align() const {
|
|||
return 4;
|
||||
}
|
||||
|
||||
Bool* Bool::Clone(CloneContext& ctx) const {
|
||||
return ctx.dst.mgr->Get<Bool>();
|
||||
}
|
||||
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -54,6 +54,10 @@ class Bool final : public Castable<Bool, Type> {
|
|||
/// @note: booleans are not host-sharable, but still may exist in workgroup
|
||||
/// storage.
|
||||
uint32_t Align() const override;
|
||||
|
||||
/// @param ctx the clone context
|
||||
/// @returns a clone of this type
|
||||
Bool* Clone(CloneContext& ctx) const override;
|
||||
};
|
||||
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -44,5 +44,14 @@ TEST_F(BoolTest, FriendlyName) {
|
|||
EXPECT_EQ(b.FriendlyName(Symbols()), "bool");
|
||||
}
|
||||
|
||||
TEST_F(BoolTest, Clone) {
|
||||
auto* a = create<Bool>();
|
||||
type::Manager mgr;
|
||||
type::CloneContext ctx{{nullptr}, {nullptr, &mgr}};
|
||||
|
||||
auto* b = a->Clone(ctx);
|
||||
ASSERT_TRUE(b->Is<Bool>());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
// Copyright 2023 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.
|
||||
|
||||
#ifndef SRC_TINT_TYPE_CLONE_CONTEXT_H_
|
||||
#define SRC_TINT_TYPE_CLONE_CONTEXT_H_
|
||||
|
||||
// Forward Declarations
|
||||
namespace tint {
|
||||
class SymbolTable;
|
||||
} // namespace tint
|
||||
namespace tint::type {
|
||||
class Manager;
|
||||
} // namespace tint::type
|
||||
|
||||
namespace tint::type {
|
||||
|
||||
/// Context information for cloning of types
|
||||
struct CloneContext {
|
||||
/// Source information
|
||||
struct {
|
||||
/// The source symbol table
|
||||
const SymbolTable* st;
|
||||
} src;
|
||||
|
||||
/// Destination information
|
||||
struct {
|
||||
/// The destination symbol table
|
||||
SymbolTable* st;
|
||||
/// The destination type manger
|
||||
Manager* mgr;
|
||||
} dst;
|
||||
};
|
||||
|
||||
} // namespace tint::type
|
||||
|
||||
#endif // SRC_TINT_TYPE_CLONE_CONTEXT_H_
|
|
@ -48,4 +48,8 @@ std::string DepthMultisampledTexture::FriendlyName(const SymbolTable&) const {
|
|||
return out.str();
|
||||
}
|
||||
|
||||
DepthMultisampledTexture* DepthMultisampledTexture::Clone(CloneContext& ctx) const {
|
||||
return ctx.dst.mgr->Get<DepthMultisampledTexture>(dim());
|
||||
}
|
||||
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -39,6 +39,10 @@ class DepthMultisampledTexture final : public Castable<DepthMultisampledTexture,
|
|||
/// @returns the name for this type that closely resembles how it would be
|
||||
/// declared in WGSL.
|
||||
std::string FriendlyName(const SymbolTable& symbols) const override;
|
||||
|
||||
/// @param ctx the clone context
|
||||
/// @returns a clone of this type
|
||||
DepthMultisampledTexture* Clone(CloneContext& ctx) const override;
|
||||
};
|
||||
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -57,5 +57,15 @@ TEST_F(DepthMultisampledTextureTest, FriendlyName) {
|
|||
EXPECT_EQ(d.FriendlyName(Symbols()), "texture_depth_multisampled_2d");
|
||||
}
|
||||
|
||||
TEST_F(DepthMultisampledTextureTest, Clone) {
|
||||
auto* a = create<DepthMultisampledTexture>(ast::TextureDimension::k2d);
|
||||
|
||||
type::Manager mgr;
|
||||
type::CloneContext ctx{{nullptr}, {nullptr, &mgr}};
|
||||
|
||||
auto* dt = a->Clone(ctx);
|
||||
EXPECT_EQ(dt->dim(), ast::TextureDimension::k2d);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -49,4 +49,8 @@ std::string DepthTexture::FriendlyName(const SymbolTable&) const {
|
|||
return out.str();
|
||||
}
|
||||
|
||||
DepthTexture* DepthTexture::Clone(CloneContext& ctx) const {
|
||||
return ctx.dst.mgr->Get<DepthTexture>(dim());
|
||||
}
|
||||
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -39,6 +39,10 @@ class DepthTexture final : public Castable<DepthTexture, Texture> {
|
|||
/// @returns the name for this type that closely resembles how it would be
|
||||
/// declared in WGSL.
|
||||
std::string FriendlyName(const SymbolTable& symbols) const override;
|
||||
|
||||
/// @param ctx the clone context
|
||||
/// @returns a clone of this type
|
||||
DepthTexture* Clone(CloneContext& ctx) const override;
|
||||
};
|
||||
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -69,5 +69,15 @@ TEST_F(DepthTextureTest, FriendlyName) {
|
|||
EXPECT_EQ(d.FriendlyName(Symbols()), "texture_depth_cube");
|
||||
}
|
||||
|
||||
TEST_F(DepthTextureTest, Clone) {
|
||||
auto* a = create<DepthTexture>(ast::TextureDimension::k2d);
|
||||
|
||||
type::Manager mgr;
|
||||
type::CloneContext ctx{{nullptr}, {nullptr, &mgr}};
|
||||
|
||||
auto* dt = a->Clone(ctx);
|
||||
EXPECT_EQ(dt->dim(), ast::TextureDimension::k2d);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -34,4 +34,8 @@ std::string ExternalTexture::FriendlyName(const SymbolTable&) const {
|
|||
return "texture_external";
|
||||
}
|
||||
|
||||
ExternalTexture* ExternalTexture::Clone(CloneContext& ctx) const {
|
||||
return ctx.dst.mgr->Get<ExternalTexture>();
|
||||
}
|
||||
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -38,6 +38,10 @@ class ExternalTexture final : public Castable<ExternalTexture, Texture> {
|
|||
/// @returns the name for this type that closely resembles how it would be
|
||||
/// declared in WGSL.
|
||||
std::string FriendlyName(const SymbolTable& symbols) const override;
|
||||
|
||||
/// @param ctx the clone context
|
||||
/// @returns a clone of this type
|
||||
ExternalTexture* Clone(CloneContext& ctx) const override;
|
||||
};
|
||||
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -66,5 +66,15 @@ TEST_F(ExternalTextureTest, FriendlyName) {
|
|||
EXPECT_EQ(s.FriendlyName(Symbols()), "texture_external");
|
||||
}
|
||||
|
||||
TEST_F(ExternalTextureTest, Clone) {
|
||||
auto* a = create<ExternalTexture>();
|
||||
|
||||
type::Manager mgr;
|
||||
type::CloneContext ctx{{nullptr}, {nullptr, &mgr}};
|
||||
|
||||
auto* b = a->Clone(ctx);
|
||||
ASSERT_TRUE(b->Is<ExternalTexture>());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -46,4 +46,8 @@ uint32_t F16::Align() const {
|
|||
return 2;
|
||||
}
|
||||
|
||||
F16* F16::Clone(CloneContext& ctx) const {
|
||||
return ctx.dst.mgr->Get<F16>();
|
||||
}
|
||||
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -44,6 +44,10 @@ class F16 final : public Castable<F16, Type> {
|
|||
|
||||
/// @returns the alignment in bytes of the type.
|
||||
uint32_t Align() const override;
|
||||
|
||||
/// @param ctx the clone context
|
||||
/// @returns a clone of this type
|
||||
F16* Clone(CloneContext& ctx) const override;
|
||||
};
|
||||
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -44,5 +44,15 @@ TEST_F(F16Test, FriendlyName) {
|
|||
EXPECT_EQ(f.FriendlyName(Symbols()), "f16");
|
||||
}
|
||||
|
||||
TEST_F(F16Test, Clone) {
|
||||
auto* a = create<F16>();
|
||||
|
||||
type::Manager mgr;
|
||||
type::CloneContext ctx{{nullptr}, {nullptr, &mgr}};
|
||||
|
||||
auto* b = a->Clone(ctx);
|
||||
ASSERT_TRUE(b->Is<F16>());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -46,4 +46,8 @@ uint32_t F32::Align() const {
|
|||
return 4;
|
||||
}
|
||||
|
||||
F32* F32::Clone(CloneContext& ctx) const {
|
||||
return ctx.dst.mgr->Get<F32>();
|
||||
}
|
||||
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -44,6 +44,10 @@ class F32 final : public Castable<F32, Type> {
|
|||
|
||||
/// @returns the alignment in bytes of the type.
|
||||
uint32_t Align() const override;
|
||||
|
||||
/// @param ctx the clone context
|
||||
/// @returns a clone of this type
|
||||
F32* Clone(CloneContext& ctx) const override;
|
||||
};
|
||||
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -44,5 +44,15 @@ TEST_F(F32Test, FriendlyName) {
|
|||
EXPECT_EQ(f.FriendlyName(Symbols()), "f32");
|
||||
}
|
||||
|
||||
TEST_F(F32Test, Clone) {
|
||||
auto* a = create<F32>();
|
||||
|
||||
type::Manager mgr;
|
||||
type::CloneContext ctx{{nullptr}, {nullptr, &mgr}};
|
||||
|
||||
auto* b = a->Clone(ctx);
|
||||
ASSERT_TRUE(b->Is<F32>());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -46,4 +46,8 @@ uint32_t I32::Align() const {
|
|||
return 4;
|
||||
}
|
||||
|
||||
I32* I32::Clone(CloneContext& ctx) const {
|
||||
return ctx.dst.mgr->Get<I32>();
|
||||
}
|
||||
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -44,6 +44,10 @@ class I32 final : public Castable<I32, Type> {
|
|||
|
||||
/// @returns the alignment in bytes of the type.
|
||||
uint32_t Align() const override;
|
||||
|
||||
/// @param ctx the clone context
|
||||
/// @returns a clone of this type
|
||||
I32* Clone(CloneContext& ctx) const override;
|
||||
};
|
||||
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -44,5 +44,15 @@ TEST_F(I32Test, FriendlyName) {
|
|||
EXPECT_EQ(i.FriendlyName(Symbols()), "i32");
|
||||
}
|
||||
|
||||
TEST_F(I32Test, Clone) {
|
||||
auto* a = create<I32>();
|
||||
|
||||
type::Manager mgr;
|
||||
type::CloneContext ctx{{nullptr}, {nullptr, &mgr}};
|
||||
|
||||
auto* b = a->Clone(ctx);
|
||||
ASSERT_TRUE(b->Is<I32>());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -17,8 +17,11 @@
|
|||
namespace tint::type {
|
||||
|
||||
Manager::Manager() = default;
|
||||
|
||||
Manager::Manager(Manager&&) = default;
|
||||
|
||||
Manager& Manager::operator=(Manager&& rhs) = default;
|
||||
|
||||
Manager::~Manager() = default;
|
||||
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -66,4 +66,9 @@ uint32_t Matrix::ColumnStride() const {
|
|||
return column_type_->Align();
|
||||
}
|
||||
|
||||
Matrix* Matrix::Clone(CloneContext& ctx) const {
|
||||
auto* col_ty = column_type_->Clone(ctx);
|
||||
return ctx.dst.mgr->Get<Matrix>(col_ty, columns_);
|
||||
}
|
||||
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -66,6 +66,10 @@ class Matrix final : public Castable<Matrix, Type> {
|
|||
/// @returns the number of bytes between columns of the matrix
|
||||
uint32_t ColumnStride() const;
|
||||
|
||||
/// @param ctx the clone context
|
||||
/// @returns a clone of this type
|
||||
Matrix* Clone(CloneContext& ctx) const override;
|
||||
|
||||
private:
|
||||
const Type* const subtype_;
|
||||
const Vector* const column_type_;
|
||||
|
|
|
@ -65,5 +65,17 @@ TEST_F(MatrixTest, FriendlyName) {
|
|||
EXPECT_EQ(m.FriendlyName(Symbols()), "mat2x3<i32>");
|
||||
}
|
||||
|
||||
TEST_F(MatrixTest, Clone) {
|
||||
auto* a = create<Matrix>(create<Vector>(create<I32>(), 3u), 4u);
|
||||
|
||||
type::Manager mgr;
|
||||
type::CloneContext ctx{{nullptr}, {nullptr, &mgr}};
|
||||
|
||||
auto* mat = a->Clone(ctx);
|
||||
EXPECT_TRUE(mat->type()->Is<I32>());
|
||||
EXPECT_EQ(mat->rows(), 3u);
|
||||
EXPECT_EQ(mat->columns(), 4u);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -42,4 +42,9 @@ std::string MultisampledTexture::FriendlyName(const SymbolTable& symbols) const
|
|||
return out.str();
|
||||
}
|
||||
|
||||
MultisampledTexture* MultisampledTexture::Clone(CloneContext& ctx) const {
|
||||
auto* ty = type_->Clone(ctx);
|
||||
return ctx.dst.mgr->Get<MultisampledTexture>(dim(), ty);
|
||||
}
|
||||
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -44,6 +44,10 @@ class MultisampledTexture final : public Castable<MultisampledTexture, Texture>
|
|||
/// declared in WGSL.
|
||||
std::string FriendlyName(const SymbolTable& symbols) const override;
|
||||
|
||||
/// @param ctx the clone context
|
||||
/// @returns a clone of this type
|
||||
MultisampledTexture* Clone(CloneContext& ctx) const override;
|
||||
|
||||
private:
|
||||
const Type* const type_;
|
||||
};
|
||||
|
|
|
@ -81,5 +81,16 @@ TEST_F(MultisampledTextureTest, FriendlyName) {
|
|||
EXPECT_EQ(s.FriendlyName(Symbols()), "texture_multisampled_3d<f32>");
|
||||
}
|
||||
|
||||
TEST_F(MultisampledTextureTest, Clone) {
|
||||
auto* a = create<MultisampledTexture>(ast::TextureDimension::k2d, create<F32>());
|
||||
|
||||
type::Manager mgr;
|
||||
type::CloneContext ctx{{nullptr}, {nullptr, &mgr}};
|
||||
|
||||
auto* mt = a->Clone(ctx);
|
||||
EXPECT_EQ(mt->dim(), ast::TextureDimension::k2d);
|
||||
EXPECT_TRUE(mt->type()->Is<F32>());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -53,4 +53,9 @@ std::string Pointer::FriendlyName(const SymbolTable& symbols) const {
|
|||
|
||||
Pointer::~Pointer() = default;
|
||||
|
||||
Pointer* Pointer::Clone(CloneContext& ctx) const {
|
||||
auto* ty = subtype_->Clone(ctx);
|
||||
return ctx.dst.mgr->Get<Pointer>(ty, address_space_, access_);
|
||||
}
|
||||
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -53,6 +53,10 @@ class Pointer final : public Castable<Pointer, Type> {
|
|||
/// declared in WGSL.
|
||||
std::string FriendlyName(const SymbolTable& symbols) const override;
|
||||
|
||||
/// @param ctx the clone context
|
||||
/// @returns a clone of this type
|
||||
Pointer* Clone(CloneContext& ctx) const override;
|
||||
|
||||
private:
|
||||
Type const* const subtype_;
|
||||
ast::AddressSpace const address_space_;
|
||||
|
|
|
@ -68,5 +68,17 @@ TEST_F(PointerTest, FriendlyNameWithAddressSpace) {
|
|||
EXPECT_EQ(r->FriendlyName(Symbols()), "ptr<workgroup, i32, read>");
|
||||
}
|
||||
|
||||
TEST_F(PointerTest, Clone) {
|
||||
auto* a = create<Pointer>(create<I32>(), ast::AddressSpace::kStorage, ast::Access::kReadWrite);
|
||||
|
||||
type::Manager mgr;
|
||||
type::CloneContext ctx{{nullptr}, {nullptr, &mgr}};
|
||||
|
||||
auto* ptr = a->Clone(ctx);
|
||||
EXPECT_TRUE(ptr->StoreType()->Is<I32>());
|
||||
EXPECT_EQ(ptr->AddressSpace(), ast::AddressSpace::kStorage);
|
||||
EXPECT_EQ(ptr->Access(), ast::Access::kReadWrite);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -52,4 +52,9 @@ std::string Reference::FriendlyName(const SymbolTable& symbols) const {
|
|||
|
||||
Reference::~Reference() = default;
|
||||
|
||||
Reference* Reference::Clone(CloneContext& ctx) const {
|
||||
auto* ty = subtype_->Clone(ctx);
|
||||
return ctx.dst.mgr->Get<Reference>(ty, address_space_, access_);
|
||||
}
|
||||
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -53,6 +53,10 @@ class Reference final : public Castable<Reference, Type> {
|
|||
/// declared in WGSL.
|
||||
std::string FriendlyName(const SymbolTable& symbols) const override;
|
||||
|
||||
/// @param ctx the clone context
|
||||
/// @returns a clone of this type
|
||||
Reference* Clone(CloneContext& ctx) const override;
|
||||
|
||||
private:
|
||||
Type const* const subtype_;
|
||||
ast::AddressSpace const address_space_;
|
||||
|
|
|
@ -78,5 +78,18 @@ TEST_F(ReferenceTest, FriendlyNameWithAddressSpace) {
|
|||
EXPECT_EQ(r->FriendlyName(Symbols()), "ref<workgroup, i32, read>");
|
||||
}
|
||||
|
||||
TEST_F(ReferenceTest, Clone) {
|
||||
auto* a =
|
||||
create<Reference>(create<I32>(), ast::AddressSpace::kStorage, ast::Access::kReadWrite);
|
||||
|
||||
type::Manager mgr;
|
||||
type::CloneContext ctx{{nullptr}, {nullptr, &mgr}};
|
||||
|
||||
auto* ref = a->Clone(ctx);
|
||||
EXPECT_TRUE(ref->StoreType()->Is<I32>());
|
||||
EXPECT_EQ(ref->AddressSpace(), ast::AddressSpace::kStorage);
|
||||
EXPECT_EQ(ref->Access(), ast::Access::kReadWrite);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -41,4 +41,9 @@ std::string SampledTexture::FriendlyName(const SymbolTable& symbols) const {
|
|||
return out.str();
|
||||
}
|
||||
|
||||
SampledTexture* SampledTexture::Clone(CloneContext& ctx) const {
|
||||
auto* ty = type_->Clone(ctx);
|
||||
return ctx.dst.mgr->Get<SampledTexture>(dim(), ty);
|
||||
}
|
||||
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -44,6 +44,10 @@ class SampledTexture final : public Castable<SampledTexture, Texture> {
|
|||
/// declared in WGSL.
|
||||
std::string FriendlyName(const SymbolTable& symbols) const override;
|
||||
|
||||
/// @param ctx the clone context
|
||||
/// @returns a clone of this type
|
||||
SampledTexture* Clone(CloneContext& ctx) const override;
|
||||
|
||||
private:
|
||||
const Type* const type_;
|
||||
};
|
||||
|
|
|
@ -85,5 +85,16 @@ TEST_F(SampledTextureTest, FriendlyName) {
|
|||
EXPECT_EQ(s.FriendlyName(Symbols()), "texture_3d<f32>");
|
||||
}
|
||||
|
||||
TEST_F(SampledTextureTest, Clone) {
|
||||
auto* a = create<SampledTexture>(ast::TextureDimension::kCube, create<F32>());
|
||||
|
||||
type::Manager mgr;
|
||||
type::CloneContext ctx{{nullptr}, {nullptr, &mgr}};
|
||||
|
||||
auto* mt = a->Clone(ctx);
|
||||
EXPECT_EQ(mt->dim(), ast::TextureDimension::kCube);
|
||||
EXPECT_TRUE(mt->type()->Is<F32>());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -37,4 +37,8 @@ std::string Sampler::FriendlyName(const SymbolTable&) const {
|
|||
return kind_ == ast::SamplerKind::kSampler ? "sampler" : "sampler_comparison";
|
||||
}
|
||||
|
||||
Sampler* Sampler::Clone(CloneContext& ctx) const {
|
||||
return ctx.dst.mgr->Get<Sampler>(kind_);
|
||||
}
|
||||
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -47,6 +47,10 @@ class Sampler final : public Castable<Sampler, Type> {
|
|||
/// declared in WGSL.
|
||||
std::string FriendlyName(const SymbolTable& symbols) const override;
|
||||
|
||||
/// @param ctx the clone context
|
||||
/// @returns a clone of this type
|
||||
Sampler* Clone(CloneContext& ctx) const override;
|
||||
|
||||
private:
|
||||
ast::SamplerKind const kind_;
|
||||
};
|
||||
|
|
|
@ -63,5 +63,15 @@ TEST_F(SamplerTest, FriendlyNameComparisonSampler) {
|
|||
EXPECT_EQ(s.FriendlyName(Symbols()), "sampler_comparison");
|
||||
}
|
||||
|
||||
TEST_F(SamplerTest, Clone) {
|
||||
auto* a = create<Sampler>(ast::SamplerKind::kSampler);
|
||||
|
||||
type::Manager mgr;
|
||||
type::CloneContext ctx{{nullptr}, {nullptr, &mgr}};
|
||||
|
||||
auto* mt = a->Clone(ctx);
|
||||
EXPECT_EQ(mt->kind(), ast::SamplerKind::kSampler);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -79,4 +79,9 @@ Type* StorageTexture::SubtypeFor(ast::TexelFormat format, Manager& type_mgr) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
StorageTexture* StorageTexture::Clone(CloneContext& ctx) const {
|
||||
auto* ty = subtype_->Clone(ctx);
|
||||
return ctx.dst.mgr->Get<StorageTexture>(dim(), texel_format_, access_, ty);
|
||||
}
|
||||
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -67,6 +67,10 @@ class StorageTexture final : public Castable<StorageTexture, Texture> {
|
|||
/// @returns the storage texture subtype for the given TexelFormat
|
||||
static Type* SubtypeFor(ast::TexelFormat format, Manager& type_mgr);
|
||||
|
||||
/// @param ctx the clone context
|
||||
/// @returns a clone of this type
|
||||
StorageTexture* Clone(CloneContext& ctx) const override;
|
||||
|
||||
private:
|
||||
ast::TexelFormat const texel_format_;
|
||||
ast::Access const access_;
|
||||
|
|
|
@ -134,5 +134,18 @@ TEST_F(StorageTextureTest, I32) {
|
|||
EXPECT_TRUE(s->As<StorageTexture>()->type()->Is<I32>());
|
||||
}
|
||||
|
||||
TEST_F(StorageTextureTest, Clone) {
|
||||
auto* a = Create(ast::TextureDimension::kCube, ast::TexelFormat::kRgba32Float,
|
||||
ast::Access::kReadWrite);
|
||||
|
||||
type::Manager mgr;
|
||||
type::CloneContext ctx{{nullptr}, {nullptr, &mgr}};
|
||||
|
||||
auto* mt = a->Clone(ctx);
|
||||
EXPECT_EQ(mt->dim(), ast::TextureDimension::kCube);
|
||||
EXPECT_EQ(mt->texel_format(), ast::TexelFormat::kRgba32Float);
|
||||
EXPECT_TRUE(mt->type()->Is<F32>());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <utility>
|
||||
|
||||
#include "src/tint/symbol_table.h"
|
||||
#include "src/tint/type/manager.h"
|
||||
#include "src/tint/utils/hash.h"
|
||||
|
||||
TINT_INSTANTIATE_TYPEINFO(tint::type::Struct);
|
||||
|
@ -160,6 +161,16 @@ std::string Struct::Layout(const tint::SymbolTable& symbols) const {
|
|||
return ss.str();
|
||||
}
|
||||
|
||||
Struct* Struct::Clone(CloneContext& ctx) const {
|
||||
auto sym = ctx.dst.st->Register(ctx.src.st->NameFor(name_));
|
||||
|
||||
utils::Vector<const StructMember*, 4> members;
|
||||
for (const auto& mem : members_) {
|
||||
members.Push(mem->Clone(ctx));
|
||||
}
|
||||
return ctx.dst.mgr->Get<Struct>(source_, sym, members, align_, size_, size_no_padding_);
|
||||
}
|
||||
|
||||
StructMember::StructMember(tint::Source source,
|
||||
Symbol name,
|
||||
const type::Type* type,
|
||||
|
@ -179,4 +190,11 @@ StructMember::StructMember(tint::Source source,
|
|||
|
||||
StructMember::~StructMember() = default;
|
||||
|
||||
StructMember* StructMember::Clone(CloneContext& ctx) const {
|
||||
auto sym = ctx.dst.st->Register(ctx.src.st->NameFor(name_));
|
||||
auto* ty = type_->Clone(ctx);
|
||||
return ctx.dst.mgr->Get<StructMember>(source_, sym, ty, index_, offset_, align_, size_,
|
||||
location_);
|
||||
}
|
||||
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -149,6 +149,10 @@ class Struct : public Castable<Struct, Type> {
|
|||
/// @note only structures returned by builtins may be abstract (e.g. modf, frexp)
|
||||
utils::VectorRef<const Struct*> ConcreteTypes() const { return concrete_types_; }
|
||||
|
||||
/// @param ctx the clone context
|
||||
/// @returns a clone of this type
|
||||
Struct* Clone(CloneContext& ctx) const override;
|
||||
|
||||
private:
|
||||
const tint::Source source_;
|
||||
const Symbol name_;
|
||||
|
@ -216,6 +220,10 @@ class StructMember : public Castable<StructMember, Node> {
|
|||
/// @returns the location, if set
|
||||
std::optional<uint32_t> Location() const { return location_; }
|
||||
|
||||
/// @param ctx the clone context
|
||||
/// @returns a clone of this struct member
|
||||
StructMember* Clone(CloneContext& ctx) const;
|
||||
|
||||
private:
|
||||
const tint::Source source_;
|
||||
const Symbol name_;
|
||||
|
|
|
@ -206,5 +206,47 @@ TEST_F(TypeStructTest, HasFixedFootprint) {
|
|||
EXPECT_FALSE(sem_outer_with_runtime_sized_array->HasFixedFootprint());
|
||||
}
|
||||
|
||||
TEST_F(TypeStructTest, Clone) {
|
||||
auto* s = create<Struct>(
|
||||
Source{}, Sym("my_struct"),
|
||||
utils::Vector{create<StructMember>(Source{}, Sym("b"), create<Vector>(create<F32>(), 3u),
|
||||
0u, 0u, 16u, 12u, std::optional<uint32_t>{2}),
|
||||
create<StructMember>(Source{}, Sym("a"), create<I32>(), 1u, 16u, 4u, 4u,
|
||||
std::optional<uint32_t>())},
|
||||
4u /* align */, 8u /* size */, 16u /* size_no_padding */);
|
||||
|
||||
ProgramID id;
|
||||
SymbolTable new_st{id};
|
||||
|
||||
type::Manager mgr;
|
||||
type::CloneContext ctx{{&Symbols()}, {&new_st, &mgr}};
|
||||
|
||||
auto* st = s->Clone(ctx);
|
||||
|
||||
EXPECT_TRUE(new_st.Get("my_struct").IsValid());
|
||||
EXPECT_EQ(new_st.NameFor(st->Name()), "my_struct");
|
||||
|
||||
EXPECT_EQ(st->Align(), 4u);
|
||||
EXPECT_EQ(st->Size(), 8u);
|
||||
EXPECT_EQ(st->SizeNoPadding(), 16u);
|
||||
|
||||
auto members = st->Members();
|
||||
ASSERT_EQ(members.Length(), 2u);
|
||||
|
||||
EXPECT_EQ(new_st.NameFor(members[0]->Name()), "b");
|
||||
EXPECT_TRUE(members[0]->Type()->Is<Vector>());
|
||||
EXPECT_EQ(members[0]->Index(), 0u);
|
||||
EXPECT_EQ(members[0]->Offset(), 0u);
|
||||
EXPECT_EQ(members[0]->Align(), 16u);
|
||||
EXPECT_EQ(members[0]->Size(), 12u);
|
||||
|
||||
EXPECT_EQ(new_st.NameFor(members[1]->Name()), "a");
|
||||
EXPECT_TRUE(members[1]->Type()->Is<I32>());
|
||||
EXPECT_EQ(members[1]->Index(), 1u);
|
||||
EXPECT_EQ(members[1]->Offset(), 16u);
|
||||
EXPECT_EQ(members[1]->Align(), 4u);
|
||||
EXPECT_EQ(members[1]->Size(), 4u);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
#include "src/tint/type/clone_context.h"
|
||||
#include "src/tint/type/unique_node.h"
|
||||
#include "src/tint/utils/enum_set.h"
|
||||
#include "src/tint/utils/vector.h"
|
||||
|
@ -72,6 +73,10 @@ class Type : public Castable<Type, UniqueNode> {
|
|||
/// @note opaque types will return a size of 0.
|
||||
virtual uint32_t Align() const;
|
||||
|
||||
/// @param ctx the clone context
|
||||
/// @returns a clone of this type created in the provided context
|
||||
virtual Type* Clone(CloneContext& ctx) const = 0;
|
||||
|
||||
/// @returns the flags on the type
|
||||
type::Flags Flags() { return flags_; }
|
||||
|
||||
|
|
|
@ -46,4 +46,8 @@ uint32_t U32::Align() const {
|
|||
return 4;
|
||||
}
|
||||
|
||||
U32* U32::Clone(CloneContext& ctx) const {
|
||||
return ctx.dst.mgr->Get<U32>();
|
||||
}
|
||||
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -44,6 +44,10 @@ class U32 final : public Castable<U32, Type> {
|
|||
|
||||
/// @returns the alignment in bytes of the type.
|
||||
uint32_t Align() const override;
|
||||
|
||||
/// @param ctx the clone context
|
||||
/// @returns a clone of this type
|
||||
U32* Clone(CloneContext& ctx) const override;
|
||||
};
|
||||
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -44,5 +44,15 @@ TEST_F(U32Test, FriendlyName) {
|
|||
EXPECT_EQ(u.FriendlyName(Symbols()), "u32");
|
||||
}
|
||||
|
||||
TEST_F(U32Test, Clone) {
|
||||
auto* a = create<U32>();
|
||||
|
||||
type::Manager mgr;
|
||||
type::CloneContext ctx{{nullptr}, {nullptr, &mgr}};
|
||||
|
||||
auto* b = a->Clone(ctx);
|
||||
ASSERT_TRUE(b->Is<U32>());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -65,4 +65,9 @@ uint32_t Vector::Align() const {
|
|||
return 0; // Unreachable
|
||||
}
|
||||
|
||||
Vector* Vector::Clone(CloneContext& ctx) const {
|
||||
auto* subtype = subtype_->Clone(ctx);
|
||||
return ctx.dst.mgr->Get<Vector>(subtype, width_);
|
||||
}
|
||||
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -62,6 +62,10 @@ class Vector final : public Castable<Vector, Type> {
|
|||
/// @returns the alignment in bytes of a vector of the given width.
|
||||
static uint32_t AlignOf(uint32_t width);
|
||||
|
||||
/// @param ctx the clone context
|
||||
/// @returns a clone of this type
|
||||
Vector* Clone(CloneContext& ctx) const override;
|
||||
|
||||
private:
|
||||
Type const* const subtype_;
|
||||
const uint32_t width_;
|
||||
|
|
|
@ -59,5 +59,16 @@ TEST_F(VectorTest, FriendlyName) {
|
|||
EXPECT_EQ(v->FriendlyName(Symbols()), "vec3<f32>");
|
||||
}
|
||||
|
||||
TEST_F(VectorTest, Clone) {
|
||||
auto* a = create<Vector>(create<I32>(), 2u);
|
||||
|
||||
type::Manager mgr;
|
||||
type::CloneContext ctx{{nullptr}, {nullptr, &mgr}};
|
||||
|
||||
auto* vec = a->Clone(ctx);
|
||||
EXPECT_TRUE(vec->type()->Is<I32>());
|
||||
EXPECT_EQ(vec->Width(), 2u);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -32,4 +32,8 @@ std::string Void::FriendlyName(const SymbolTable&) const {
|
|||
return "void";
|
||||
}
|
||||
|
||||
Void* Void::Clone(CloneContext& ctx) const {
|
||||
return ctx.dst.mgr->Get<Void>();
|
||||
}
|
||||
|
||||
} // namespace tint::type
|
||||
|
|
|
@ -38,6 +38,10 @@ class Void final : public Castable<Void, Type> {
|
|||
/// @returns the name for this type that closely resembles how it would be
|
||||
/// declared in WGSL.
|
||||
std::string FriendlyName(const SymbolTable& symbols) const override;
|
||||
|
||||
/// @param ctx the clone context
|
||||
/// @returns a clone of this type
|
||||
Void* Clone(CloneContext& ctx) const override;
|
||||
};
|
||||
|
||||
} // namespace tint::type
|
||||
|
|
Loading…
Reference in New Issue