Add optional access to ptr<>

This also completes the work to resolve the access controls for each
storage type.

Fixed: tint:846
Change-Id: Iab24057ec14620a2978ec63c4a91ba12d1bc6e9b
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/53381
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: James Price <jrprice@google.com>
This commit is contained in:
Ben Clayton 2021-06-04 22:17:37 +00:00 committed by Tint LUCI CQ
parent 3db1820f0b
commit 1858854f7e
248 changed files with 7332 additions and 2027 deletions

View File

@ -67,7 +67,7 @@ TEST_F(AstAliasTest, UnwrapAll_TwiceAliasPointerTwiceAlias) {
auto* u32 = create<U32>(); auto* u32 = create<U32>();
auto* a = create<Alias>(Sym("a_type"), u32); auto* a = create<Alias>(Sym("a_type"), u32);
auto* aa = create<Alias>(Sym("aa_type"), a); auto* aa = create<Alias>(Sym("aa_type"), a);
auto* paa = create<Pointer>(aa, StorageClass::kUniform); auto* paa = create<Pointer>(aa, StorageClass::kUniform, Access::kUndefined);
auto* apaa = create<Alias>(Sym("paa_type"), paa); auto* apaa = create<Alias>(Sym("paa_type"), paa);
auto* aapaa = create<Alias>(Sym("aapaa_type"), apaa); auto* aapaa = create<Alias>(Sym("aapaa_type"), apaa);

View File

@ -24,14 +24,19 @@ namespace ast {
Pointer::Pointer(ProgramID program_id, Pointer::Pointer(ProgramID program_id,
const Source& source, const Source& source,
Type* const subtype, Type* const subtype,
ast::StorageClass storage_class) ast::StorageClass storage_class,
ast::Access access)
: Base(program_id, source), : Base(program_id, source),
subtype_(subtype), subtype_(subtype),
storage_class_(storage_class) {} storage_class_(storage_class),
access_(access) {}
std::string Pointer::type_name() const { std::string Pointer::type_name() const {
std::ostringstream out; std::ostringstream out;
out << "__ptr_" << storage_class_ << subtype_->type_name(); out << "__ptr_" << storage_class_ << subtype_->type_name();
if (access_ != ast::Access::kUndefined) {
out << "_" << access_;
}
return out.str(); return out.str();
} }
@ -41,7 +46,11 @@ std::string Pointer::FriendlyName(const SymbolTable& symbols) const {
if (storage_class_ != ast::StorageClass::kNone) { if (storage_class_ != ast::StorageClass::kNone) {
out << storage_class_ << ", "; out << storage_class_ << ", ";
} }
out << subtype_->FriendlyName(symbols) << ">"; out << subtype_->FriendlyName(symbols);
if (access_ != ast::Access::kUndefined) {
out << ", " << access_;
}
out << ">";
return out.str(); return out.str();
} }
@ -53,7 +62,7 @@ Pointer* Pointer::Clone(CloneContext* ctx) const {
// Clone arguments outside of create() call to have deterministic ordering // Clone arguments outside of create() call to have deterministic ordering
auto src = ctx->Clone(source()); auto src = ctx->Clone(source());
auto* ty = ctx->Clone(type()); auto* ty = ctx->Clone(type());
return ctx->dst->create<Pointer>(src, ty, storage_class_); return ctx->dst->create<Pointer>(src, ty, storage_class_, access_);
} }
} // namespace ast } // namespace ast

View File

@ -17,6 +17,7 @@
#include <string> #include <string>
#include "src/ast/access.h"
#include "src/ast/storage_class.h" #include "src/ast/storage_class.h"
#include "src/ast/type.h" #include "src/ast/type.h"
@ -31,19 +32,25 @@ class Pointer : public Castable<Pointer, Type> {
/// @param source the source of this node /// @param source the source of this node
/// @param subtype the pointee type /// @param subtype the pointee type
/// @param storage_class the storage class of the pointer /// @param storage_class the storage class of the pointer
/// @param access the access control of the pointer
Pointer(ProgramID program_id, Pointer(ProgramID program_id,
const Source& source, const Source& source,
Type* const subtype, Type* const subtype,
ast::StorageClass storage_class); ast::StorageClass storage_class,
ast::Access access);
/// Move constructor /// Move constructor
Pointer(Pointer&&); Pointer(Pointer&&);
~Pointer() override; ~Pointer() override;
/// @returns the pointee type /// @returns the pointee type
Type* type() const { return const_cast<Type*>(subtype_); } Type* type() const { return const_cast<Type*>(subtype_); }
/// @returns the storage class of the pointer /// @returns the storage class of the pointer
ast::StorageClass storage_class() const { return storage_class_; } ast::StorageClass storage_class() const { return storage_class_; }
/// @returns the access control of the pointer
ast::Access access() const { return access_; }
/// @returns the name for this type /// @returns the name for this type
std::string type_name() const override; std::string type_name() const override;
@ -60,6 +67,7 @@ class Pointer : public Castable<Pointer, Type> {
private: private:
Type const* const subtype_; Type const* const subtype_;
ast::StorageClass const storage_class_; ast::StorageClass const storage_class_;
ast::Access const access_;
}; };
} // namespace ast } // namespace ast

View File

@ -25,27 +25,37 @@ using AstPointerTest = TestHelper;
TEST_F(AstPointerTest, Creation) { TEST_F(AstPointerTest, Creation) {
auto* i32 = create<I32>(); auto* i32 = create<I32>();
auto* p = create<Pointer>(i32, ast::StorageClass::kStorage); auto* p = create<Pointer>(i32, ast::StorageClass::kStorage, Access::kRead);
EXPECT_EQ(p->type(), i32); EXPECT_EQ(p->type(), i32);
EXPECT_EQ(p->storage_class(), ast::StorageClass::kStorage); EXPECT_EQ(p->storage_class(), ast::StorageClass::kStorage);
EXPECT_EQ(p->access(), Access::kRead);
} }
TEST_F(AstPointerTest, TypeName) { TEST_F(AstPointerTest, TypeName) {
auto* i32 = create<I32>(); auto* i32 = create<I32>();
auto* p = create<Pointer>(i32, ast::StorageClass::kWorkgroup); auto* p =
create<Pointer>(i32, ast::StorageClass::kWorkgroup, Access::kUndefined);
EXPECT_EQ(p->type_name(), "__ptr_workgroup__i32"); EXPECT_EQ(p->type_name(), "__ptr_workgroup__i32");
} }
TEST_F(AstPointerTest, FriendlyNameWithStorageClass) { TEST_F(AstPointerTest, TypeNameWithAccess) {
auto* i32 = create<I32>(); auto* i32 = create<I32>();
auto* p = create<Pointer>(i32, ast::StorageClass::kWorkgroup); auto* p = create<Pointer>(i32, ast::StorageClass::kWorkgroup, Access::kRead);
EXPECT_EQ(p->type_name(), "__ptr_workgroup__i32_read");
}
TEST_F(AstPointerTest, FriendlyName) {
auto* i32 = create<I32>();
auto* p =
create<Pointer>(i32, ast::StorageClass::kWorkgroup, Access::kUndefined);
EXPECT_EQ(p->FriendlyName(Symbols()), "ptr<workgroup, i32>"); EXPECT_EQ(p->FriendlyName(Symbols()), "ptr<workgroup, i32>");
} }
TEST_F(AstPointerTest, FriendlyNameWithoutStorageClass) { TEST_F(AstPointerTest, FriendlyNameWithAccess) {
auto* i32 = create<I32>(); auto* i32 = create<I32>();
auto* p = create<Pointer>(i32, ast::StorageClass::kNone); auto* p =
EXPECT_EQ(p->FriendlyName(Symbols()), "ptr<i32>"); create<Pointer>(i32, ast::StorageClass::kStorage, Access::kReadWrite);
EXPECT_EQ(p->FriendlyName(Symbols()), "ptr<storage, i32, read_write>");
} }
} // namespace } // namespace

View File

@ -431,24 +431,30 @@ const sem::Array* build_array(MatchState& state, const sem::Type* el) {
/* stride_implicit */ 0); /* stride_implicit */ 0);
} }
bool match_ptr(const sem::Type* ty, Number& S, const sem::Type*& T) { bool match_ptr(const sem::Type* ty, Number& S, const sem::Type*& T, Number& A) {
if (ty->Is<Any>()) { if (ty->Is<Any>()) {
S = Number::any; S = Number::any;
T = ty; T = ty;
A = Number::any;
return true; return true;
} }
if (auto* p = ty->As<sem::Pointer>()) { if (auto* p = ty->As<sem::Pointer>()) {
S = Number(static_cast<uint32_t>(p->StorageClass())); S = Number(static_cast<uint32_t>(p->StorageClass()));
T = p->StoreType(); T = p->StoreType();
A = Number(static_cast<uint32_t>(p->Access()));
return true; return true;
} }
return false; return false;
} }
const sem::Pointer* build_ptr(MatchState& state, Number S, const sem::Type* T) { const sem::Pointer* build_ptr(MatchState& state,
Number S,
const sem::Type* T,
Number& A) {
return state.builder.create<sem::Pointer>( return state.builder.create<sem::Pointer>(
T, static_cast<ast::StorageClass>(S.Value())); T, static_cast<ast::StorageClass>(S.Value()),
static_cast<ast::Access>(A.Value()));
} }
bool match_sampler(const sem::Type* ty) { bool match_sampler(const sem::Type* ty) {

File diff suppressed because it is too large Load Diff

View File

@ -196,7 +196,8 @@ TEST_F(IntrinsicTableTest, MismatchBool) {
TEST_F(IntrinsicTableTest, MatchPointer) { TEST_F(IntrinsicTableTest, MatchPointer) {
auto* f32 = create<sem::F32>(); auto* f32 = create<sem::F32>();
auto* ptr = create<sem::Pointer>(f32, ast::StorageClass::kNone); auto* ptr = create<sem::Pointer>(f32, ast::StorageClass::kFunction,
ast::Access::kReadWrite);
auto* result = table->Lookup(IntrinsicType::kModf, {f32, ptr}, Source{}); auto* result = table->Lookup(IntrinsicType::kModf, {f32, ptr}, Source{});
ASSERT_NE(result, nullptr) << Diagnostics().str(); ASSERT_NE(result, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), ""); ASSERT_EQ(Diagnostics().str(), "");
@ -386,9 +387,11 @@ TEST_F(IntrinsicTableTest, MismatchTexture) {
TEST_F(IntrinsicTableTest, ImplicitLoadOnReference) { TEST_F(IntrinsicTableTest, ImplicitLoadOnReference) {
auto* f32 = create<sem::F32>(); auto* f32 = create<sem::F32>();
auto* result = table->Lookup( auto* result =
IntrinsicType::kCos, table->Lookup(IntrinsicType::kCos,
{create<sem::Reference>(f32, ast::StorageClass::kNone)}, Source{}); {create<sem::Reference>(f32, ast::StorageClass::kFunction,
ast::Access::kReadWrite)},
Source{});
ASSERT_NE(result, nullptr) << Diagnostics().str(); ASSERT_NE(result, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), ""); ASSERT_EQ(Diagnostics().str(), "");
EXPECT_THAT(result->Type(), IntrinsicType::kCos); EXPECT_THAT(result->Type(), IntrinsicType::kCos);

View File

@ -74,7 +74,7 @@ type vec3<T>
type vec4<T> type vec4<T>
[[display("vec{N}<{T}>")]] type vec<N: num, T> [[display("vec{N}<{T}>")]] type vec<N: num, T>
[[display("mat{N}x{M}<{T}>")]] type mat<N: num, M: num, T> [[display("mat{N}x{M}<{T}>")]] type mat<N: num, M: num, T>
[[display("ptr<{T}>")]] type ptr<S: storage_class, T> // TODO(crbug.com/tint/846): Add access control [[display("ptr<{T}>")]] type ptr<S: storage_class, T, A: access>
type array<T> type array<T>
type sampler type sampler
type sampler_comparison type sampler_comparison
@ -305,8 +305,8 @@ fn fma(f32, f32, f32) -> f32
fn fma<N: num>(vec<N, f32>, vec<N, f32>, vec<N, f32>) -> vec<N, f32> fn fma<N: num>(vec<N, f32>, vec<N, f32>, vec<N, f32>) -> vec<N, f32>
fn fract(f32) -> f32 fn fract(f32) -> f32
fn fract<N: num>(vec<N, f32>) -> vec<N, f32> fn fract<N: num>(vec<N, f32>) -> vec<N, f32>
fn frexp<T: iu32, S: storage_class>(f32, ptr<S, T>) -> f32 fn frexp<T: iu32, S: storage_class, A: access>(f32, ptr<S, T, A>) -> f32
fn frexp<N: num, T: iu32, S: storage_class>(vec<N, f32>, ptr<S, vec<N, T>>) -> vec<N, f32> fn frexp<N: num, T: iu32, S: storage_class, A: access>(vec<N, f32>, ptr<S, vec<N, T>, A>) -> vec<N, f32>
fn fwidth(f32) -> f32 fn fwidth(f32) -> f32
fn fwidth<N: num>(vec<N, f32>) -> vec<N, f32> fn fwidth<N: num>(vec<N, f32>) -> vec<N, f32>
fn fwidthCoarse(f32) -> f32 fn fwidthCoarse(f32) -> f32
@ -337,8 +337,8 @@ fn min<T: fiu32>(T, T) -> T
fn min<N: num, T: fiu32>(vec<N, T>, vec<N, T>) -> vec<N, T> fn min<N: num, T: fiu32>(vec<N, T>, vec<N, T>) -> vec<N, T>
fn mix(f32, f32, f32) -> f32 fn mix(f32, f32, f32) -> f32
fn mix<N: num>(vec<N, f32>, vec<N, f32>, vec<N, f32>) -> vec<N, f32> fn mix<N: num>(vec<N, f32>, vec<N, f32>, vec<N, f32>) -> vec<N, f32>
fn modf<S: storage_class>(f32, ptr<S, f32>) -> f32 fn modf<S: storage_class, A: access>(f32, ptr<S, f32, A>) -> f32
fn modf<N: num, S: storage_class>(vec<N, f32>, ptr<S, vec<N, f32>>) -> vec<N, f32> fn modf<N: num, S: storage_class, A: access>(vec<N, f32>, ptr<S, vec<N, f32>, A>) -> vec<N, f32>
fn normalize<N: num>(vec<N, f32>) -> vec<N, f32> fn normalize<N: num>(vec<N, f32>) -> vec<N, f32>
fn pack2x16float(vec2<f32>) -> u32 fn pack2x16float(vec2<f32>) -> u32
fn pack2x16snorm(vec2<f32>) -> u32 fn pack2x16snorm(vec2<f32>) -> u32

View File

@ -712,29 +712,35 @@ class ProgramBuilder {
/// @param type the type of the pointer /// @param type the type of the pointer
/// @param storage_class the storage class of the pointer /// @param storage_class the storage class of the pointer
/// @param access the optional access control of the pointer
/// @return the pointer to `type` with the given ast::StorageClass /// @return the pointer to `type` with the given ast::StorageClass
ast::Pointer* pointer(ast::Type* type, ast::Pointer* pointer(ast::Type* type,
ast::StorageClass storage_class) const { ast::StorageClass storage_class,
ast::Access access = ast::Access::kUndefined) const {
type = MaybeCreateTypename(type); type = MaybeCreateTypename(type);
return builder->create<ast::Pointer>(type, storage_class); return builder->create<ast::Pointer>(type, storage_class, access);
} }
/// @param source the Source of the node /// @param source the Source of the node
/// @param type the type of the pointer /// @param type the type of the pointer
/// @param storage_class the storage class of the pointer /// @param storage_class the storage class of the pointer
/// @param access the optional access control of the pointer
/// @return the pointer to `type` with the given ast::StorageClass /// @return the pointer to `type` with the given ast::StorageClass
ast::Pointer* pointer(const Source& source, ast::Pointer* pointer(const Source& source,
ast::Type* type, ast::Type* type,
ast::StorageClass storage_class) const { ast::StorageClass storage_class,
ast::Access access = ast::Access::kUndefined) const {
type = MaybeCreateTypename(type); type = MaybeCreateTypename(type);
return builder->create<ast::Pointer>(source, type, storage_class); return builder->create<ast::Pointer>(source, type, storage_class, access);
} }
/// @param storage_class the storage class of the pointer /// @param storage_class the storage class of the pointer
/// @param access the optional access control of the pointer
/// @return the pointer to type `T` with the given ast::StorageClass. /// @return the pointer to type `T` with the given ast::StorageClass.
template <typename T> template <typename T>
ast::Pointer* pointer(ast::StorageClass storage_class) const { ast::Pointer* pointer(ast::StorageClass storage_class,
return pointer(Of<T>(), storage_class); ast::Access access = ast::Access::kUndefined) const {
return pointer(Of<T>(), storage_class, access);
} }
/// @param kind the kind of sampler /// @param kind the kind of sampler

View File

@ -971,7 +971,7 @@ Expect<ast::Access> ParserImpl::expect_access(const std::string& use) {
if (ident.value == kReadWriteAccess) if (ident.value == kReadWriteAccess)
return {ast::Access::kReadWrite, ident.source}; return {ast::Access::kReadWrite, ident.source};
return add_error(ident.source, "invalid value for access decoration"); return add_error(ident.source, "invalid value for access control");
} }
// variable_qualifier // variable_qualifier
@ -1045,7 +1045,7 @@ Maybe<ast::Alias*> ParserImpl::type_alias() {
// | VEC2 LESS_THAN type_decl GREATER_THAN // | VEC2 LESS_THAN type_decl GREATER_THAN
// | VEC3 LESS_THAN type_decl GREATER_THAN // | VEC3 LESS_THAN type_decl GREATER_THAN
// | VEC4 LESS_THAN type_decl GREATER_THAN // | VEC4 LESS_THAN type_decl GREATER_THAN
// | PTR LESS_THAN storage_class, type_decl GREATER_THAN // | PTR LESS_THAN storage_class, type_decl (COMMA access_mode)? GREATER_THAN
// | array_decoration_list* ARRAY LESS_THAN type_decl COMMA // | array_decoration_list* ARRAY LESS_THAN type_decl COMMA
// INT_LITERAL GREATER_THAN // INT_LITERAL GREATER_THAN
// | array_decoration_list* ARRAY LESS_THAN type_decl // | array_decoration_list* ARRAY LESS_THAN type_decl
@ -1142,20 +1142,32 @@ Expect<ast::Type*> ParserImpl::expect_type(const std::string& use) {
Expect<ast::Type*> ParserImpl::expect_type_decl_pointer(Token t) { Expect<ast::Type*> ParserImpl::expect_type_decl_pointer(Token t) {
const char* use = "ptr declaration"; const char* use = "ptr declaration";
ast::StorageClass storage_class = ast::StorageClass::kNone; auto storage_class = ast::StorageClass::kNone;
auto access = ast::Access::kUndefined;
auto subtype = expect_lt_gt_block(use, [&]() -> Expect<ast::Type*> { auto subtype = expect_lt_gt_block(use, [&]() -> Expect<ast::Type*> {
auto sc = expect_storage_class(use); auto sc = expect_storage_class(use);
if (sc.errored) if (sc.errored) {
return Failure::kErrored; return Failure::kErrored;
}
storage_class = sc.value; storage_class = sc.value;
if (!expect(use, Token::Type::kComma)) if (!expect(use, Token::Type::kComma)) {
return Failure::kErrored; return Failure::kErrored;
}
auto type = expect_type(use); auto type = expect_type(use);
if (type.errored) if (type.errored) {
return Failure::kErrored; return Failure::kErrored;
}
if (match(Token::Type::kComma)) {
auto ac = expect_access("access control");
if (ac.errored) {
return Failure::kErrored;
}
access = ac.value;
}
return type.value; return type.value;
}); });
@ -1165,7 +1177,7 @@ Expect<ast::Type*> ParserImpl::expect_type_decl_pointer(Token t) {
} }
return builder_.ty.pointer(make_source_range_from(t.source()), subtype.value, return builder_.ty.pointer(make_source_range_from(t.source()), subtype.value,
storage_class); storage_class, access);
} }
Expect<ast::Type*> ParserImpl::expect_type_decl_vector(Token t) { Expect<ast::Type*> ParserImpl::expect_type_decl_vector(Token t) {

View File

@ -314,7 +314,7 @@ TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_InvalidAccess) {
EXPECT_EQ(t.value, nullptr); EXPECT_EQ(t.value, nullptr);
EXPECT_FALSE(t.matched); EXPECT_FALSE(t.matched);
EXPECT_TRUE(t.errored); EXPECT_TRUE(t.errored);
EXPECT_EQ(p->error(), "1:30: invalid value for access decoration"); EXPECT_EQ(p->error(), "1:30: invalid value for access control");
} }
TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_MissingType) { TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_MissingType) {

View File

@ -223,6 +223,22 @@ TEST_F(ParserImplTest, TypeDecl_Ptr) {
EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 1u}, {1u, 19u}})); EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 1u}, {1u, 19u}}));
} }
TEST_F(ParserImplTest, TypeDecl_Ptr_WithAccess) {
auto p = parser("ptr<function, f32, read>");
auto t = p->type_decl();
EXPECT_TRUE(t.matched);
EXPECT_FALSE(t.errored);
ASSERT_NE(t.value, nullptr) << p->error();
ASSERT_FALSE(p->has_error());
ASSERT_TRUE(t.value->Is<ast::Pointer>());
auto* ptr = t.value->As<ast::Pointer>();
ASSERT_TRUE(ptr->type()->Is<ast::F32>());
ASSERT_EQ(ptr->storage_class(), ast::StorageClass::kFunction);
ASSERT_EQ(ptr->access(), ast::Access::kRead);
EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 1u}, {1u, 25u}}));
}
TEST_F(ParserImplTest, TypeDecl_Ptr_ToVec) { TEST_F(ParserImplTest, TypeDecl_Ptr_ToVec) {
auto p = parser("ptr<function, vec2<f32>>"); auto p = parser("ptr<function, vec2<f32>>");
auto t = p->type_decl(); auto t = p->type_decl();
@ -252,7 +268,7 @@ TEST_F(ParserImplTest, TypeDecl_Ptr_MissingLessThan) {
ASSERT_EQ(p->error(), "1:5: expected '<' for ptr declaration"); ASSERT_EQ(p->error(), "1:5: expected '<' for ptr declaration");
} }
TEST_F(ParserImplTest, TypeDecl_Ptr_MissingGreaterThan) { TEST_F(ParserImplTest, TypeDecl_Ptr_MissingGreaterThanAfterType) {
auto p = parser("ptr<function, f32"); auto p = parser("ptr<function, f32");
auto t = p->type_decl(); auto t = p->type_decl();
EXPECT_TRUE(t.errored); EXPECT_TRUE(t.errored);
@ -262,7 +278,17 @@ TEST_F(ParserImplTest, TypeDecl_Ptr_MissingGreaterThan) {
ASSERT_EQ(p->error(), "1:18: expected '>' for ptr declaration"); ASSERT_EQ(p->error(), "1:18: expected '>' for ptr declaration");
} }
TEST_F(ParserImplTest, TypeDecl_Ptr_MissingComma) { TEST_F(ParserImplTest, TypeDecl_Ptr_MissingGreaterThanAfterAccess) {
auto p = parser("ptr<function, f32, read");
auto t = p->type_decl();
EXPECT_TRUE(t.errored);
EXPECT_FALSE(t.matched);
ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
ASSERT_EQ(p->error(), "1:24: expected '>' for ptr declaration");
}
TEST_F(ParserImplTest, TypeDecl_Ptr_MissingCommaAfterStorageClass) {
auto p = parser("ptr<function f32>"); auto p = parser("ptr<function f32>");
auto t = p->type_decl(); auto t = p->type_decl();
EXPECT_TRUE(t.errored); EXPECT_TRUE(t.errored);
@ -272,18 +298,18 @@ TEST_F(ParserImplTest, TypeDecl_Ptr_MissingComma) {
ASSERT_EQ(p->error(), "1:14: expected ',' for ptr declaration"); ASSERT_EQ(p->error(), "1:14: expected ',' for ptr declaration");
} }
TEST_F(ParserImplTest, TypeDecl_Ptr_MissingStorageClass) { TEST_F(ParserImplTest, TypeDecl_Ptr_MissingCommaAfterAccess) {
auto p = parser("ptr<, f32>"); auto p = parser("ptr<function, f32 read>");
auto t = p->type_decl(); auto t = p->type_decl();
EXPECT_TRUE(t.errored); EXPECT_TRUE(t.errored);
EXPECT_FALSE(t.matched); EXPECT_FALSE(t.matched);
ASSERT_EQ(t.value, nullptr); ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error()); ASSERT_TRUE(p->has_error());
ASSERT_EQ(p->error(), "1:5: invalid storage class for ptr declaration"); ASSERT_EQ(p->error(), "1:19: expected '>' for ptr declaration");
} }
TEST_F(ParserImplTest, TypeDecl_Ptr_MissingParams) { TEST_F(ParserImplTest, TypeDecl_Ptr_MissingStorageClass) {
auto p = parser("ptr<>"); auto p = parser("ptr<, f32>");
auto t = p->type_decl(); auto t = p->type_decl();
EXPECT_TRUE(t.errored); EXPECT_TRUE(t.errored);
EXPECT_FALSE(t.matched); EXPECT_FALSE(t.matched);
@ -302,6 +328,26 @@ TEST_F(ParserImplTest, TypeDecl_Ptr_MissingType) {
ASSERT_EQ(p->error(), "1:14: invalid type for ptr declaration"); ASSERT_EQ(p->error(), "1:14: invalid type for ptr declaration");
} }
TEST_F(ParserImplTest, TypeDecl_Ptr_MissingAccess) {
auto p = parser("ptr<function, i32, >");
auto t = p->type_decl();
EXPECT_TRUE(t.errored);
EXPECT_FALSE(t.matched);
ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
ASSERT_EQ(p->error(), "1:20: expected identifier for access control");
}
TEST_F(ParserImplTest, TypeDecl_Ptr_MissingParams) {
auto p = parser("ptr<>");
auto t = p->type_decl();
EXPECT_TRUE(t.errored);
EXPECT_FALSE(t.matched);
ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
ASSERT_EQ(p->error(), "1:5: invalid storage class for ptr declaration");
}
TEST_F(ParserImplTest, TypeDecl_Ptr_BadStorageClass) { TEST_F(ParserImplTest, TypeDecl_Ptr_BadStorageClass) {
auto p = parser("ptr<unknown, f32>"); auto p = parser("ptr<unknown, f32>");
auto t = p->type_decl(); auto t = p->type_decl();
@ -322,6 +368,16 @@ TEST_F(ParserImplTest, TypeDecl_Ptr_BadType) {
ASSERT_EQ(p->error(), "1:15: unknown constructed type 'unknown'"); ASSERT_EQ(p->error(), "1:15: unknown constructed type 'unknown'");
} }
TEST_F(ParserImplTest, TypeDecl_Ptr_BadAccess) {
auto p = parser("ptr<function, i32, unknown>");
auto t = p->type_decl();
EXPECT_TRUE(t.errored);
EXPECT_FALSE(t.matched);
ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
ASSERT_EQ(p->error(), "1:20: invalid value for access control");
}
TEST_F(ParserImplTest, TypeDecl_Array) { TEST_F(ParserImplTest, TypeDecl_Array) {
auto p = parser("array<f32, 5>"); auto p = parser("array<f32, 5>");
auto t = p->type_decl(); auto t = p->type_decl();

View File

@ -234,7 +234,7 @@ TEST_F(ParserImplTest, VariableIdentDecl_AccessDecoBadValue_DEPRECATED) {
auto decl = p->expect_variable_ident_decl("test"); auto decl = p->expect_variable_ident_decl("test");
ASSERT_TRUE(p->has_error()); ASSERT_TRUE(p->has_error());
ASSERT_TRUE(decl.errored); ASSERT_TRUE(decl.errored);
ASSERT_EQ(p->error(), "1:19: invalid value for access decoration"); ASSERT_EQ(p->error(), "1:19: invalid value for access control");
} }
// TODO(crbug.com/tint/846): Remove // TODO(crbug.com/tint/846): Remove

View File

@ -849,12 +849,14 @@ TEST_F(ResolverIntrinsicDataTest, Frexp_Error_FirstParamInt) {
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(
"error: no matching call to frexp(i32, ptr<workgroup, i32>)\n\n" r()->error(),
"2 candidate functions:\n" R"(error: no matching call to frexp(i32, ptr<workgroup, i32, read_write>)
" frexp(f32, ptr<T>) -> f32 where: T is i32 or u32\n"
" frexp(vecN<f32>, ptr<vecN<T>>) -> vecN<f32> " 2 candidate functions:
"where: T is i32 or u32\n"); frexp(f32, ptr<T>) -> f32 where: T is i32 or u32
frexp(vecN<f32>, ptr<vecN<T>>) -> vecN<f32> where: T is i32 or u32
)");
} }
TEST_F(ResolverIntrinsicDataTest, Frexp_Error_SecondParamFloatPtr) { TEST_F(ResolverIntrinsicDataTest, Frexp_Error_SecondParamFloatPtr) {
@ -864,12 +866,14 @@ TEST_F(ResolverIntrinsicDataTest, Frexp_Error_SecondParamFloatPtr) {
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(
"error: no matching call to frexp(f32, ptr<workgroup, f32>)\n\n" r()->error(),
"2 candidate functions:\n" R"(error: no matching call to frexp(f32, ptr<workgroup, f32, read_write>)
" frexp(f32, ptr<T>) -> f32 where: T is i32 or u32\n"
" frexp(vecN<f32>, ptr<vecN<T>>) -> vecN<f32> " 2 candidate functions:
"where: T is i32 or u32\n"); frexp(f32, ptr<T>) -> f32 where: T is i32 or u32
frexp(vecN<f32>, ptr<vecN<T>>) -> vecN<f32> where: T is i32 or u32
)");
} }
TEST_F(ResolverIntrinsicDataTest, Frexp_Error_SecondParamNotAPointer) { TEST_F(ResolverIntrinsicDataTest, Frexp_Error_SecondParamNotAPointer) {
@ -895,7 +899,7 @@ TEST_F(ResolverIntrinsicDataTest, Frexp_Error_VectorSizesDontMatch) {
EXPECT_EQ( EXPECT_EQ(
r()->error(), r()->error(),
R"(error: no matching call to frexp(vec2<f32>, ptr<workgroup, vec4<i32>>) R"(error: no matching call to frexp(vec2<f32>, ptr<workgroup, vec4<i32>, read_write>)
2 candidate functions: 2 candidate functions:
frexp(f32, ptr<T>) -> f32 where: T is i32 or u32 frexp(f32, ptr<T>) -> f32 where: T is i32 or u32
@ -933,11 +937,14 @@ TEST_F(ResolverIntrinsicDataTest, Modf_Error_FirstParamInt) {
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(
"error: no matching call to modf(i32, ptr<workgroup, f32>)\n\n" r()->error(),
"2 candidate functions:\n" R"(error: no matching call to modf(i32, ptr<workgroup, f32, read_write>)
" modf(f32, ptr<f32>) -> f32\n"
" modf(vecN<f32>, ptr<vecN<f32>>) -> vecN<f32>\n"); 2 candidate functions:
modf(f32, ptr<f32>) -> f32
modf(vecN<f32>, ptr<vecN<f32>>) -> vecN<f32>
)");
} }
TEST_F(ResolverIntrinsicDataTest, Modf_Error_SecondParamIntPtr) { TEST_F(ResolverIntrinsicDataTest, Modf_Error_SecondParamIntPtr) {
@ -947,11 +954,14 @@ TEST_F(ResolverIntrinsicDataTest, Modf_Error_SecondParamIntPtr) {
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(
"error: no matching call to modf(f32, ptr<workgroup, i32>)\n\n" r()->error(),
"2 candidate functions:\n" R"(error: no matching call to modf(f32, ptr<workgroup, i32, read_write>)
" modf(f32, ptr<f32>) -> f32\n"
" modf(vecN<f32>, ptr<vecN<f32>>) -> vecN<f32>\n"); 2 candidate functions:
modf(f32, ptr<f32>) -> f32
modf(vecN<f32>, ptr<vecN<f32>>) -> vecN<f32>
)");
} }
TEST_F(ResolverIntrinsicDataTest, Modf_Error_SecondParamNotAPointer) { TEST_F(ResolverIntrinsicDataTest, Modf_Error_SecondParamNotAPointer) {
@ -976,7 +986,7 @@ TEST_F(ResolverIntrinsicDataTest, Modf_Error_VectorSizesDontMatch) {
EXPECT_EQ( EXPECT_EQ(
r()->error(), r()->error(),
R"(error: no matching call to modf(vec2<f32>, ptr<workgroup, vec4<f32>>) R"(error: no matching call to modf(vec2<f32>, ptr<workgroup, vec4<f32>, read_write>)
2 candidate functions: 2 candidate functions:
modf(vecN<f32>, ptr<vecN<f32>>) -> vecN<f32> modf(vecN<f32>, ptr<vecN<f32>>) -> vecN<f32>

View File

@ -87,8 +87,8 @@ TEST_F(ResolverIsHostShareable, Matrix) {
} }
TEST_F(ResolverIsHostShareable, Pointer) { TEST_F(ResolverIsHostShareable, Pointer) {
auto* ptr = auto* ptr = create<sem::Pointer>(
create<sem::Pointer>(create<sem::I32>(), ast::StorageClass::kPrivate); create<sem::I32>(), ast::StorageClass::kPrivate, ast::Access::kReadWrite);
EXPECT_FALSE(r()->IsHostShareable(ptr)); EXPECT_FALSE(r()->IsHostShareable(ptr));
} }

View File

@ -62,8 +62,8 @@ TEST_F(ResolverIsStorableTest, Matrix) {
} }
TEST_F(ResolverIsStorableTest, Pointer) { TEST_F(ResolverIsStorableTest, Pointer) {
auto* ptr = auto* ptr = create<sem::Pointer>(
create<sem::Pointer>(create<sem::I32>(), ast::StorageClass::kPrivate); create<sem::I32>(), ast::StorageClass::kPrivate, ast::Access::kReadWrite);
EXPECT_FALSE(r()->IsStorable(ptr)); EXPECT_FALSE(r()->IsStorable(ptr));
} }
@ -95,7 +95,7 @@ TEST_F(ResolverIsStorableTest, Struct_SomeMembersNonStorable) {
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ( EXPECT_EQ(
r()->error(), r()->error(),
R"(error: ptr<private, i32> cannot be used as the type of a structure member)"); R"(error: ptr<private, i32, read_write> cannot be used as the type of a structure member)");
} }
TEST_F(ResolverIsStorableTest, Struct_NestedStorable) { TEST_F(ResolverIsStorableTest, Struct_NestedStorable) {
@ -126,7 +126,7 @@ TEST_F(ResolverIsStorableTest, Struct_NestedNonStorable) {
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ( EXPECT_EQ(
r()->error(), r()->error(),
R"(error: ptr<private, i32> cannot be used as the type of a structure member)"); R"(error: ptr<private, i32, read_write> cannot be used as the type of a structure member)");
} }
} // namespace } // namespace

View File

@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include "src/ast/struct_block_decoration.h"
#include "src/resolver/resolver.h" #include "src/resolver/resolver.h"
#include "src/resolver/resolver_test_helper.h" #include "src/resolver/resolver_test_helper.h"
#include "src/sem/reference_type.h" #include "src/sem/reference_type.h"
@ -57,6 +58,111 @@ TEST_F(ResolverPtrRefTest, AddressOfThenDeref) {
EXPECT_TRUE(TypeOf(expr)->As<sem::Reference>()->StoreType()->Is<sem::I32>()); EXPECT_TRUE(TypeOf(expr)->As<sem::Reference>()->StoreType()->Is<sem::I32>());
} }
TEST_F(ResolverPtrRefTest, DefaultStorageClass) {
// https://gpuweb.github.io/gpuweb/wgsl/#storage-class
auto* buf = Structure("S", {Member("m", ty.i32())},
{create<ast::StructBlockDecoration>()});
auto* function = Var("f", ty.i32());
auto* private_ = Global("p", ty.i32(), ast::StorageClass::kPrivate);
auto* workgroup = Global("w", ty.i32(), ast::StorageClass::kWorkgroup);
auto* uniform = Global("ub", buf, ast::StorageClass::kUniform,
ast::DecorationList{
create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(0),
});
auto* storage = Global("sb", buf, ast::StorageClass::kStorage,
ast::DecorationList{
create<ast::BindingDecoration>(1),
create<ast::GroupDecoration>(0),
});
auto* handle = Global("h", ty.depth_texture(ast::TextureDimension::k2d),
ast::DecorationList{
create<ast::BindingDecoration>(2),
create<ast::GroupDecoration>(0),
});
WrapInFunction(function);
EXPECT_TRUE(r()->Resolve()) << r()->error();
ASSERT_TRUE(TypeOf(function)->Is<sem::Reference>());
ASSERT_TRUE(TypeOf(private_)->Is<sem::Reference>());
ASSERT_TRUE(TypeOf(workgroup)->Is<sem::Reference>());
ASSERT_TRUE(TypeOf(uniform)->Is<sem::Reference>());
ASSERT_TRUE(TypeOf(storage)->Is<sem::Reference>());
ASSERT_TRUE(TypeOf(handle)->Is<sem::Reference>());
EXPECT_EQ(TypeOf(function)->As<sem::Reference>()->Access(),
ast::Access::kReadWrite);
EXPECT_EQ(TypeOf(private_)->As<sem::Reference>()->Access(),
ast::Access::kReadWrite);
EXPECT_EQ(TypeOf(workgroup)->As<sem::Reference>()->Access(),
ast::Access::kReadWrite);
EXPECT_EQ(TypeOf(uniform)->As<sem::Reference>()->Access(),
ast::Access::kRead);
EXPECT_EQ(TypeOf(storage)->As<sem::Reference>()->Access(),
ast::Access::kRead);
EXPECT_EQ(TypeOf(handle)->As<sem::Reference>()->Access(), ast::Access::kRead);
}
TEST_F(ResolverPtrRefTest, ExplicitStorageClass) {
// https://gpuweb.github.io/gpuweb/wgsl/#storage-class
auto* buf = Structure("S", {Member("m", ty.i32())},
{create<ast::StructBlockDecoration>()});
auto* storage =
Global("sb", buf, ast::StorageClass::kStorage, ast::Access::kReadWrite,
ast::DecorationList{
create<ast::BindingDecoration>(1),
create<ast::GroupDecoration>(0),
});
EXPECT_TRUE(r()->Resolve()) << r()->error();
ASSERT_TRUE(TypeOf(storage)->Is<sem::Reference>());
EXPECT_EQ(TypeOf(storage)->As<sem::Reference>()->Access(),
ast::Access::kReadWrite);
}
TEST_F(ResolverPtrRefTest, InheritsAccessFromOriginatingVariable) {
// struct Inner {
// arr: array<i32, 4>;
// }
// [[block]] struct S {
// inner: Inner;
// }
// [[group(0), binding(0)]] var<storage, read_write> s : S;
// fn f() {
// let p = &s.inner.arr[2];
// }
auto* inner = Structure("Inner", {Member("arr", ty.array<i32, 4>())});
auto* buf = Structure("S", {Member("inner", inner)},
{create<ast::StructBlockDecoration>()});
auto* storage =
Global("s", buf, ast::StorageClass::kStorage, ast::Access::kReadWrite,
ast::DecorationList{
create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(0),
});
auto* expr =
IndexAccessor(MemberAccessor(MemberAccessor(storage, "inner"), "arr"), 4);
auto* ptr = Const("p", nullptr, AddressOf(expr));
WrapInFunction(ptr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
ASSERT_TRUE(TypeOf(expr)->Is<sem::Reference>());
ASSERT_TRUE(TypeOf(ptr)->Is<sem::Pointer>());
EXPECT_EQ(TypeOf(expr)->As<sem::Reference>()->Access(),
ast::Access::kReadWrite);
EXPECT_EQ(TypeOf(ptr)->As<sem::Pointer>()->Access(), ast::Access::kReadWrite);
}
} // namespace } // namespace
} // namespace resolver } // namespace resolver
} // namespace tint } // namespace tint

View File

@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include "src/ast/struct_block_decoration.h"
#include "src/resolver/resolver.h" #include "src/resolver/resolver.h"
#include "src/resolver/resolver_test_helper.h" #include "src/resolver/resolver_test_helper.h"
#include "src/sem/reference_type.h" #include "src/sem/reference_type.h"
@ -77,6 +78,42 @@ TEST_F(ResolverPtrRefValidationTest, DerefOfVar) {
"12:34 error: cannot dereference expression of type 'i32'"); "12:34 error: cannot dereference expression of type 'i32'");
} }
TEST_F(ResolverPtrRefValidationTest, InferredAccessMismatch) {
// struct Inner {
// arr: array<i32, 4>;
// }
// [[block]] struct S {
// inner: Inner;
// }
// [[group(0), binding(0)]] var<storage> s : S;
// fn f() {
// let p : pointer<storage, i32, read_write> = &s.inner.arr[2];
// }
auto* inner = Structure("Inner", {Member("arr", ty.array<i32, 4>())});
auto* buf = Structure("S", {Member("inner", inner)},
{create<ast::StructBlockDecoration>()});
auto* storage = Global("s", buf, ast::StorageClass::kStorage,
ast::DecorationList{
create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(0),
});
auto* expr =
IndexAccessor(MemberAccessor(MemberAccessor(storage, "inner"), "arr"), 4);
auto* ptr = Const(
Source{{12, 34}}, "p",
ty.pointer<i32>(ast::StorageClass::kStorage, ast::Access::kReadWrite),
AddressOf(expr));
WrapInFunction(ptr);
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
"12:34 error: cannot initialize let of type "
"'ptr<storage, i32, read_write>' with value of type "
"'ptr<storage, i32, read>'");
}
} // namespace } // namespace
} // namespace resolver } // namespace resolver
} // namespace tint } // namespace tint

View File

@ -307,8 +307,12 @@ sem::Type* Resolver::Type(const ast::Type* ty) {
} }
if (auto* t = ty->As<ast::Pointer>()) { if (auto* t = ty->As<ast::Pointer>()) {
if (auto* el = Type(t->type())) { if (auto* el = Type(t->type())) {
auto access = t->access();
if (access == ast::kUndefined) {
access = DefaultAccessForStorageClass(t->storage_class());
}
return builder_->create<sem::Pointer>(const_cast<sem::Type*>(el), return builder_->create<sem::Pointer>(const_cast<sem::Type*>(el),
t->storage_class()); t->storage_class(), access);
} }
return nullptr; return nullptr;
} }
@ -477,11 +481,17 @@ Resolver::VariableInfo* Resolver::Variable(ast::Variable* var,
} }
} }
auto access = var->declared_access();
if (access == ast::Access::kUndefined) {
access = DefaultAccessForStorageClass(storage_class);
}
auto* type = storage_type; auto* type = storage_type;
if (!var->is_const()) { if (!var->is_const()) {
// Variable declaration. Unlike `let`, `var` has storage. // Variable declaration. Unlike `let`, `var` has storage.
// Variables are always of a reference type to the declared storage type. // Variables are always of a reference type to the declared storage type.
type = builder_->create<sem::Reference>(storage_type, storage_class); type =
builder_->create<sem::Reference>(storage_type, storage_class, access);
} }
if (rhs_type && !ValidateVariableConstructor(var, storage_type, type_name, if (rhs_type && !ValidateVariableConstructor(var, storage_type, type_name,
@ -489,15 +499,6 @@ Resolver::VariableInfo* Resolver::Variable(ast::Variable* var,
return nullptr; return nullptr;
} }
auto access = var->declared_access();
if (access == ast::Access::kUndefined &&
storage_class == ast::StorageClass::kStorage) {
// https://gpuweb.github.io/gpuweb/wgsl/#access-mode-defaults
// For the storage storage class, the access mode is optional, and defaults
// to read.
access = ast::Access::kRead;
}
auto* info = variable_infos_.Create(var, const_cast<sem::Type*>(type), auto* info = variable_infos_.Create(var, const_cast<sem::Type*>(type),
type_name, storage_class, access); type_name, storage_class, access);
variable_to_info_.emplace(var, info); variable_to_info_.emplace(var, info);
@ -505,6 +506,21 @@ Resolver::VariableInfo* Resolver::Variable(ast::Variable* var,
return info; return info;
} }
ast::AccessControl Resolver::DefaultAccessForStorageClass(
ast::StorageClass storage_class) {
// https://gpuweb.github.io/gpuweb/wgsl/#storage-class
switch (storage_class) {
case ast::StorageClass::kStorage:
return ast::Access::kRead;
case ast::StorageClass::kUniform:
case ast::StorageClass::kUniformConstant:
return ast::Access::kRead;
default:
break;
}
return ast::Access::kReadWrite;
}
bool Resolver::ValidateVariableConstructor(const ast::Variable* var, bool Resolver::ValidateVariableConstructor(const ast::Variable* var,
const sem::Type* storage_type, const sem::Type* storage_type,
const std::string& type_name, const std::string& type_name,
@ -1603,7 +1619,8 @@ bool Resolver::ArrayAccessor(ast::ArrayAccessorExpression* expr) {
// If we're extracting from a reference, we return a reference. // If we're extracting from a reference, we return a reference.
if (auto* ref = res->As<sem::Reference>()) { if (auto* ref = res->As<sem::Reference>()) {
ret = builder_->create<sem::Reference>(ret, ref->StorageClass()); ret = builder_->create<sem::Reference>(ret, ref->StorageClass(),
ref->Access());
} }
SetType(expr, ret); SetType(expr, ret);
@ -1959,7 +1976,8 @@ bool Resolver::MemberAccessor(ast::MemberAccessorExpression* expr) {
// If we're extracting from a reference, we return a reference. // If we're extracting from a reference, we return a reference.
if (auto* ref = structure->As<sem::Reference>()) { if (auto* ref = structure->As<sem::Reference>()) {
ret = builder_->create<sem::Reference>(ret, ref->StorageClass()); ret = builder_->create<sem::Reference>(ret, ref->StorageClass(),
ref->Access());
} }
builder_->Sem().Add(expr, builder_->create<sem::StructMemberAccess>( builder_->Sem().Add(expr, builder_->create<sem::StructMemberAccess>(
@ -2028,7 +2046,8 @@ bool Resolver::MemberAccessor(ast::MemberAccessorExpression* expr) {
ret = vec->type(); ret = vec->type();
// If we're extracting from a reference, we return a reference. // If we're extracting from a reference, we return a reference.
if (auto* ref = structure->As<sem::Reference>()) { if (auto* ref = structure->As<sem::Reference>()) {
ret = builder_->create<sem::Reference>(ret, ref->StorageClass()); ret = builder_->create<sem::Reference>(ret, ref->StorageClass(),
ref->Access());
} }
} else { } else {
// The vector will have a number of components equal to the length of // The vector will have a number of components equal to the length of
@ -2291,8 +2310,8 @@ bool Resolver::UnaryOp(ast::UnaryOpExpression* unary) {
case ast::UnaryOp::kAddressOf: case ast::UnaryOp::kAddressOf:
if (auto* ref = expr_type->As<sem::Reference>()) { if (auto* ref = expr_type->As<sem::Reference>()) {
type = builder_->create<sem::Pointer>(ref->StoreType(), type = builder_->create<sem::Pointer>(
ref->StorageClass()); ref->StoreType(), ref->StorageClass(), ref->Access());
} else { } else {
diagnostics_.add_error("cannot take the address of expression", diagnostics_.add_error("cannot take the address of expression",
unary->expr()->source()); unary->expr()->source());
@ -2302,8 +2321,8 @@ bool Resolver::UnaryOp(ast::UnaryOpExpression* unary) {
case ast::UnaryOp::kIndirection: case ast::UnaryOp::kIndirection:
if (auto* ptr = expr_type->As<sem::Pointer>()) { if (auto* ptr = expr_type->As<sem::Pointer>()) {
type = builder_->create<sem::Reference>(ptr->StoreType(), type = builder_->create<sem::Reference>(
ptr->StorageClass()); ptr->StoreType(), ptr->StorageClass(), ptr->Access());
} else { } else {
diagnostics_.add_error("cannot dereference expression of type '" + diagnostics_.add_error("cannot dereference expression of type '" +
TypeNameOf(unary->expr()) + "'", TypeNameOf(unary->expr()) + "'",

View File

@ -319,6 +319,11 @@ class Resolver {
uint32_t& align, uint32_t& align,
uint32_t& size); uint32_t& size);
/// @param storage_class the storage class
/// @returns the default access control for the given storage class
ast::AccessControl DefaultAccessForStorageClass(
ast::StorageClass storage_class);
/// @returns the resolved type of the ast::Expression `expr` /// @returns the resolved type of the ast::Expression `expr`
/// @param expr the expression /// @param expr the expression
sem::Type* TypeOf(const ast::Expression* expr); sem::Type* TypeOf(const ast::Expression* expr);

View File

@ -87,7 +87,8 @@ TEST_P(InferTypeTest_FromConstructorExpression, All) {
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
auto* got = TypeOf(a_ident); auto* got = TypeOf(a_ident);
auto* expected = create<sem::Reference>(params.create_rhs_sem_type(ty), auto* expected = create<sem::Reference>(params.create_rhs_sem_type(ty),
ast::StorageClass::kFunction); ast::StorageClass::kFunction,
ast::Access::kReadWrite);
ASSERT_EQ(got, expected) << "got: " << FriendlyName(got) << "\n" ASSERT_EQ(got, expected) << "got: " << FriendlyName(got) << "\n"
<< "expected: " << FriendlyName(expected) << "\n"; << "expected: " << FriendlyName(expected) << "\n";
} }
@ -141,7 +142,8 @@ TEST_P(InferTypeTest_FromArithmeticExpression, All) {
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
auto* got = TypeOf(a_ident); auto* got = TypeOf(a_ident);
auto* expected = create<sem::Reference>(params.create_rhs_sem_type(ty), auto* expected = create<sem::Reference>(params.create_rhs_sem_type(ty),
ast::StorageClass::kFunction); ast::StorageClass::kFunction,
ast::Access::kReadWrite);
ASSERT_EQ(got, expected) << "got: " << FriendlyName(got) << "\n" ASSERT_EQ(got, expected) << "got: " << FriendlyName(got) << "\n"
<< "expected: " << FriendlyName(expected) << "\n"; << "expected: " << FriendlyName(expected) << "\n";
} }
@ -190,7 +192,8 @@ TEST_P(InferTypeTest_FromCallExpression, All) {
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
auto* got = TypeOf(a_ident); auto* got = TypeOf(a_ident);
auto* expected = create<sem::Reference>(params.create_rhs_sem_type(ty), auto* expected = create<sem::Reference>(params.create_rhs_sem_type(ty),
ast::StorageClass::kFunction); ast::StorageClass::kFunction,
ast::Access::kReadWrite);
ASSERT_EQ(got, expected) << "got: " << FriendlyName(got) << "\n" ASSERT_EQ(got, expected) << "got: " << FriendlyName(got) << "\n"
<< "expected: " << FriendlyName(expected) << "\n"; << "expected: " << FriendlyName(expected) << "\n";
} }

View File

@ -52,7 +52,8 @@ TEST_F(ResolverVarLetValidationTest, VarConstructorNotStorable) {
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"12:34 error: 'ptr<function, i32>' is not storable for assignment"); "12:34 error: 'ptr<function, i32, read_write>' is not storable for "
"assignment");
} }
TEST_F(ResolverVarLetValidationTest, LetConstructorWrongType) { TEST_F(ResolverVarLetValidationTest, LetConstructorWrongType) {

View File

@ -15,18 +15,24 @@
#include "src/sem/pointer_type.h" #include "src/sem/pointer_type.h"
#include "src/program_builder.h" #include "src/program_builder.h"
#include "src/sem/reference_type.h"
TINT_INSTANTIATE_TYPEINFO(tint::sem::Pointer); TINT_INSTANTIATE_TYPEINFO(tint::sem::Pointer);
namespace tint { namespace tint {
namespace sem { namespace sem {
Pointer::Pointer(const Type* subtype, ast::StorageClass storage_class) Pointer::Pointer(const Type* subtype,
: subtype_(subtype), storage_class_(storage_class) {} ast::StorageClass storage_class,
ast::Access access)
: subtype_(subtype), storage_class_(storage_class), access_(access) {
TINT_ASSERT(!subtype->Is<Reference>());
TINT_ASSERT(access != ast::Access::kUndefined);
}
std::string Pointer::type_name() const { std::string Pointer::type_name() const {
std::ostringstream out; std::ostringstream out;
out << "__ptr_" << storage_class_ << subtype_->type_name(); out << "__ptr_" << storage_class_ << subtype_->type_name() << "__" << access_;
return out.str(); return out.str();
} }
@ -36,7 +42,8 @@ std::string Pointer::FriendlyName(const SymbolTable& symbols) const {
if (storage_class_ != ast::StorageClass::kNone) { if (storage_class_ != ast::StorageClass::kNone) {
out << storage_class_ << ", "; out << storage_class_ << ", ";
} }
out << subtype_->FriendlyName(symbols) << ">"; out << subtype_->FriendlyName(symbols) << ", " << access_;
out << ">";
return out.str(); return out.str();
} }

View File

@ -17,6 +17,7 @@
#include <string> #include <string>
#include "src/ast/access.h"
#include "src/ast/storage_class.h" #include "src/ast/storage_class.h"
#include "src/sem/type.h" #include "src/sem/type.h"
@ -29,16 +30,24 @@ class Pointer : public Castable<Pointer, Type> {
/// Constructor /// Constructor
/// @param subtype the pointee type /// @param subtype the pointee type
/// @param storage_class the storage class of the pointer /// @param storage_class the storage class of the pointer
Pointer(const Type* subtype, ast::StorageClass storage_class); /// @param access the resolved access control of the reference
Pointer(const Type* subtype,
ast::StorageClass storage_class,
ast::Access access);
/// Move constructor /// Move constructor
Pointer(Pointer&&); Pointer(Pointer&&);
~Pointer() override; ~Pointer() override;
/// @returns the pointee type /// @returns the pointee type
const Type* StoreType() const { return subtype_; } const Type* StoreType() const { return subtype_; }
/// @returns the storage class of the pointer /// @returns the storage class of the pointer
ast::StorageClass StorageClass() const { return storage_class_; } ast::StorageClass StorageClass() const { return storage_class_; }
/// @returns the access control of the reference
ast::Access Access() const { return access_; }
/// @returns the name for this type /// @returns the name for this type
std::string type_name() const override; std::string type_name() const override;
@ -50,6 +59,7 @@ class Pointer : public Castable<Pointer, Type> {
private: private:
Type const* const subtype_; Type const* const subtype_;
ast::StorageClass const storage_class_; ast::StorageClass const storage_class_;
ast::AccessControl const access_;
}; };
} // namespace sem } // namespace sem

View File

@ -22,24 +22,29 @@ namespace {
using PointerTest = TestHelper; using PointerTest = TestHelper;
TEST_F(PointerTest, Creation) { TEST_F(PointerTest, Creation) {
auto* r = create<Pointer>(create<I32>(), ast::StorageClass::kStorage); auto* r = create<Pointer>(create<I32>(), ast::StorageClass::kStorage,
ast::Access::kReadWrite);
EXPECT_TRUE(r->StoreType()->Is<sem::I32>()); EXPECT_TRUE(r->StoreType()->Is<sem::I32>());
EXPECT_EQ(r->StorageClass(), ast::StorageClass::kStorage); EXPECT_EQ(r->StorageClass(), ast::StorageClass::kStorage);
EXPECT_EQ(r->Access(), ast::Access::kReadWrite);
} }
TEST_F(PointerTest, TypeName) { TEST_F(PointerTest, TypeName) {
auto* r = create<Pointer>(create<I32>(), ast::StorageClass::kWorkgroup); auto* r = create<Pointer>(create<I32>(), ast::StorageClass::kWorkgroup,
EXPECT_EQ(r->type_name(), "__ptr_workgroup__i32"); ast::Access::kReadWrite);
EXPECT_EQ(r->type_name(), "__ptr_workgroup__i32__read_write");
}
TEST_F(PointerTest, FriendlyName) {
auto* r = create<Pointer>(create<I32>(), ast::StorageClass::kNone,
ast::Access::kRead);
EXPECT_EQ(r->FriendlyName(Symbols()), "ptr<i32, read>");
} }
TEST_F(PointerTest, FriendlyNameWithStorageClass) { TEST_F(PointerTest, FriendlyNameWithStorageClass) {
auto* r = create<Pointer>(create<I32>(), ast::StorageClass::kWorkgroup); auto* r = create<Pointer>(create<I32>(), ast::StorageClass::kWorkgroup,
EXPECT_EQ(r->FriendlyName(Symbols()), "ptr<workgroup, i32>"); ast::Access::kRead);
} EXPECT_EQ(r->FriendlyName(Symbols()), "ptr<workgroup, i32, read>");
TEST_F(PointerTest, FriendlyNameWithoutStorageClass) {
auto* r = create<Pointer>(create<I32>(), ast::StorageClass::kNone);
EXPECT_EQ(r->FriendlyName(Symbols()), "ptr<i32>");
} }
} // namespace } // namespace

View File

@ -21,14 +21,17 @@ TINT_INSTANTIATE_TYPEINFO(tint::sem::Reference);
namespace tint { namespace tint {
namespace sem { namespace sem {
Reference::Reference(const Type* subtype, ast::StorageClass storage_class) Reference::Reference(const Type* subtype,
: subtype_(subtype), storage_class_(storage_class) { ast::StorageClass storage_class,
ast::Access access)
: subtype_(subtype), storage_class_(storage_class), access_(access) {
TINT_ASSERT(!subtype->Is<Reference>()); TINT_ASSERT(!subtype->Is<Reference>());
TINT_ASSERT(access != ast::Access::kUndefined);
} }
std::string Reference::type_name() const { std::string Reference::type_name() const {
std::ostringstream out; std::ostringstream out;
out << "__ref_" << storage_class_ << subtype_->type_name(); out << "__ref_" << storage_class_ << subtype_->type_name() << "__" << access_;
return out.str(); return out.str();
} }
@ -38,7 +41,8 @@ std::string Reference::FriendlyName(const SymbolTable& symbols) const {
if (storage_class_ != ast::StorageClass::kNone) { if (storage_class_ != ast::StorageClass::kNone) {
out << storage_class_ << ", "; out << storage_class_ << ", ";
} }
out << subtype_->FriendlyName(symbols) << ">"; out << subtype_->FriendlyName(symbols) << ", " << access_;
out << ">";
return out.str(); return out.str();
} }

View File

@ -17,6 +17,7 @@
#include <string> #include <string>
#include "src/ast/access.h"
#include "src/ast/storage_class.h" #include "src/ast/storage_class.h"
#include "src/sem/type.h" #include "src/sem/type.h"
@ -29,16 +30,24 @@ class Reference : public Castable<Reference, Type> {
/// Constructor /// Constructor
/// @param subtype the pointee type /// @param subtype the pointee type
/// @param storage_class the storage class of the reference /// @param storage_class the storage class of the reference
Reference(const Type* subtype, ast::StorageClass storage_class); /// @param access the resolved access control of the reference
Reference(const Type* subtype,
ast::StorageClass storage_class,
ast::Access access);
/// Move constructor /// Move constructor
Reference(Reference&&); Reference(Reference&&);
~Reference() override; ~Reference() override;
/// @returns the pointee type /// @returns the pointee type
const Type* StoreType() const { return subtype_; } const Type* StoreType() const { return subtype_; }
/// @returns the storage class of the reference /// @returns the storage class of the reference
ast::StorageClass StorageClass() const { return storage_class_; } ast::StorageClass StorageClass() const { return storage_class_; }
/// @returns the resolved access control of the reference.
ast::Access Access() const { return access_; }
/// @returns the name for this type /// @returns the name for this type
std::string type_name() const override; std::string type_name() const override;
@ -50,6 +59,7 @@ class Reference : public Castable<Reference, Type> {
private: private:
Type const* const subtype_; Type const* const subtype_;
ast::StorageClass const storage_class_; ast::StorageClass const storage_class_;
ast::AccessControl const access_;
}; };
} // namespace sem } // namespace sem

View File

@ -22,24 +22,29 @@ namespace {
using ReferenceTest = TestHelper; using ReferenceTest = TestHelper;
TEST_F(ReferenceTest, Creation) { TEST_F(ReferenceTest, Creation) {
auto* r = create<Reference>(create<I32>(), ast::StorageClass::kStorage); auto* r = create<Reference>(create<I32>(), ast::StorageClass::kStorage,
ast::Access::kReadWrite);
EXPECT_TRUE(r->StoreType()->Is<sem::I32>()); EXPECT_TRUE(r->StoreType()->Is<sem::I32>());
EXPECT_EQ(r->StorageClass(), ast::StorageClass::kStorage); EXPECT_EQ(r->StorageClass(), ast::StorageClass::kStorage);
EXPECT_EQ(r->Access(), ast::Access::kReadWrite);
} }
TEST_F(ReferenceTest, TypeName) { TEST_F(ReferenceTest, TypeName) {
auto* r = create<Reference>(create<I32>(), ast::StorageClass::kWorkgroup); auto* r = create<Reference>(create<I32>(), ast::StorageClass::kWorkgroup,
EXPECT_EQ(r->type_name(), "__ref_workgroup__i32"); ast::Access::kReadWrite);
EXPECT_EQ(r->type_name(), "__ref_workgroup__i32__read_write");
}
TEST_F(ReferenceTest, FriendlyName) {
auto* r = create<Reference>(create<I32>(), ast::StorageClass::kNone,
ast::Access::kRead);
EXPECT_EQ(r->FriendlyName(Symbols()), "ref<i32, read>");
} }
TEST_F(ReferenceTest, FriendlyNameWithStorageClass) { TEST_F(ReferenceTest, FriendlyNameWithStorageClass) {
auto* r = create<Reference>(create<I32>(), ast::StorageClass::kWorkgroup); auto* r = create<Reference>(create<I32>(), ast::StorageClass::kWorkgroup,
EXPECT_EQ(r->FriendlyName(Symbols()), "ref<workgroup, i32>"); ast::Access::kRead);
} EXPECT_EQ(r->FriendlyName(Symbols()), "ref<workgroup, i32, read>");
TEST_F(ReferenceTest, FriendlyNameWithoutStorageClass) {
auto* r = create<Reference>(create<I32>(), ast::StorageClass::kNone);
EXPECT_EQ(r->FriendlyName(Symbols()), "ref<i32>");
} }
} // namespace } // namespace

View File

@ -154,7 +154,8 @@ TEST_F(HlslGeneratorImplTest_Type, EmitType_Matrix) {
// TODO(dsinclair): How to annotate as workgroup? // TODO(dsinclair): How to annotate as workgroup?
TEST_F(HlslGeneratorImplTest_Type, DISABLED_EmitType_Pointer) { TEST_F(HlslGeneratorImplTest_Type, DISABLED_EmitType_Pointer) {
auto* f32 = create<sem::F32>(); auto* f32 = create<sem::F32>();
auto* p = create<sem::Pointer>(f32, ast::StorageClass::kWorkgroup); auto* p = create<sem::Pointer>(f32, ast::StorageClass::kWorkgroup,
ast::Access::kReadWrite);
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();

View File

@ -162,7 +162,8 @@ TEST_F(MslGeneratorImplTest, EmitType_Matrix) {
TEST_F(MslGeneratorImplTest, EmitType_Pointer) { TEST_F(MslGeneratorImplTest, EmitType_Pointer) {
auto* f32 = create<sem::F32>(); auto* f32 = create<sem::F32>();
auto* p = create<sem::Pointer>(f32, ast::StorageClass::kWorkgroup); auto* p = create<sem::Pointer>(f32, ast::StorageClass::kWorkgroup,
ast::Access::kReadWrite);
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();

View File

@ -1730,8 +1730,8 @@ uint32_t Builder::GenerateShortCircuitBinaryExpression(
uint32_t Builder::GenerateSplat(uint32_t scalar_id, const sem::Type* vec_type) { uint32_t Builder::GenerateSplat(uint32_t scalar_id, const sem::Type* vec_type) {
// Create a new vector to splat scalar into // Create a new vector to splat scalar into
auto splat_vector = result_op(); auto splat_vector = result_op();
auto* splat_vector_type = auto* splat_vector_type = builder_.create<sem::Pointer>(
builder_.create<sem::Pointer>(vec_type, ast::StorageClass::kFunction); vec_type, ast::StorageClass::kFunction, ast::Access::kReadWrite);
push_function_var( push_function_var(
{Operand::Int(GenerateTypeIfNeeded(splat_vector_type)), splat_vector, {Operand::Int(GenerateTypeIfNeeded(splat_vector_type)), splat_vector,
Operand::Int(ConvertStorageClass(ast::StorageClass::kFunction)), Operand::Int(ConvertStorageClass(ast::StorageClass::kFunction)),
@ -3228,13 +3228,22 @@ uint32_t Builder::GenerateTypeIfNeeded(const sem::Type* type) {
return 0; return 0;
} }
// Pointers and references with differing accesses should not result in a
// different SPIR-V types, so we explicitly ignore the access.
// Pointers and References both map to a SPIR-V pointer type. // Pointers and References both map to a SPIR-V pointer type.
// Transform a Reference to a Pointer to prevent these having duplicated // Transform a Reference to a Pointer to prevent these having duplicated
// definitions in the generated SPIR-V. Note that nested references are not // definitions in the generated SPIR-V. Note that nested pointers and
// legal, so only considering the top-level type is fine. // references are not legal in WGSL, so only considering the top-level type is
// fine.
std::string type_name; std::string type_name;
if (auto* ref = type->As<sem::Reference>()) { if (auto* ptr = type->As<sem::Pointer>()) {
type_name = sem::Pointer(ref->StoreType(), ref->StorageClass()).type_name(); type_name =
sem::Pointer(ptr->StoreType(), ptr->StorageClass(), ast::kReadWrite)
.type_name();
} else if (auto* ref = type->As<sem::Reference>()) {
type_name =
sem::Pointer(ref->StoreType(), ref->StorageClass(), ast::kReadWrite)
.type_name();
} else { } else {
type_name = type->type_name(); type_name = type->type_name();
} }

View File

@ -241,7 +241,8 @@ TEST_F(BuilderTest_Type, ReturnsGeneratedMatrix) {
TEST_F(BuilderTest_Type, GeneratePtr) { TEST_F(BuilderTest_Type, GeneratePtr) {
auto* i32 = create<sem::I32>(); auto* i32 = create<sem::I32>();
auto* ptr = create<sem::Pointer>(i32, ast::StorageClass::kOutput); auto* ptr = create<sem::Pointer>(i32, ast::StorageClass::kOutput,
ast::Access::kReadWrite);
spirv::Builder& b = Build(); spirv::Builder& b = Build();
@ -256,7 +257,8 @@ TEST_F(BuilderTest_Type, GeneratePtr) {
TEST_F(BuilderTest_Type, ReturnsGeneratedPtr) { TEST_F(BuilderTest_Type, ReturnsGeneratedPtr) {
auto* i32 = create<sem::I32>(); auto* i32 = create<sem::I32>();
auto* ptr = create<sem::Pointer>(i32, ast::StorageClass::kOutput); auto* ptr = create<sem::Pointer>(i32, ast::StorageClass::kOutput,
ast::Access::kReadWrite);
spirv::Builder& b = Build(); spirv::Builder& b = Build();

View File

@ -25,6 +25,7 @@
OpDecorate %_arr_int_uint_4 ArrayStride 16 OpDecorate %_arr_int_uint_4 ArrayStride 16
OpDecorate %S Block OpDecorate %S Block
OpMemberDecorate %S 0 Offset 0 OpMemberDecorate %S 0 Offset 0
OpDecorate %src_uniform NonWritable
OpDecorate %src_uniform DescriptorSet 0 OpDecorate %src_uniform DescriptorSet 0
OpDecorate %src_uniform Binding 0 OpDecorate %src_uniform Binding 0
OpDecorate %src_storage DescriptorSet 0 OpDecorate %src_storage DescriptorSet 0

View File

@ -25,6 +25,7 @@
OpDecorate %_arr_int_uint_4 ArrayStride 16 OpDecorate %_arr_int_uint_4 ArrayStride 16
OpDecorate %S Block OpDecorate %S Block
OpMemberDecorate %S 0 Offset 0 OpMemberDecorate %S 0 Offset 0
OpDecorate %src_uniform NonWritable
OpDecorate %src_uniform DescriptorSet 0 OpDecorate %src_uniform DescriptorSet 0
OpDecorate %src_uniform Binding 0 OpDecorate %src_uniform Binding 0
OpDecorate %src_storage DescriptorSet 0 OpDecorate %src_storage DescriptorSet 0

View File

@ -27,6 +27,7 @@
OpDecorate %_arr_int_uint_4 ArrayStride 16 OpDecorate %_arr_int_uint_4 ArrayStride 16
OpDecorate %S Block OpDecorate %S Block
OpMemberDecorate %S 0 Offset 0 OpMemberDecorate %S 0 Offset 0
OpDecorate %src_uniform NonWritable
OpDecorate %src_uniform DescriptorSet 0 OpDecorate %src_uniform DescriptorSet 0
OpDecorate %src_uniform Binding 0 OpDecorate %src_uniform Binding 0
OpDecorate %src_storage DescriptorSet 0 OpDecorate %src_storage DescriptorSet 0

View File

@ -25,6 +25,7 @@
OpDecorate %_arr_int_uint_4 ArrayStride 16 OpDecorate %_arr_int_uint_4 ArrayStride 16
OpDecorate %S Block OpDecorate %S Block
OpMemberDecorate %S 0 Offset 0 OpMemberDecorate %S 0 Offset 0
OpDecorate %src_uniform NonWritable
OpDecorate %src_uniform DescriptorSet 0 OpDecorate %src_uniform DescriptorSet 0
OpDecorate %src_uniform Binding 0 OpDecorate %src_uniform Binding 0
OpDecorate %src_storage DescriptorSet 0 OpDecorate %src_storage DescriptorSet 0

View File

@ -13,7 +13,7 @@ fn main() {
var i : u32 = 0u; var i : u32 = 0u;
loop { loop {
if (i >= b.count) { break; } if (i >= b.count) { break; }
let p : ptr<storage, u32> = &b.data[i]; let p : ptr<storage, u32, read_write> = &b.data[i];
if ((i % 2u) == 0u) { continue; } if ((i % 2u) == 0u) { continue; }
*p = 0u; // Set odd elements of the array to 0 *p = 0u; // Set odd elements of the array to 0
continuing { continuing {

View File

@ -2,6 +2,6 @@
[[group(0), binding(0)]] var<storage, read_write> buf : S; [[group(0), binding(0)]] var<storage, read_write> buf : S;
[[stage(compute)]] fn main() { [[stage(compute)]] fn main() {
let p : ptr<storage, i32> = &buf.a; let p : ptr<storage, i32, read_write> = &buf.a;
*p = 12; *p = 12;
} }

View File

@ -37,6 +37,7 @@
OpMemberDecorate %Uniforms 0 Offset 0 OpMemberDecorate %Uniforms 0 Offset 0
OpMemberDecorate %Uniforms 1 Offset 8 OpMemberDecorate %Uniforms 1 Offset 8
OpMemberDecorate %Uniforms 2 Offset 16 OpMemberDecorate %Uniforms 2 Offset 16
OpDecorate %uniforms NonWritable
OpDecorate %uniforms DescriptorSet 0 OpDecorate %uniforms DescriptorSet 0
OpDecorate %uniforms Binding 3 OpDecorate %uniforms Binding 3
OpDecorate %tint_symbol BuiltIn GlobalInvocationId OpDecorate %tint_symbol BuiltIn GlobalInvocationId

View File

@ -49,6 +49,7 @@
OpDecorate %gl_FragCoord BuiltIn FragCoord OpDecorate %gl_FragCoord BuiltIn FragCoord
OpDecorate %buf0 Block OpDecorate %buf0 Block
OpMemberDecorate %buf0 0 Offset 0 OpMemberDecorate %buf0 0 Offset 0
OpDecorate %x_188 NonWritable
OpDecorate %x_188 DescriptorSet 0 OpDecorate %x_188 DescriptorSet 0
OpDecorate %x_188 Binding 0 OpDecorate %x_188 Binding 0
OpDecorate %x_GLF_color Location 0 OpDecorate %x_GLF_color Location 0

View File

@ -22,23 +22,23 @@
// Do not modify this file directly // Do not modify this file directly
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
fn frexp_4b73e3() { fn frexp_013caa() {
var arg_1: vec4<i32>; var arg_1: vec4<i32>;
var res: vec4<f32> = frexp(vec4<f32>(), &arg_1); var res: vec4<f32> = frexp(vec4<f32>(), &arg_1);
} }
[[stage(vertex)]] [[stage(vertex)]]
fn vertex_main() -> [[builtin(position)]] vec4<f32> { fn vertex_main() -> [[builtin(position)]] vec4<f32> {
frexp_4b73e3(); frexp_013caa();
return vec4<f32>(); return vec4<f32>();
} }
[[stage(fragment)]] [[stage(fragment)]]
fn fragment_main() { fn fragment_main() {
frexp_4b73e3(); frexp_013caa();
} }
[[stage(compute)]] [[stage(compute)]]
fn compute_main() { fn compute_main() {
frexp_4b73e3(); frexp_013caa();
} }

View File

@ -0,0 +1,31 @@
SKIP: FAILED
fn frexp_013caa() {
var arg_1 : vec4<i32>;
var res : vec4<f32> = frexp(vec4<f32>(), &(arg_1));
}
struct tint_symbol {
[[builtin(position)]]
value : vec4<f32>;
};
[[stage(vertex)]]
fn vertex_main() -> tint_symbol {
frexp_013caa();
let tint_symbol_1 : tint_symbol = tint_symbol(vec4<f32>());
return tint_symbol_1;
}
[[stage(fragment)]]
fn fragment_main() {
frexp_013caa();
}
[[stage(compute)]]
fn compute_main() {
frexp_013caa();
}
Failed to generate: error: Unknown builtin method: frexp

View File

@ -0,0 +1,31 @@
SKIP: FAILED
fn frexp_013caa() {
var arg_1 : vec4<i32>;
var res : vec4<f32> = frexp(vec4<f32>(), &(arg_1));
}
struct tint_symbol {
[[builtin(position)]]
value : vec4<f32>;
};
[[stage(vertex)]]
fn vertex_main() -> tint_symbol {
frexp_013caa();
let tint_symbol_1 : tint_symbol = tint_symbol(vec4<f32>());
return tint_symbol_1;
}
[[stage(fragment)]]
fn fragment_main() {
frexp_013caa();
}
[[stage(compute)]]
fn compute_main() {
frexp_013caa();
}
Failed to generate: error: Unknown import method: frexp

View File

@ -13,7 +13,7 @@
OpExecutionMode %compute_main LocalSize 1 1 1 OpExecutionMode %compute_main LocalSize 1 1 1
OpName %tint_pointsize "tint_pointsize" OpName %tint_pointsize "tint_pointsize"
OpName %tint_symbol_1 "tint_symbol_1" OpName %tint_symbol_1 "tint_symbol_1"
OpName %frexp_4b73e3 "frexp_4b73e3" OpName %frexp_013caa "frexp_013caa"
OpName %arg_1 "arg_1" OpName %arg_1 "arg_1"
OpName %res "res" OpName %res "res"
OpName %tint_symbol_2 "tint_symbol_2" OpName %tint_symbol_2 "tint_symbol_2"
@ -40,7 +40,7 @@
%_ptr_Function_v4float = OpTypePointer Function %v4float %_ptr_Function_v4float = OpTypePointer Function %v4float
%23 = OpTypeFunction %void %v4float %23 = OpTypeFunction %void %v4float
%float_1 = OpConstant %float 1 %float_1 = OpConstant %float 1
%frexp_4b73e3 = OpFunction %void None %9 %frexp_013caa = OpFunction %void None %9
%12 = OpLabel %12 = OpLabel
%arg_1 = OpVariable %_ptr_Function_v4int Function %17 %arg_1 = OpVariable %_ptr_Function_v4int Function %17
%res = OpVariable %_ptr_Function_v4float Function %8 %res = OpVariable %_ptr_Function_v4float Function %8
@ -57,17 +57,17 @@
%vertex_main = OpFunction %void None %9 %vertex_main = OpFunction %void None %9
%28 = OpLabel %28 = OpLabel
OpStore %tint_pointsize %float_1 OpStore %tint_pointsize %float_1
%30 = OpFunctionCall %void %frexp_4b73e3 %30 = OpFunctionCall %void %frexp_013caa
%31 = OpFunctionCall %void %tint_symbol_2 %8 %31 = OpFunctionCall %void %tint_symbol_2 %8
OpReturn OpReturn
OpFunctionEnd OpFunctionEnd
%fragment_main = OpFunction %void None %9 %fragment_main = OpFunction %void None %9
%33 = OpLabel %33 = OpLabel
%34 = OpFunctionCall %void %frexp_4b73e3 %34 = OpFunctionCall %void %frexp_013caa
OpReturn OpReturn
OpFunctionEnd OpFunctionEnd
%compute_main = OpFunction %void None %9 %compute_main = OpFunction %void None %9
%36 = OpLabel %36 = OpLabel
%37 = OpFunctionCall %void %frexp_4b73e3 %37 = OpFunctionCall %void %frexp_013caa
OpReturn OpReturn
OpFunctionEnd OpFunctionEnd

View File

@ -1,20 +1,20 @@
fn frexp_4b73e3() { fn frexp_013caa() {
var arg_1 : vec4<i32>; var arg_1 : vec4<i32>;
var res : vec4<f32> = frexp(vec4<f32>(), &(arg_1)); var res : vec4<f32> = frexp(vec4<f32>(), &(arg_1));
} }
[[stage(vertex)]] [[stage(vertex)]]
fn vertex_main() -> [[builtin(position)]] vec4<f32> { fn vertex_main() -> [[builtin(position)]] vec4<f32> {
frexp_4b73e3(); frexp_013caa();
return vec4<f32>(); return vec4<f32>();
} }
[[stage(fragment)]] [[stage(fragment)]]
fn fragment_main() { fn fragment_main() {
frexp_4b73e3(); frexp_013caa();
} }
[[stage(compute)]] [[stage(compute)]]
fn compute_main() { fn compute_main() {
frexp_4b73e3(); frexp_013caa();
} }

View File

@ -22,23 +22,23 @@
// Do not modify this file directly // Do not modify this file directly
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
fn frexp_1d6b62() { fn frexp_15edf3() {
var arg_1: vec2<i32>; var arg_1: vec2<i32>;
var res: vec2<f32> = frexp(vec2<f32>(), &arg_1); var res: vec2<f32> = frexp(vec2<f32>(), &arg_1);
} }
[[stage(vertex)]] [[stage(vertex)]]
fn vertex_main() -> [[builtin(position)]] vec4<f32> { fn vertex_main() -> [[builtin(position)]] vec4<f32> {
frexp_1d6b62(); frexp_15edf3();
return vec4<f32>(); return vec4<f32>();
} }
[[stage(fragment)]] [[stage(fragment)]]
fn fragment_main() { fn fragment_main() {
frexp_1d6b62(); frexp_15edf3();
} }
[[stage(compute)]] [[stage(compute)]]
fn compute_main() { fn compute_main() {
frexp_1d6b62(); frexp_15edf3();
} }

View File

@ -0,0 +1,31 @@
SKIP: FAILED
fn frexp_15edf3() {
var arg_1 : vec2<i32>;
var res : vec2<f32> = frexp(vec2<f32>(), &(arg_1));
}
struct tint_symbol {
[[builtin(position)]]
value : vec4<f32>;
};
[[stage(vertex)]]
fn vertex_main() -> tint_symbol {
frexp_15edf3();
let tint_symbol_1 : tint_symbol = tint_symbol(vec4<f32>());
return tint_symbol_1;
}
[[stage(fragment)]]
fn fragment_main() {
frexp_15edf3();
}
[[stage(compute)]]
fn compute_main() {
frexp_15edf3();
}
Failed to generate: error: Unknown builtin method: frexp

View File

@ -0,0 +1,31 @@
SKIP: FAILED
fn frexp_15edf3() {
var arg_1 : vec2<i32>;
var res : vec2<f32> = frexp(vec2<f32>(), &(arg_1));
}
struct tint_symbol {
[[builtin(position)]]
value : vec4<f32>;
};
[[stage(vertex)]]
fn vertex_main() -> tint_symbol {
frexp_15edf3();
let tint_symbol_1 : tint_symbol = tint_symbol(vec4<f32>());
return tint_symbol_1;
}
[[stage(fragment)]]
fn fragment_main() {
frexp_15edf3();
}
[[stage(compute)]]
fn compute_main() {
frexp_15edf3();
}
Failed to generate: error: Unknown import method: frexp

View File

@ -13,7 +13,7 @@
OpExecutionMode %compute_main LocalSize 1 1 1 OpExecutionMode %compute_main LocalSize 1 1 1
OpName %tint_pointsize "tint_pointsize" OpName %tint_pointsize "tint_pointsize"
OpName %tint_symbol_1 "tint_symbol_1" OpName %tint_symbol_1 "tint_symbol_1"
OpName %frexp_1d6b62 "frexp_1d6b62" OpName %frexp_15edf3 "frexp_15edf3"
OpName %arg_1 "arg_1" OpName %arg_1 "arg_1"
OpName %res "res" OpName %res "res"
OpName %tint_symbol_2 "tint_symbol_2" OpName %tint_symbol_2 "tint_symbol_2"
@ -42,7 +42,7 @@
%_ptr_Function_v2float = OpTypePointer Function %v2float %_ptr_Function_v2float = OpTypePointer Function %v2float
%25 = OpTypeFunction %void %v4float %25 = OpTypeFunction %void %v4float
%float_1 = OpConstant %float 1 %float_1 = OpConstant %float 1
%frexp_1d6b62 = OpFunction %void None %9 %frexp_15edf3 = OpFunction %void None %9
%12 = OpLabel %12 = OpLabel
%arg_1 = OpVariable %_ptr_Function_v2int Function %17 %arg_1 = OpVariable %_ptr_Function_v2int Function %17
%res = OpVariable %_ptr_Function_v2float Function %21 %res = OpVariable %_ptr_Function_v2float Function %21
@ -59,17 +59,17 @@
%vertex_main = OpFunction %void None %9 %vertex_main = OpFunction %void None %9
%30 = OpLabel %30 = OpLabel
OpStore %tint_pointsize %float_1 OpStore %tint_pointsize %float_1
%32 = OpFunctionCall %void %frexp_1d6b62 %32 = OpFunctionCall %void %frexp_15edf3
%33 = OpFunctionCall %void %tint_symbol_2 %8 %33 = OpFunctionCall %void %tint_symbol_2 %8
OpReturn OpReturn
OpFunctionEnd OpFunctionEnd
%fragment_main = OpFunction %void None %9 %fragment_main = OpFunction %void None %9
%35 = OpLabel %35 = OpLabel
%36 = OpFunctionCall %void %frexp_1d6b62 %36 = OpFunctionCall %void %frexp_15edf3
OpReturn OpReturn
OpFunctionEnd OpFunctionEnd
%compute_main = OpFunction %void None %9 %compute_main = OpFunction %void None %9
%38 = OpLabel %38 = OpLabel
%39 = OpFunctionCall %void %frexp_1d6b62 %39 = OpFunctionCall %void %frexp_15edf3
OpReturn OpReturn
OpFunctionEnd OpFunctionEnd

View File

@ -1,20 +1,20 @@
fn frexp_1d6b62() { fn frexp_15edf3() {
var arg_1 : vec2<i32>; var arg_1 : vec2<i32>;
var res : vec2<f32> = frexp(vec2<f32>(), &(arg_1)); var res : vec2<f32> = frexp(vec2<f32>(), &(arg_1));
} }
[[stage(vertex)]] [[stage(vertex)]]
fn vertex_main() -> [[builtin(position)]] vec4<f32> { fn vertex_main() -> [[builtin(position)]] vec4<f32> {
frexp_1d6b62(); frexp_15edf3();
return vec4<f32>(); return vec4<f32>();
} }
[[stage(fragment)]] [[stage(fragment)]]
fn fragment_main() { fn fragment_main() {
frexp_1d6b62(); frexp_15edf3();
} }
[[stage(compute)]] [[stage(compute)]]
fn compute_main() { fn compute_main() {
frexp_1d6b62(); frexp_15edf3();
} }

View File

@ -0,0 +1,44 @@
// Copyright 2021 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.
////////////////////////////////////////////////////////////////////////////////
// File generated by tools/intrinsic-gen
// using the template:
// test/intrinsics/intrinsics.wgsl.tmpl
// and the intrinsic defintion file:
// src/intrinsics.def
//
// Do not modify this file directly
////////////////////////////////////////////////////////////////////////////////
fn frexp_19ab15() {
var arg_1: vec4<i32>;
var res: vec4<f32> = frexp(vec4<f32>(), &arg_1);
}
[[stage(vertex)]]
fn vertex_main() -> [[builtin(position)]] vec4<f32> {
frexp_19ab15();
return vec4<f32>();
}
[[stage(fragment)]]
fn fragment_main() {
frexp_19ab15();
}
[[stage(compute)]]
fn compute_main() {
frexp_19ab15();
}

View File

@ -0,0 +1,31 @@
SKIP: FAILED
fn frexp_19ab15() {
var arg_1 : vec4<i32>;
var res : vec4<f32> = frexp(vec4<f32>(), &(arg_1));
}
struct tint_symbol {
[[builtin(position)]]
value : vec4<f32>;
};
[[stage(vertex)]]
fn vertex_main() -> tint_symbol {
frexp_19ab15();
let tint_symbol_1 : tint_symbol = tint_symbol(vec4<f32>());
return tint_symbol_1;
}
[[stage(fragment)]]
fn fragment_main() {
frexp_19ab15();
}
[[stage(compute)]]
fn compute_main() {
frexp_19ab15();
}
Failed to generate: error: Unknown builtin method: frexp

View File

@ -0,0 +1,31 @@
SKIP: FAILED
fn frexp_19ab15() {
var arg_1 : vec4<i32>;
var res : vec4<f32> = frexp(vec4<f32>(), &(arg_1));
}
struct tint_symbol {
[[builtin(position)]]
value : vec4<f32>;
};
[[stage(vertex)]]
fn vertex_main() -> tint_symbol {
frexp_19ab15();
let tint_symbol_1 : tint_symbol = tint_symbol(vec4<f32>());
return tint_symbol_1;
}
[[stage(fragment)]]
fn fragment_main() {
frexp_19ab15();
}
[[stage(compute)]]
fn compute_main() {
frexp_19ab15();
}
Failed to generate: error: Unknown import method: frexp

View File

@ -0,0 +1,73 @@
; SPIR-V
; Version: 1.3
; Generator: Google Tint Compiler; 0
; Bound: 38
; Schema: 0
OpCapability Shader
%19 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Vertex %vertex_main "vertex_main" %tint_pointsize %tint_symbol_1
OpEntryPoint Fragment %fragment_main "fragment_main"
OpEntryPoint GLCompute %compute_main "compute_main"
OpExecutionMode %fragment_main OriginUpperLeft
OpExecutionMode %compute_main LocalSize 1 1 1
OpName %tint_pointsize "tint_pointsize"
OpName %tint_symbol_1 "tint_symbol_1"
OpName %frexp_19ab15 "frexp_19ab15"
OpName %arg_1 "arg_1"
OpName %res "res"
OpName %tint_symbol_2 "tint_symbol_2"
OpName %tint_symbol "tint_symbol"
OpName %vertex_main "vertex_main"
OpName %fragment_main "fragment_main"
OpName %compute_main "compute_main"
OpDecorate %tint_pointsize BuiltIn PointSize
OpDecorate %tint_symbol_1 BuiltIn Position
%float = OpTypeFloat 32
%_ptr_Output_float = OpTypePointer Output %float
%4 = OpConstantNull %float
%tint_pointsize = OpVariable %_ptr_Output_float Output %4
%v4float = OpTypeVector %float 4
%_ptr_Output_v4float = OpTypePointer Output %v4float
%8 = OpConstantNull %v4float
%tint_symbol_1 = OpVariable %_ptr_Output_v4float Output %8
%void = OpTypeVoid
%9 = OpTypeFunction %void
%int = OpTypeInt 32 1
%v4int = OpTypeVector %int 4
%_ptr_Function_v4int = OpTypePointer Function %v4int
%17 = OpConstantNull %v4int
%_ptr_Function_v4float = OpTypePointer Function %v4float
%23 = OpTypeFunction %void %v4float
%float_1 = OpConstant %float 1
%frexp_19ab15 = OpFunction %void None %9
%12 = OpLabel
%arg_1 = OpVariable %_ptr_Function_v4int Function %17
%res = OpVariable %_ptr_Function_v4float Function %8
%18 = OpExtInst %v4float %19 Frexp %8 %arg_1
OpStore %res %18
OpReturn
OpFunctionEnd
%tint_symbol_2 = OpFunction %void None %23
%tint_symbol = OpFunctionParameter %v4float
%26 = OpLabel
OpStore %tint_symbol_1 %tint_symbol
OpReturn
OpFunctionEnd
%vertex_main = OpFunction %void None %9
%28 = OpLabel
OpStore %tint_pointsize %float_1
%30 = OpFunctionCall %void %frexp_19ab15
%31 = OpFunctionCall %void %tint_symbol_2 %8
OpReturn
OpFunctionEnd
%fragment_main = OpFunction %void None %9
%33 = OpLabel
%34 = OpFunctionCall %void %frexp_19ab15
OpReturn
OpFunctionEnd
%compute_main = OpFunction %void None %9
%36 = OpLabel
%37 = OpFunctionCall %void %frexp_19ab15
OpReturn
OpFunctionEnd

View File

@ -0,0 +1,20 @@
fn frexp_19ab15() {
var arg_1 : vec4<i32>;
var res : vec4<f32> = frexp(vec4<f32>(), &(arg_1));
}
[[stage(vertex)]]
fn vertex_main() -> [[builtin(position)]] vec4<f32> {
frexp_19ab15();
return vec4<f32>();
}
[[stage(fragment)]]
fn fragment_main() {
frexp_19ab15();
}
[[stage(compute)]]
fn compute_main() {
frexp_19ab15();
}

View File

@ -1,24 +0,0 @@
SKIP: FAILED
fn frexp_1d6b62() {
var arg_1 : vec2<i32>;
var res : vec2<f32> = frexp(vec2<f32>(), &(arg_1));
}
[[stage(vertex)]]
fn vertex_main() {
frexp_1d6b62();
}
[[stage(fragment)]]
fn fragment_main() {
frexp_1d6b62();
}
[[stage(compute)]]
fn compute_main() {
frexp_1d6b62();
}
Failed to generate: error: Unknown builtin method: frexp

View File

@ -1,24 +0,0 @@
SKIP: FAILED
fn frexp_1d6b62() {
var arg_1 : vec2<i32>;
var res : vec2<f32> = frexp(vec2<f32>(), &(arg_1));
}
[[stage(vertex)]]
fn vertex_main() {
frexp_1d6b62();
}
[[stage(fragment)]]
fn fragment_main() {
frexp_1d6b62();
}
[[stage(compute)]]
fn compute_main() {
frexp_1d6b62();
}
Failed to generate: error: Unknown import method: frexp

View File

@ -0,0 +1,44 @@
// Copyright 2021 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.
////////////////////////////////////////////////////////////////////////////////
// File generated by tools/intrinsic-gen
// using the template:
// test/intrinsics/intrinsics.wgsl.tmpl
// and the intrinsic defintion file:
// src/intrinsics.def
//
// Do not modify this file directly
////////////////////////////////////////////////////////////////////////////////
fn frexp_2052e9() {
var arg_1: vec4<i32>;
var res: vec4<f32> = frexp(vec4<f32>(), &arg_1);
}
[[stage(vertex)]]
fn vertex_main() -> [[builtin(position)]] vec4<f32> {
frexp_2052e9();
return vec4<f32>();
}
[[stage(fragment)]]
fn fragment_main() {
frexp_2052e9();
}
[[stage(compute)]]
fn compute_main() {
frexp_2052e9();
}

View File

@ -0,0 +1,31 @@
SKIP: FAILED
fn frexp_2052e9() {
var arg_1 : vec4<i32>;
var res : vec4<f32> = frexp(vec4<f32>(), &(arg_1));
}
struct tint_symbol {
[[builtin(position)]]
value : vec4<f32>;
};
[[stage(vertex)]]
fn vertex_main() -> tint_symbol {
frexp_2052e9();
let tint_symbol_1 : tint_symbol = tint_symbol(vec4<f32>());
return tint_symbol_1;
}
[[stage(fragment)]]
fn fragment_main() {
frexp_2052e9();
}
[[stage(compute)]]
fn compute_main() {
frexp_2052e9();
}
Failed to generate: error: Unknown builtin method: frexp

View File

@ -0,0 +1,31 @@
SKIP: FAILED
fn frexp_2052e9() {
var arg_1 : vec4<i32>;
var res : vec4<f32> = frexp(vec4<f32>(), &(arg_1));
}
struct tint_symbol {
[[builtin(position)]]
value : vec4<f32>;
};
[[stage(vertex)]]
fn vertex_main() -> tint_symbol {
frexp_2052e9();
let tint_symbol_1 : tint_symbol = tint_symbol(vec4<f32>());
return tint_symbol_1;
}
[[stage(fragment)]]
fn fragment_main() {
frexp_2052e9();
}
[[stage(compute)]]
fn compute_main() {
frexp_2052e9();
}
Failed to generate: error: Unknown import method: frexp

View File

@ -0,0 +1,73 @@
; SPIR-V
; Version: 1.3
; Generator: Google Tint Compiler; 0
; Bound: 38
; Schema: 0
OpCapability Shader
%19 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Vertex %vertex_main "vertex_main" %tint_pointsize %tint_symbol_1
OpEntryPoint Fragment %fragment_main "fragment_main"
OpEntryPoint GLCompute %compute_main "compute_main"
OpExecutionMode %fragment_main OriginUpperLeft
OpExecutionMode %compute_main LocalSize 1 1 1
OpName %tint_pointsize "tint_pointsize"
OpName %tint_symbol_1 "tint_symbol_1"
OpName %frexp_2052e9 "frexp_2052e9"
OpName %arg_1 "arg_1"
OpName %res "res"
OpName %tint_symbol_2 "tint_symbol_2"
OpName %tint_symbol "tint_symbol"
OpName %vertex_main "vertex_main"
OpName %fragment_main "fragment_main"
OpName %compute_main "compute_main"
OpDecorate %tint_pointsize BuiltIn PointSize
OpDecorate %tint_symbol_1 BuiltIn Position
%float = OpTypeFloat 32
%_ptr_Output_float = OpTypePointer Output %float
%4 = OpConstantNull %float
%tint_pointsize = OpVariable %_ptr_Output_float Output %4
%v4float = OpTypeVector %float 4
%_ptr_Output_v4float = OpTypePointer Output %v4float
%8 = OpConstantNull %v4float
%tint_symbol_1 = OpVariable %_ptr_Output_v4float Output %8
%void = OpTypeVoid
%9 = OpTypeFunction %void
%int = OpTypeInt 32 1
%v4int = OpTypeVector %int 4
%_ptr_Function_v4int = OpTypePointer Function %v4int
%17 = OpConstantNull %v4int
%_ptr_Function_v4float = OpTypePointer Function %v4float
%23 = OpTypeFunction %void %v4float
%float_1 = OpConstant %float 1
%frexp_2052e9 = OpFunction %void None %9
%12 = OpLabel
%arg_1 = OpVariable %_ptr_Function_v4int Function %17
%res = OpVariable %_ptr_Function_v4float Function %8
%18 = OpExtInst %v4float %19 Frexp %8 %arg_1
OpStore %res %18
OpReturn
OpFunctionEnd
%tint_symbol_2 = OpFunction %void None %23
%tint_symbol = OpFunctionParameter %v4float
%26 = OpLabel
OpStore %tint_symbol_1 %tint_symbol
OpReturn
OpFunctionEnd
%vertex_main = OpFunction %void None %9
%28 = OpLabel
OpStore %tint_pointsize %float_1
%30 = OpFunctionCall %void %frexp_2052e9
%31 = OpFunctionCall %void %tint_symbol_2 %8
OpReturn
OpFunctionEnd
%fragment_main = OpFunction %void None %9
%33 = OpLabel
%34 = OpFunctionCall %void %frexp_2052e9
OpReturn
OpFunctionEnd
%compute_main = OpFunction %void None %9
%36 = OpLabel
%37 = OpFunctionCall %void %frexp_2052e9
OpReturn
OpFunctionEnd

View File

@ -0,0 +1,20 @@
fn frexp_2052e9() {
var arg_1 : vec4<i32>;
var res : vec4<f32> = frexp(vec4<f32>(), &(arg_1));
}
[[stage(vertex)]]
fn vertex_main() -> [[builtin(position)]] vec4<f32> {
frexp_2052e9();
return vec4<f32>();
}
[[stage(fragment)]]
fn fragment_main() {
frexp_2052e9();
}
[[stage(compute)]]
fn compute_main() {
frexp_2052e9();
}

View File

@ -22,23 +22,23 @@
// Do not modify this file directly // Do not modify this file directly
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
fn frexp_2507b2() { fn frexp_234f02() {
var arg_1: vec4<u32>; var arg_1: vec4<u32>;
var res: vec4<f32> = frexp(vec4<f32>(), &arg_1); var res: vec4<f32> = frexp(vec4<f32>(), &arg_1);
} }
[[stage(vertex)]] [[stage(vertex)]]
fn vertex_main() -> [[builtin(position)]] vec4<f32> { fn vertex_main() -> [[builtin(position)]] vec4<f32> {
frexp_2507b2(); frexp_234f02();
return vec4<f32>(); return vec4<f32>();
} }
[[stage(fragment)]] [[stage(fragment)]]
fn fragment_main() { fn fragment_main() {
frexp_2507b2(); frexp_234f02();
} }
[[stage(compute)]] [[stage(compute)]]
fn compute_main() { fn compute_main() {
frexp_2507b2(); frexp_234f02();
} }

View File

@ -0,0 +1,31 @@
SKIP: FAILED
fn frexp_234f02() {
var arg_1 : vec4<u32>;
var res : vec4<f32> = frexp(vec4<f32>(), &(arg_1));
}
struct tint_symbol {
[[builtin(position)]]
value : vec4<f32>;
};
[[stage(vertex)]]
fn vertex_main() -> tint_symbol {
frexp_234f02();
let tint_symbol_1 : tint_symbol = tint_symbol(vec4<f32>());
return tint_symbol_1;
}
[[stage(fragment)]]
fn fragment_main() {
frexp_234f02();
}
[[stage(compute)]]
fn compute_main() {
frexp_234f02();
}
Failed to generate: error: Unknown builtin method: frexp

View File

@ -0,0 +1,31 @@
SKIP: FAILED
fn frexp_234f02() {
var arg_1 : vec4<u32>;
var res : vec4<f32> = frexp(vec4<f32>(), &(arg_1));
}
struct tint_symbol {
[[builtin(position)]]
value : vec4<f32>;
};
[[stage(vertex)]]
fn vertex_main() -> tint_symbol {
frexp_234f02();
let tint_symbol_1 : tint_symbol = tint_symbol(vec4<f32>());
return tint_symbol_1;
}
[[stage(fragment)]]
fn fragment_main() {
frexp_234f02();
}
[[stage(compute)]]
fn compute_main() {
frexp_234f02();
}
Failed to generate: error: Unknown import method: frexp

View File

@ -13,7 +13,7 @@
OpExecutionMode %compute_main LocalSize 1 1 1 OpExecutionMode %compute_main LocalSize 1 1 1
OpName %tint_pointsize "tint_pointsize" OpName %tint_pointsize "tint_pointsize"
OpName %tint_symbol_1 "tint_symbol_1" OpName %tint_symbol_1 "tint_symbol_1"
OpName %frexp_2507b2 "frexp_2507b2" OpName %frexp_234f02 "frexp_234f02"
OpName %arg_1 "arg_1" OpName %arg_1 "arg_1"
OpName %res "res" OpName %res "res"
OpName %tint_symbol_2 "tint_symbol_2" OpName %tint_symbol_2 "tint_symbol_2"
@ -40,7 +40,7 @@
%_ptr_Function_v4float = OpTypePointer Function %v4float %_ptr_Function_v4float = OpTypePointer Function %v4float
%23 = OpTypeFunction %void %v4float %23 = OpTypeFunction %void %v4float
%float_1 = OpConstant %float 1 %float_1 = OpConstant %float 1
%frexp_2507b2 = OpFunction %void None %9 %frexp_234f02 = OpFunction %void None %9
%12 = OpLabel %12 = OpLabel
%arg_1 = OpVariable %_ptr_Function_v4uint Function %17 %arg_1 = OpVariable %_ptr_Function_v4uint Function %17
%res = OpVariable %_ptr_Function_v4float Function %8 %res = OpVariable %_ptr_Function_v4float Function %8
@ -57,17 +57,17 @@
%vertex_main = OpFunction %void None %9 %vertex_main = OpFunction %void None %9
%28 = OpLabel %28 = OpLabel
OpStore %tint_pointsize %float_1 OpStore %tint_pointsize %float_1
%30 = OpFunctionCall %void %frexp_2507b2 %30 = OpFunctionCall %void %frexp_234f02
%31 = OpFunctionCall %void %tint_symbol_2 %8 %31 = OpFunctionCall %void %tint_symbol_2 %8
OpReturn OpReturn
OpFunctionEnd OpFunctionEnd
%fragment_main = OpFunction %void None %9 %fragment_main = OpFunction %void None %9
%33 = OpLabel %33 = OpLabel
%34 = OpFunctionCall %void %frexp_2507b2 %34 = OpFunctionCall %void %frexp_234f02
OpReturn OpReturn
OpFunctionEnd OpFunctionEnd
%compute_main = OpFunction %void None %9 %compute_main = OpFunction %void None %9
%36 = OpLabel %36 = OpLabel
%37 = OpFunctionCall %void %frexp_2507b2 %37 = OpFunctionCall %void %frexp_234f02
OpReturn OpReturn
OpFunctionEnd OpFunctionEnd

View File

@ -1,20 +1,20 @@
fn frexp_2507b2() { fn frexp_234f02() {
var arg_1 : vec4<u32>; var arg_1 : vec4<u32>;
var res : vec4<f32> = frexp(vec4<f32>(), &(arg_1)); var res : vec4<f32> = frexp(vec4<f32>(), &(arg_1));
} }
[[stage(vertex)]] [[stage(vertex)]]
fn vertex_main() -> [[builtin(position)]] vec4<f32> { fn vertex_main() -> [[builtin(position)]] vec4<f32> {
frexp_2507b2(); frexp_234f02();
return vec4<f32>(); return vec4<f32>();
} }
[[stage(fragment)]] [[stage(fragment)]]
fn fragment_main() { fn fragment_main() {
frexp_2507b2(); frexp_234f02();
} }
[[stage(compute)]] [[stage(compute)]]
fn compute_main() { fn compute_main() {
frexp_2507b2(); frexp_234f02();
} }

View File

@ -1,24 +0,0 @@
SKIP: FAILED
fn frexp_2507b2() {
var arg_1 : vec4<u32>;
var res : vec4<f32> = frexp(vec4<f32>(), &(arg_1));
}
[[stage(vertex)]]
fn vertex_main() {
frexp_2507b2();
}
[[stage(fragment)]]
fn fragment_main() {
frexp_2507b2();
}
[[stage(compute)]]
fn compute_main() {
frexp_2507b2();
}
Failed to generate: error: Unknown builtin method: frexp

View File

@ -1,24 +0,0 @@
SKIP: FAILED
fn frexp_2507b2() {
var arg_1 : vec4<u32>;
var res : vec4<f32> = frexp(vec4<f32>(), &(arg_1));
}
[[stage(vertex)]]
fn vertex_main() {
frexp_2507b2();
}
[[stage(fragment)]]
fn fragment_main() {
frexp_2507b2();
}
[[stage(compute)]]
fn compute_main() {
frexp_2507b2();
}
Failed to generate: error: Unknown import method: frexp

View File

@ -22,23 +22,23 @@
// Do not modify this file directly // Do not modify this file directly
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
fn frexp_2a171c() { fn frexp_2945dc() {
var arg_1: vec2<u32>; var arg_1: vec2<u32>;
var res: vec2<f32> = frexp(vec2<f32>(), &arg_1); var res: vec2<f32> = frexp(vec2<f32>(), &arg_1);
} }
[[stage(vertex)]] [[stage(vertex)]]
fn vertex_main() -> [[builtin(position)]] vec4<f32> { fn vertex_main() -> [[builtin(position)]] vec4<f32> {
frexp_2a171c(); frexp_2945dc();
return vec4<f32>(); return vec4<f32>();
} }
[[stage(fragment)]] [[stage(fragment)]]
fn fragment_main() { fn fragment_main() {
frexp_2a171c(); frexp_2945dc();
} }
[[stage(compute)]] [[stage(compute)]]
fn compute_main() { fn compute_main() {
frexp_2a171c(); frexp_2945dc();
} }

View File

@ -0,0 +1,31 @@
SKIP: FAILED
fn frexp_2945dc() {
var arg_1 : vec2<u32>;
var res : vec2<f32> = frexp(vec2<f32>(), &(arg_1));
}
struct tint_symbol {
[[builtin(position)]]
value : vec4<f32>;
};
[[stage(vertex)]]
fn vertex_main() -> tint_symbol {
frexp_2945dc();
let tint_symbol_1 : tint_symbol = tint_symbol(vec4<f32>());
return tint_symbol_1;
}
[[stage(fragment)]]
fn fragment_main() {
frexp_2945dc();
}
[[stage(compute)]]
fn compute_main() {
frexp_2945dc();
}
Failed to generate: error: Unknown builtin method: frexp

View File

@ -0,0 +1,31 @@
SKIP: FAILED
fn frexp_2945dc() {
var arg_1 : vec2<u32>;
var res : vec2<f32> = frexp(vec2<f32>(), &(arg_1));
}
struct tint_symbol {
[[builtin(position)]]
value : vec4<f32>;
};
[[stage(vertex)]]
fn vertex_main() -> tint_symbol {
frexp_2945dc();
let tint_symbol_1 : tint_symbol = tint_symbol(vec4<f32>());
return tint_symbol_1;
}
[[stage(fragment)]]
fn fragment_main() {
frexp_2945dc();
}
[[stage(compute)]]
fn compute_main() {
frexp_2945dc();
}
Failed to generate: error: Unknown import method: frexp

View File

@ -13,7 +13,7 @@
OpExecutionMode %compute_main LocalSize 1 1 1 OpExecutionMode %compute_main LocalSize 1 1 1
OpName %tint_pointsize "tint_pointsize" OpName %tint_pointsize "tint_pointsize"
OpName %tint_symbol_1 "tint_symbol_1" OpName %tint_symbol_1 "tint_symbol_1"
OpName %frexp_2a171c "frexp_2a171c" OpName %frexp_2945dc "frexp_2945dc"
OpName %arg_1 "arg_1" OpName %arg_1 "arg_1"
OpName %res "res" OpName %res "res"
OpName %tint_symbol_2 "tint_symbol_2" OpName %tint_symbol_2 "tint_symbol_2"
@ -42,7 +42,7 @@
%_ptr_Function_v2float = OpTypePointer Function %v2float %_ptr_Function_v2float = OpTypePointer Function %v2float
%25 = OpTypeFunction %void %v4float %25 = OpTypeFunction %void %v4float
%float_1 = OpConstant %float 1 %float_1 = OpConstant %float 1
%frexp_2a171c = OpFunction %void None %9 %frexp_2945dc = OpFunction %void None %9
%12 = OpLabel %12 = OpLabel
%arg_1 = OpVariable %_ptr_Function_v2uint Function %17 %arg_1 = OpVariable %_ptr_Function_v2uint Function %17
%res = OpVariable %_ptr_Function_v2float Function %21 %res = OpVariable %_ptr_Function_v2float Function %21
@ -59,17 +59,17 @@
%vertex_main = OpFunction %void None %9 %vertex_main = OpFunction %void None %9
%30 = OpLabel %30 = OpLabel
OpStore %tint_pointsize %float_1 OpStore %tint_pointsize %float_1
%32 = OpFunctionCall %void %frexp_2a171c %32 = OpFunctionCall %void %frexp_2945dc
%33 = OpFunctionCall %void %tint_symbol_2 %8 %33 = OpFunctionCall %void %tint_symbol_2 %8
OpReturn OpReturn
OpFunctionEnd OpFunctionEnd
%fragment_main = OpFunction %void None %9 %fragment_main = OpFunction %void None %9
%35 = OpLabel %35 = OpLabel
%36 = OpFunctionCall %void %frexp_2a171c %36 = OpFunctionCall %void %frexp_2945dc
OpReturn OpReturn
OpFunctionEnd OpFunctionEnd
%compute_main = OpFunction %void None %9 %compute_main = OpFunction %void None %9
%38 = OpLabel %38 = OpLabel
%39 = OpFunctionCall %void %frexp_2a171c %39 = OpFunctionCall %void %frexp_2945dc
OpReturn OpReturn
OpFunctionEnd OpFunctionEnd

View File

@ -1,20 +1,20 @@
fn frexp_2a171c() { fn frexp_2945dc() {
var arg_1 : vec2<u32>; var arg_1 : vec2<u32>;
var res : vec2<f32> = frexp(vec2<f32>(), &(arg_1)); var res : vec2<f32> = frexp(vec2<f32>(), &(arg_1));
} }
[[stage(vertex)]] [[stage(vertex)]]
fn vertex_main() -> [[builtin(position)]] vec4<f32> { fn vertex_main() -> [[builtin(position)]] vec4<f32> {
frexp_2a171c(); frexp_2945dc();
return vec4<f32>(); return vec4<f32>();
} }
[[stage(fragment)]] [[stage(fragment)]]
fn fragment_main() { fn fragment_main() {
frexp_2a171c(); frexp_2945dc();
} }
[[stage(compute)]] [[stage(compute)]]
fn compute_main() { fn compute_main() {
frexp_2a171c(); frexp_2945dc();
} }

View File

@ -1,24 +0,0 @@
SKIP: FAILED
fn frexp_2a171c() {
var arg_1 : vec2<u32>;
var res : vec2<f32> = frexp(vec2<f32>(), &(arg_1));
}
[[stage(vertex)]]
fn vertex_main() {
frexp_2a171c();
}
[[stage(fragment)]]
fn fragment_main() {
frexp_2a171c();
}
[[stage(compute)]]
fn compute_main() {
frexp_2a171c();
}
Failed to generate: error: Unknown builtin method: frexp

View File

@ -1,24 +0,0 @@
SKIP: FAILED
fn frexp_2a171c() {
var arg_1 : vec2<u32>;
var res : vec2<f32> = frexp(vec2<f32>(), &(arg_1));
}
[[stage(vertex)]]
fn vertex_main() {
frexp_2a171c();
}
[[stage(fragment)]]
fn fragment_main() {
frexp_2a171c();
}
[[stage(compute)]]
fn compute_main() {
frexp_2a171c();
}
Failed to generate: error: Unknown import method: frexp

View File

@ -1,24 +0,0 @@
SKIP: FAILED
fn frexp_34dd30() {
var arg_1 : u32;
var res : f32 = frexp(1.0, &(arg_1));
}
[[stage(vertex)]]
fn vertex_main() {
frexp_34dd30();
}
[[stage(fragment)]]
fn fragment_main() {
frexp_34dd30();
}
[[stage(compute)]]
fn compute_main() {
frexp_34dd30();
}
Failed to generate: error: Unknown builtin method: frexp

View File

@ -1,24 +0,0 @@
SKIP: FAILED
fn frexp_34dd30() {
var arg_1 : u32;
var res : f32 = frexp(1.0, &(arg_1));
}
[[stage(vertex)]]
fn vertex_main() {
frexp_34dd30();
}
[[stage(fragment)]]
fn fragment_main() {
frexp_34dd30();
}
[[stage(compute)]]
fn compute_main() {
frexp_34dd30();
}
Failed to generate: error: Unknown import method: frexp

View File

@ -22,23 +22,23 @@
// Do not modify this file directly // Do not modify this file directly
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
fn frexp_99b922() { fn frexp_41e931() {
var arg_1: i32; var arg_1: i32;
var res: f32 = frexp(1.0, &arg_1); var res: f32 = frexp(1.0, &arg_1);
} }
[[stage(vertex)]] [[stage(vertex)]]
fn vertex_main() -> [[builtin(position)]] vec4<f32> { fn vertex_main() -> [[builtin(position)]] vec4<f32> {
frexp_99b922(); frexp_41e931();
return vec4<f32>(); return vec4<f32>();
} }
[[stage(fragment)]] [[stage(fragment)]]
fn fragment_main() { fn fragment_main() {
frexp_99b922(); frexp_41e931();
} }
[[stage(compute)]] [[stage(compute)]]
fn compute_main() { fn compute_main() {
frexp_99b922(); frexp_41e931();
} }

View File

@ -0,0 +1,31 @@
SKIP: FAILED
fn frexp_41e931() {
var arg_1 : i32;
var res : f32 = frexp(1.0, &(arg_1));
}
struct tint_symbol {
[[builtin(position)]]
value : vec4<f32>;
};
[[stage(vertex)]]
fn vertex_main() -> tint_symbol {
frexp_41e931();
let tint_symbol_1 : tint_symbol = tint_symbol(vec4<f32>());
return tint_symbol_1;
}
[[stage(fragment)]]
fn fragment_main() {
frexp_41e931();
}
[[stage(compute)]]
fn compute_main() {
frexp_41e931();
}
Failed to generate: error: Unknown builtin method: frexp

View File

@ -0,0 +1,31 @@
SKIP: FAILED
fn frexp_41e931() {
var arg_1 : i32;
var res : f32 = frexp(1.0, &(arg_1));
}
struct tint_symbol {
[[builtin(position)]]
value : vec4<f32>;
};
[[stage(vertex)]]
fn vertex_main() -> tint_symbol {
frexp_41e931();
let tint_symbol_1 : tint_symbol = tint_symbol(vec4<f32>());
return tint_symbol_1;
}
[[stage(fragment)]]
fn fragment_main() {
frexp_41e931();
}
[[stage(compute)]]
fn compute_main() {
frexp_41e931();
}
Failed to generate: error: Unknown import method: frexp

View File

@ -13,7 +13,7 @@
OpExecutionMode %compute_main LocalSize 1 1 1 OpExecutionMode %compute_main LocalSize 1 1 1
OpName %tint_pointsize "tint_pointsize" OpName %tint_pointsize "tint_pointsize"
OpName %tint_symbol_1 "tint_symbol_1" OpName %tint_symbol_1 "tint_symbol_1"
OpName %frexp_99b922 "frexp_99b922" OpName %frexp_41e931 "frexp_41e931"
OpName %arg_1 "arg_1" OpName %arg_1 "arg_1"
OpName %res "res" OpName %res "res"
OpName %tint_symbol_2 "tint_symbol_2" OpName %tint_symbol_2 "tint_symbol_2"
@ -39,7 +39,7 @@
%float_1 = OpConstant %float 1 %float_1 = OpConstant %float 1
%_ptr_Function_float = OpTypePointer Function %float %_ptr_Function_float = OpTypePointer Function %float
%23 = OpTypeFunction %void %v4float %23 = OpTypeFunction %void %v4float
%frexp_99b922 = OpFunction %void None %9 %frexp_41e931 = OpFunction %void None %9
%12 = OpLabel %12 = OpLabel
%arg_1 = OpVariable %_ptr_Function_int Function %16 %arg_1 = OpVariable %_ptr_Function_int Function %16
%res = OpVariable %_ptr_Function_float Function %4 %res = OpVariable %_ptr_Function_float Function %4
@ -56,17 +56,17 @@
%vertex_main = OpFunction %void None %9 %vertex_main = OpFunction %void None %9
%28 = OpLabel %28 = OpLabel
OpStore %tint_pointsize %float_1 OpStore %tint_pointsize %float_1
%29 = OpFunctionCall %void %frexp_99b922 %29 = OpFunctionCall %void %frexp_41e931
%30 = OpFunctionCall %void %tint_symbol_2 %8 %30 = OpFunctionCall %void %tint_symbol_2 %8
OpReturn OpReturn
OpFunctionEnd OpFunctionEnd
%fragment_main = OpFunction %void None %9 %fragment_main = OpFunction %void None %9
%32 = OpLabel %32 = OpLabel
%33 = OpFunctionCall %void %frexp_99b922 %33 = OpFunctionCall %void %frexp_41e931
OpReturn OpReturn
OpFunctionEnd OpFunctionEnd
%compute_main = OpFunction %void None %9 %compute_main = OpFunction %void None %9
%35 = OpLabel %35 = OpLabel
%36 = OpFunctionCall %void %frexp_99b922 %36 = OpFunctionCall %void %frexp_41e931
OpReturn OpReturn
OpFunctionEnd OpFunctionEnd

View File

@ -1,20 +1,20 @@
fn frexp_99b922() { fn frexp_41e931() {
var arg_1 : i32; var arg_1 : i32;
var res : f32 = frexp(1.0, &(arg_1)); var res : f32 = frexp(1.0, &(arg_1));
} }
[[stage(vertex)]] [[stage(vertex)]]
fn vertex_main() -> [[builtin(position)]] vec4<f32> { fn vertex_main() -> [[builtin(position)]] vec4<f32> {
frexp_99b922(); frexp_41e931();
return vec4<f32>(); return vec4<f32>();
} }
[[stage(fragment)]] [[stage(fragment)]]
fn fragment_main() { fn fragment_main() {
frexp_99b922(); frexp_41e931();
} }
[[stage(compute)]] [[stage(compute)]]
fn compute_main() { fn compute_main() {
frexp_99b922(); frexp_41e931();
} }

View File

@ -0,0 +1,44 @@
// Copyright 2021 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.
////////////////////////////////////////////////////////////////////////////////
// File generated by tools/intrinsic-gen
// using the template:
// test/intrinsics/intrinsics.wgsl.tmpl
// and the intrinsic defintion file:
// src/intrinsics.def
//
// Do not modify this file directly
////////////////////////////////////////////////////////////////////////////////
fn frexp_481e59() {
var arg_1: i32;
var res: f32 = frexp(1.0, &arg_1);
}
[[stage(vertex)]]
fn vertex_main() -> [[builtin(position)]] vec4<f32> {
frexp_481e59();
return vec4<f32>();
}
[[stage(fragment)]]
fn fragment_main() {
frexp_481e59();
}
[[stage(compute)]]
fn compute_main() {
frexp_481e59();
}

View File

@ -0,0 +1,31 @@
SKIP: FAILED
fn frexp_481e59() {
var arg_1 : i32;
var res : f32 = frexp(1.0, &(arg_1));
}
struct tint_symbol {
[[builtin(position)]]
value : vec4<f32>;
};
[[stage(vertex)]]
fn vertex_main() -> tint_symbol {
frexp_481e59();
let tint_symbol_1 : tint_symbol = tint_symbol(vec4<f32>());
return tint_symbol_1;
}
[[stage(fragment)]]
fn fragment_main() {
frexp_481e59();
}
[[stage(compute)]]
fn compute_main() {
frexp_481e59();
}
Failed to generate: error: Unknown builtin method: frexp

View File

@ -0,0 +1,31 @@
SKIP: FAILED
fn frexp_481e59() {
var arg_1 : i32;
var res : f32 = frexp(1.0, &(arg_1));
}
struct tint_symbol {
[[builtin(position)]]
value : vec4<f32>;
};
[[stage(vertex)]]
fn vertex_main() -> tint_symbol {
frexp_481e59();
let tint_symbol_1 : tint_symbol = tint_symbol(vec4<f32>());
return tint_symbol_1;
}
[[stage(fragment)]]
fn fragment_main() {
frexp_481e59();
}
[[stage(compute)]]
fn compute_main() {
frexp_481e59();
}
Failed to generate: error: Unknown import method: frexp

View File

@ -0,0 +1,72 @@
; SPIR-V
; Version: 1.3
; Generator: Google Tint Compiler; 0
; Bound: 37
; Schema: 0
OpCapability Shader
%18 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Vertex %vertex_main "vertex_main" %tint_pointsize %tint_symbol_1
OpEntryPoint Fragment %fragment_main "fragment_main"
OpEntryPoint GLCompute %compute_main "compute_main"
OpExecutionMode %fragment_main OriginUpperLeft
OpExecutionMode %compute_main LocalSize 1 1 1
OpName %tint_pointsize "tint_pointsize"
OpName %tint_symbol_1 "tint_symbol_1"
OpName %frexp_481e59 "frexp_481e59"
OpName %arg_1 "arg_1"
OpName %res "res"
OpName %tint_symbol_2 "tint_symbol_2"
OpName %tint_symbol "tint_symbol"
OpName %vertex_main "vertex_main"
OpName %fragment_main "fragment_main"
OpName %compute_main "compute_main"
OpDecorate %tint_pointsize BuiltIn PointSize
OpDecorate %tint_symbol_1 BuiltIn Position
%float = OpTypeFloat 32
%_ptr_Output_float = OpTypePointer Output %float
%4 = OpConstantNull %float
%tint_pointsize = OpVariable %_ptr_Output_float Output %4
%v4float = OpTypeVector %float 4
%_ptr_Output_v4float = OpTypePointer Output %v4float
%8 = OpConstantNull %v4float
%tint_symbol_1 = OpVariable %_ptr_Output_v4float Output %8
%void = OpTypeVoid
%9 = OpTypeFunction %void
%int = OpTypeInt 32 1
%_ptr_Function_int = OpTypePointer Function %int
%16 = OpConstantNull %int
%float_1 = OpConstant %float 1
%_ptr_Function_float = OpTypePointer Function %float
%23 = OpTypeFunction %void %v4float
%frexp_481e59 = OpFunction %void None %9
%12 = OpLabel
%arg_1 = OpVariable %_ptr_Function_int Function %16
%res = OpVariable %_ptr_Function_float Function %4
%17 = OpExtInst %float %18 Frexp %float_1 %arg_1
OpStore %res %17
OpReturn
OpFunctionEnd
%tint_symbol_2 = OpFunction %void None %23
%tint_symbol = OpFunctionParameter %v4float
%26 = OpLabel
OpStore %tint_symbol_1 %tint_symbol
OpReturn
OpFunctionEnd
%vertex_main = OpFunction %void None %9
%28 = OpLabel
OpStore %tint_pointsize %float_1
%29 = OpFunctionCall %void %frexp_481e59
%30 = OpFunctionCall %void %tint_symbol_2 %8
OpReturn
OpFunctionEnd
%fragment_main = OpFunction %void None %9
%32 = OpLabel
%33 = OpFunctionCall %void %frexp_481e59
OpReturn
OpFunctionEnd
%compute_main = OpFunction %void None %9
%35 = OpLabel
%36 = OpFunctionCall %void %frexp_481e59
OpReturn
OpFunctionEnd

View File

@ -0,0 +1,20 @@
fn frexp_481e59() {
var arg_1 : i32;
var res : f32 = frexp(1.0, &(arg_1));
}
[[stage(vertex)]]
fn vertex_main() -> [[builtin(position)]] vec4<f32> {
frexp_481e59();
return vec4<f32>();
}
[[stage(fragment)]]
fn fragment_main() {
frexp_481e59();
}
[[stage(compute)]]
fn compute_main() {
frexp_481e59();
}

View File

@ -1,24 +0,0 @@
SKIP: FAILED
fn frexp_4b73e3() {
var arg_1 : vec4<i32>;
var res : vec4<f32> = frexp(vec4<f32>(), &(arg_1));
}
[[stage(vertex)]]
fn vertex_main() {
frexp_4b73e3();
}
[[stage(fragment)]]
fn fragment_main() {
frexp_4b73e3();
}
[[stage(compute)]]
fn compute_main() {
frexp_4b73e3();
}
Failed to generate: error: Unknown builtin method: frexp

View File

@ -1,24 +0,0 @@
SKIP: FAILED
fn frexp_4b73e3() {
var arg_1 : vec4<i32>;
var res : vec4<f32> = frexp(vec4<f32>(), &(arg_1));
}
[[stage(vertex)]]
fn vertex_main() {
frexp_4b73e3();
}
[[stage(fragment)]]
fn fragment_main() {
frexp_4b73e3();
}
[[stage(compute)]]
fn compute_main() {
frexp_4b73e3();
}
Failed to generate: error: Unknown import method: frexp

View File

@ -22,23 +22,23 @@
// Do not modify this file directly // Do not modify this file directly
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
fn frexp_79ed81() { fn frexp_5a141e() {
var arg_1: vec3<i32>; var arg_1: vec3<i32>;
var res: vec3<f32> = frexp(vec3<f32>(), &arg_1); var res: vec3<f32> = frexp(vec3<f32>(), &arg_1);
} }
[[stage(vertex)]] [[stage(vertex)]]
fn vertex_main() -> [[builtin(position)]] vec4<f32> { fn vertex_main() -> [[builtin(position)]] vec4<f32> {
frexp_79ed81(); frexp_5a141e();
return vec4<f32>(); return vec4<f32>();
} }
[[stage(fragment)]] [[stage(fragment)]]
fn fragment_main() { fn fragment_main() {
frexp_79ed81(); frexp_5a141e();
} }
[[stage(compute)]] [[stage(compute)]]
fn compute_main() { fn compute_main() {
frexp_79ed81(); frexp_5a141e();
} }

View File

@ -0,0 +1,31 @@
SKIP: FAILED
fn frexp_5a141e() {
var arg_1 : vec3<i32>;
var res : vec3<f32> = frexp(vec3<f32>(), &(arg_1));
}
struct tint_symbol {
[[builtin(position)]]
value : vec4<f32>;
};
[[stage(vertex)]]
fn vertex_main() -> tint_symbol {
frexp_5a141e();
let tint_symbol_1 : tint_symbol = tint_symbol(vec4<f32>());
return tint_symbol_1;
}
[[stage(fragment)]]
fn fragment_main() {
frexp_5a141e();
}
[[stage(compute)]]
fn compute_main() {
frexp_5a141e();
}
Failed to generate: error: Unknown builtin method: frexp

View File

@ -0,0 +1,31 @@
SKIP: FAILED
fn frexp_5a141e() {
var arg_1 : vec3<i32>;
var res : vec3<f32> = frexp(vec3<f32>(), &(arg_1));
}
struct tint_symbol {
[[builtin(position)]]
value : vec4<f32>;
};
[[stage(vertex)]]
fn vertex_main() -> tint_symbol {
frexp_5a141e();
let tint_symbol_1 : tint_symbol = tint_symbol(vec4<f32>());
return tint_symbol_1;
}
[[stage(fragment)]]
fn fragment_main() {
frexp_5a141e();
}
[[stage(compute)]]
fn compute_main() {
frexp_5a141e();
}
Failed to generate: error: Unknown import method: frexp

View File

@ -13,7 +13,7 @@
OpExecutionMode %compute_main LocalSize 1 1 1 OpExecutionMode %compute_main LocalSize 1 1 1
OpName %tint_pointsize "tint_pointsize" OpName %tint_pointsize "tint_pointsize"
OpName %tint_symbol_1 "tint_symbol_1" OpName %tint_symbol_1 "tint_symbol_1"
OpName %frexp_79ed81 "frexp_79ed81" OpName %frexp_5a141e "frexp_5a141e"
OpName %arg_1 "arg_1" OpName %arg_1 "arg_1"
OpName %res "res" OpName %res "res"
OpName %tint_symbol_2 "tint_symbol_2" OpName %tint_symbol_2 "tint_symbol_2"
@ -42,7 +42,7 @@
%_ptr_Function_v3float = OpTypePointer Function %v3float %_ptr_Function_v3float = OpTypePointer Function %v3float
%25 = OpTypeFunction %void %v4float %25 = OpTypeFunction %void %v4float
%float_1 = OpConstant %float 1 %float_1 = OpConstant %float 1
%frexp_79ed81 = OpFunction %void None %9 %frexp_5a141e = OpFunction %void None %9
%12 = OpLabel %12 = OpLabel
%arg_1 = OpVariable %_ptr_Function_v3int Function %17 %arg_1 = OpVariable %_ptr_Function_v3int Function %17
%res = OpVariable %_ptr_Function_v3float Function %21 %res = OpVariable %_ptr_Function_v3float Function %21
@ -59,17 +59,17 @@
%vertex_main = OpFunction %void None %9 %vertex_main = OpFunction %void None %9
%30 = OpLabel %30 = OpLabel
OpStore %tint_pointsize %float_1 OpStore %tint_pointsize %float_1
%32 = OpFunctionCall %void %frexp_79ed81 %32 = OpFunctionCall %void %frexp_5a141e
%33 = OpFunctionCall %void %tint_symbol_2 %8 %33 = OpFunctionCall %void %tint_symbol_2 %8
OpReturn OpReturn
OpFunctionEnd OpFunctionEnd
%fragment_main = OpFunction %void None %9 %fragment_main = OpFunction %void None %9
%35 = OpLabel %35 = OpLabel
%36 = OpFunctionCall %void %frexp_79ed81 %36 = OpFunctionCall %void %frexp_5a141e
OpReturn OpReturn
OpFunctionEnd OpFunctionEnd
%compute_main = OpFunction %void None %9 %compute_main = OpFunction %void None %9
%38 = OpLabel %38 = OpLabel
%39 = OpFunctionCall %void %frexp_79ed81 %39 = OpFunctionCall %void %frexp_5a141e
OpReturn OpReturn
OpFunctionEnd OpFunctionEnd

View File

@ -1,20 +1,20 @@
fn frexp_79ed81() { fn frexp_5a141e() {
var arg_1 : vec3<i32>; var arg_1 : vec3<i32>;
var res : vec3<f32> = frexp(vec3<f32>(), &(arg_1)); var res : vec3<f32> = frexp(vec3<f32>(), &(arg_1));
} }
[[stage(vertex)]] [[stage(vertex)]]
fn vertex_main() -> [[builtin(position)]] vec4<f32> { fn vertex_main() -> [[builtin(position)]] vec4<f32> {
frexp_79ed81(); frexp_5a141e();
return vec4<f32>(); return vec4<f32>();
} }
[[stage(fragment)]] [[stage(fragment)]]
fn fragment_main() { fn fragment_main() {
frexp_79ed81(); frexp_5a141e();
} }
[[stage(compute)]] [[stage(compute)]]
fn compute_main() { fn compute_main() {
frexp_79ed81(); frexp_5a141e();
} }

View File

@ -22,23 +22,23 @@
// Do not modify this file directly // Do not modify this file directly
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
fn frexp_cb41c5() { fn frexp_64e816() {
var arg_1: vec3<u32>; var arg_1: vec3<u32>;
var res: vec3<f32> = frexp(vec3<f32>(), &arg_1); var res: vec3<f32> = frexp(vec3<f32>(), &arg_1);
} }
[[stage(vertex)]] [[stage(vertex)]]
fn vertex_main() -> [[builtin(position)]] vec4<f32> { fn vertex_main() -> [[builtin(position)]] vec4<f32> {
frexp_cb41c5(); frexp_64e816();
return vec4<f32>(); return vec4<f32>();
} }
[[stage(fragment)]] [[stage(fragment)]]
fn fragment_main() { fn fragment_main() {
frexp_cb41c5(); frexp_64e816();
} }
[[stage(compute)]] [[stage(compute)]]
fn compute_main() { fn compute_main() {
frexp_cb41c5(); frexp_64e816();
} }

View File

@ -0,0 +1,31 @@
SKIP: FAILED
fn frexp_64e816() {
var arg_1 : vec3<u32>;
var res : vec3<f32> = frexp(vec3<f32>(), &(arg_1));
}
struct tint_symbol {
[[builtin(position)]]
value : vec4<f32>;
};
[[stage(vertex)]]
fn vertex_main() -> tint_symbol {
frexp_64e816();
let tint_symbol_1 : tint_symbol = tint_symbol(vec4<f32>());
return tint_symbol_1;
}
[[stage(fragment)]]
fn fragment_main() {
frexp_64e816();
}
[[stage(compute)]]
fn compute_main() {
frexp_64e816();
}
Failed to generate: error: Unknown builtin method: frexp

View File

@ -0,0 +1,31 @@
SKIP: FAILED
fn frexp_64e816() {
var arg_1 : vec3<u32>;
var res : vec3<f32> = frexp(vec3<f32>(), &(arg_1));
}
struct tint_symbol {
[[builtin(position)]]
value : vec4<f32>;
};
[[stage(vertex)]]
fn vertex_main() -> tint_symbol {
frexp_64e816();
let tint_symbol_1 : tint_symbol = tint_symbol(vec4<f32>());
return tint_symbol_1;
}
[[stage(fragment)]]
fn fragment_main() {
frexp_64e816();
}
[[stage(compute)]]
fn compute_main() {
frexp_64e816();
}
Failed to generate: error: Unknown import method: frexp

View File

@ -13,7 +13,7 @@
OpExecutionMode %compute_main LocalSize 1 1 1 OpExecutionMode %compute_main LocalSize 1 1 1
OpName %tint_pointsize "tint_pointsize" OpName %tint_pointsize "tint_pointsize"
OpName %tint_symbol_1 "tint_symbol_1" OpName %tint_symbol_1 "tint_symbol_1"
OpName %frexp_cb41c5 "frexp_cb41c5" OpName %frexp_64e816 "frexp_64e816"
OpName %arg_1 "arg_1" OpName %arg_1 "arg_1"
OpName %res "res" OpName %res "res"
OpName %tint_symbol_2 "tint_symbol_2" OpName %tint_symbol_2 "tint_symbol_2"
@ -42,7 +42,7 @@
%_ptr_Function_v3float = OpTypePointer Function %v3float %_ptr_Function_v3float = OpTypePointer Function %v3float
%25 = OpTypeFunction %void %v4float %25 = OpTypeFunction %void %v4float
%float_1 = OpConstant %float 1 %float_1 = OpConstant %float 1
%frexp_cb41c5 = OpFunction %void None %9 %frexp_64e816 = OpFunction %void None %9
%12 = OpLabel %12 = OpLabel
%arg_1 = OpVariable %_ptr_Function_v3uint Function %17 %arg_1 = OpVariable %_ptr_Function_v3uint Function %17
%res = OpVariable %_ptr_Function_v3float Function %21 %res = OpVariable %_ptr_Function_v3float Function %21
@ -59,17 +59,17 @@
%vertex_main = OpFunction %void None %9 %vertex_main = OpFunction %void None %9
%30 = OpLabel %30 = OpLabel
OpStore %tint_pointsize %float_1 OpStore %tint_pointsize %float_1
%32 = OpFunctionCall %void %frexp_cb41c5 %32 = OpFunctionCall %void %frexp_64e816
%33 = OpFunctionCall %void %tint_symbol_2 %8 %33 = OpFunctionCall %void %tint_symbol_2 %8
OpReturn OpReturn
OpFunctionEnd OpFunctionEnd
%fragment_main = OpFunction %void None %9 %fragment_main = OpFunction %void None %9
%35 = OpLabel %35 = OpLabel
%36 = OpFunctionCall %void %frexp_cb41c5 %36 = OpFunctionCall %void %frexp_64e816
OpReturn OpReturn
OpFunctionEnd OpFunctionEnd
%compute_main = OpFunction %void None %9 %compute_main = OpFunction %void None %9
%38 = OpLabel %38 = OpLabel
%39 = OpFunctionCall %void %frexp_cb41c5 %39 = OpFunctionCall %void %frexp_64e816
OpReturn OpReturn
OpFunctionEnd OpFunctionEnd

View File

@ -1,20 +1,20 @@
fn frexp_cb41c5() { fn frexp_64e816() {
var arg_1 : vec3<u32>; var arg_1 : vec3<u32>;
var res : vec3<f32> = frexp(vec3<f32>(), &(arg_1)); var res : vec3<f32> = frexp(vec3<f32>(), &(arg_1));
} }
[[stage(vertex)]] [[stage(vertex)]]
fn vertex_main() -> [[builtin(position)]] vec4<f32> { fn vertex_main() -> [[builtin(position)]] vec4<f32> {
frexp_cb41c5(); frexp_64e816();
return vec4<f32>(); return vec4<f32>();
} }
[[stage(fragment)]] [[stage(fragment)]]
fn fragment_main() { fn fragment_main() {
frexp_cb41c5(); frexp_64e816();
} }
[[stage(compute)]] [[stage(compute)]]
fn compute_main() { fn compute_main() {
frexp_cb41c5(); frexp_64e816();
} }

Some files were not shown because too many files have changed in this diff Show More