mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-07-06 05:06:07 +00:00
tint: Add 'chromium_experimental_full_ptr_parameters' extension
Removes validation around pointer parameters. Bug: tint:1758 Change-Id: I3adc48f780fc8c6f5525f9ecc280e2a406069b49 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/112286 Reviewed-by: James Price <jrprice@google.com> Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: Ben Clayton <bclayton@google.com>
This commit is contained in:
parent
53f646c55c
commit
94706ecba7
@ -34,6 +34,9 @@ Extension ParseExtension(std::string_view str) {
|
|||||||
if (str == "chromium_experimental_dp4a") {
|
if (str == "chromium_experimental_dp4a") {
|
||||||
return Extension::kChromiumExperimentalDp4A;
|
return Extension::kChromiumExperimentalDp4A;
|
||||||
}
|
}
|
||||||
|
if (str == "chromium_experimental_full_ptr_parameters") {
|
||||||
|
return Extension::kChromiumExperimentalFullPtrParameters;
|
||||||
|
}
|
||||||
if (str == "chromium_experimental_push_constant") {
|
if (str == "chromium_experimental_push_constant") {
|
||||||
return Extension::kChromiumExperimentalPushConstant;
|
return Extension::kChromiumExperimentalPushConstant;
|
||||||
}
|
}
|
||||||
@ -51,6 +54,8 @@ std::ostream& operator<<(std::ostream& out, Extension value) {
|
|||||||
return out << "chromium_disable_uniformity_analysis";
|
return out << "chromium_disable_uniformity_analysis";
|
||||||
case Extension::kChromiumExperimentalDp4A:
|
case Extension::kChromiumExperimentalDp4A:
|
||||||
return out << "chromium_experimental_dp4a";
|
return out << "chromium_experimental_dp4a";
|
||||||
|
case Extension::kChromiumExperimentalFullPtrParameters:
|
||||||
|
return out << "chromium_experimental_full_ptr_parameters";
|
||||||
case Extension::kChromiumExperimentalPushConstant:
|
case Extension::kChromiumExperimentalPushConstant:
|
||||||
return out << "chromium_experimental_push_constant";
|
return out << "chromium_experimental_push_constant";
|
||||||
case Extension::kF16:
|
case Extension::kF16:
|
||||||
|
@ -35,6 +35,7 @@ enum class Extension {
|
|||||||
kUndefined,
|
kUndefined,
|
||||||
kChromiumDisableUniformityAnalysis,
|
kChromiumDisableUniformityAnalysis,
|
||||||
kChromiumExperimentalDp4A,
|
kChromiumExperimentalDp4A,
|
||||||
|
kChromiumExperimentalFullPtrParameters,
|
||||||
kChromiumExperimentalPushConstant,
|
kChromiumExperimentalPushConstant,
|
||||||
kF16,
|
kF16,
|
||||||
};
|
};
|
||||||
@ -52,6 +53,7 @@ Extension ParseExtension(std::string_view str);
|
|||||||
constexpr const char* kExtensionStrings[] = {
|
constexpr const char* kExtensionStrings[] = {
|
||||||
"chromium_disable_uniformity_analysis",
|
"chromium_disable_uniformity_analysis",
|
||||||
"chromium_experimental_dp4a",
|
"chromium_experimental_dp4a",
|
||||||
|
"chromium_experimental_full_ptr_parameters",
|
||||||
"chromium_experimental_push_constant",
|
"chromium_experimental_push_constant",
|
||||||
"f16",
|
"f16",
|
||||||
};
|
};
|
||||||
|
@ -45,20 +45,27 @@ void ExtensionParser(::benchmark::State& state) {
|
|||||||
"chromium_exverimentiil_dp4a",
|
"chromium_exverimentiil_dp4a",
|
||||||
"chro8ium_experimenWWal_dp4a",
|
"chro8ium_experimenWWal_dp4a",
|
||||||
"chromiMm_eperimxxntal_dp4a",
|
"chromiMm_eperimxxntal_dp4a",
|
||||||
"chrXmium_experimeggtal_ush_constant",
|
"chromium_expeggimeXtal_full_ptr_paraeters",
|
||||||
"chromiu_experVmentalpusX_constant",
|
"chromium_expVrimental_full_ptr_puraXeer",
|
||||||
"chro3ium_experimental_push_constant",
|
"chromium_experimental_full_ptr3parameters",
|
||||||
|
"chromium_experimental_full_ptr_parameters",
|
||||||
|
"chromium_experimentalEfull_ptr_parameters",
|
||||||
|
"chromium_experimentalfull_ptr_PPaTTameters",
|
||||||
|
"chromium_ddxperimental_fullptrxxparameters",
|
||||||
|
"c44romium_experimental_push_constant",
|
||||||
|
"chromium_experimental_pSSsVV_constant",
|
||||||
|
"chrom22Rm_experimental_pushRonstant",
|
||||||
"chromium_experimental_push_constant",
|
"chromium_experimental_push_constant",
|
||||||
"chromium_experEmental_push_constant",
|
"chromium_exp9rimFntal_ush_constant",
|
||||||
"chPPomiumexperimental_push_conTTtant",
|
"chrmium_experimental_push_constant",
|
||||||
"chromixxm_experimentddl_push_constnt",
|
"cOOromium_experiVeHtal_puh_conRRtant",
|
||||||
"4416",
|
"y1",
|
||||||
"fSVV6",
|
"l77rrn6",
|
||||||
"RR2",
|
"4016",
|
||||||
"f16",
|
"f16",
|
||||||
"96",
|
"5",
|
||||||
"f1",
|
"u16",
|
||||||
"VOR6",
|
"f",
|
||||||
};
|
};
|
||||||
for (auto _ : state) {
|
for (auto _ : state) {
|
||||||
for (auto& str : kStrings) {
|
for (auto& str : kStrings) {
|
||||||
|
@ -44,6 +44,8 @@ inline std::ostream& operator<<(std::ostream& out, Case c) {
|
|||||||
static constexpr Case kValidCases[] = {
|
static constexpr Case kValidCases[] = {
|
||||||
{"chromium_disable_uniformity_analysis", Extension::kChromiumDisableUniformityAnalysis},
|
{"chromium_disable_uniformity_analysis", Extension::kChromiumDisableUniformityAnalysis},
|
||||||
{"chromium_experimental_dp4a", Extension::kChromiumExperimentalDp4A},
|
{"chromium_experimental_dp4a", Extension::kChromiumExperimentalDp4A},
|
||||||
|
{"chromium_experimental_full_ptr_parameters",
|
||||||
|
Extension::kChromiumExperimentalFullPtrParameters},
|
||||||
{"chromium_experimental_push_constant", Extension::kChromiumExperimentalPushConstant},
|
{"chromium_experimental_push_constant", Extension::kChromiumExperimentalPushConstant},
|
||||||
{"f16", Extension::kF16},
|
{"f16", Extension::kF16},
|
||||||
};
|
};
|
||||||
@ -55,12 +57,15 @@ static constexpr Case kInvalidCases[] = {
|
|||||||
{"chro1ium_experimental_dp4a", Extension::kUndefined},
|
{"chro1ium_experimental_dp4a", Extension::kUndefined},
|
||||||
{"chrJmium_experiqqetal_dp4a", Extension::kUndefined},
|
{"chrJmium_experiqqetal_dp4a", Extension::kUndefined},
|
||||||
{"chromium_experimenll77l_dp4a", Extension::kUndefined},
|
{"chromium_experimenll77l_dp4a", Extension::kUndefined},
|
||||||
{"cppromium_experiHHenal_qqush_constant", Extension::kUndefined},
|
{"chroium_experimental_full_ptr_paqqppmetHHrs", Extension::kUndefined},
|
||||||
{"chromium_xpericental_sh_vonstant", Extension::kUndefined},
|
{"chrium_evperiental_full_ptr_paraceters", Extension::kUndefined},
|
||||||
{"chromium_experimental_Gsh_cbnstant", Extension::kUndefined},
|
{"chromium_expGimental_fullbptr_parameters", Extension::kUndefined},
|
||||||
{"f1vi", Extension::kUndefined},
|
{"chvomium_experimental_push_constiint", Extension::kUndefined},
|
||||||
{"f8WW", Extension::kUndefined},
|
{"chromiu8WWexperimental_push_constant", Extension::kUndefined},
|
||||||
{"fxx", Extension::kUndefined},
|
{"chromium_experiMental_push_costanxx", Extension::kUndefined},
|
||||||
|
{"fgg", Extension::kUndefined},
|
||||||
|
{"X", Extension::kUndefined},
|
||||||
|
{"316", Extension::kUndefined},
|
||||||
};
|
};
|
||||||
|
|
||||||
using ExtensionParseTest = testing::TestWithParam<Case>;
|
using ExtensionParseTest = testing::TestWithParam<Case>;
|
||||||
|
@ -51,6 +51,9 @@ enum extension {
|
|||||||
chromium_disable_uniformity_analysis
|
chromium_disable_uniformity_analysis
|
||||||
// A Chromium-specific extension for push constants
|
// A Chromium-specific extension for push constants
|
||||||
chromium_experimental_push_constant
|
chromium_experimental_push_constant
|
||||||
|
// A Chromium-specific extension that enables passing of uniform, storage and workgroup
|
||||||
|
// address-spaced pointers as parameters, as well as pointers into sub-objects.
|
||||||
|
chromium_experimental_full_ptr_parameters
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://gpuweb.github.io/gpuweb/wgsl/#storage-class
|
// https://gpuweb.github.io/gpuweb/wgsl/#storage-class
|
||||||
|
@ -62,7 +62,7 @@ TEST_F(EnableDirectiveTest, InvalidIdentifier) {
|
|||||||
// Error when unknown extension found
|
// Error when unknown extension found
|
||||||
EXPECT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), R"(1:8: expected extension
|
EXPECT_EQ(p->error(), R"(1:8: expected extension
|
||||||
Possible values: 'chromium_disable_uniformity_analysis', 'chromium_experimental_dp4a', 'chromium_experimental_push_constant', 'f16')");
|
Possible values: 'chromium_disable_uniformity_analysis', 'chromium_experimental_dp4a', 'chromium_experimental_full_ptr_parameters', 'chromium_experimental_push_constant', 'f16')");
|
||||||
auto program = p->program();
|
auto program = p->program();
|
||||||
auto& ast = program.AST();
|
auto& ast = program.AST();
|
||||||
EXPECT_EQ(ast.Enables().Length(), 0u);
|
EXPECT_EQ(ast.Enables().Length(), 0u);
|
||||||
@ -75,7 +75,7 @@ TEST_F(EnableDirectiveTest, InvalidIdentifierSuggest) {
|
|||||||
// Error when unknown extension found
|
// Error when unknown extension found
|
||||||
EXPECT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), R"(1:8: expected extension. Did you mean 'f16'?
|
EXPECT_EQ(p->error(), R"(1:8: expected extension. Did you mean 'f16'?
|
||||||
Possible values: 'chromium_disable_uniformity_analysis', 'chromium_experimental_dp4a', 'chromium_experimental_push_constant', 'f16')");
|
Possible values: 'chromium_disable_uniformity_analysis', 'chromium_experimental_dp4a', 'chromium_experimental_full_ptr_parameters', 'chromium_experimental_push_constant', 'f16')");
|
||||||
auto program = p->program();
|
auto program = p->program();
|
||||||
auto& ast = program.AST();
|
auto& ast = program.AST();
|
||||||
EXPECT_EQ(ast.Enables().Length(), 0u);
|
EXPECT_EQ(ast.Enables().Length(), 0u);
|
||||||
@ -123,7 +123,7 @@ TEST_F(EnableDirectiveTest, InvalidTokens) {
|
|||||||
p->translation_unit();
|
p->translation_unit();
|
||||||
EXPECT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), R"(1:8: expected extension
|
EXPECT_EQ(p->error(), R"(1:8: expected extension
|
||||||
Possible values: 'chromium_disable_uniformity_analysis', 'chromium_experimental_dp4a', 'chromium_experimental_push_constant', 'f16')");
|
Possible values: 'chromium_disable_uniformity_analysis', 'chromium_experimental_dp4a', 'chromium_experimental_full_ptr_parameters', 'chromium_experimental_push_constant', 'f16')");
|
||||||
auto program = p->program();
|
auto program = p->program();
|
||||||
auto& ast = program.AST();
|
auto& ast = program.AST();
|
||||||
EXPECT_EQ(ast.Enables().Length(), 0u);
|
EXPECT_EQ(ast.Enables().Length(), 0u);
|
||||||
@ -134,7 +134,7 @@ Possible values: 'chromium_disable_uniformity_analysis', 'chromium_experimental_
|
|||||||
p->translation_unit();
|
p->translation_unit();
|
||||||
EXPECT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), R"(1:8: expected extension
|
EXPECT_EQ(p->error(), R"(1:8: expected extension
|
||||||
Possible values: 'chromium_disable_uniformity_analysis', 'chromium_experimental_dp4a', 'chromium_experimental_push_constant', 'f16')");
|
Possible values: 'chromium_disable_uniformity_analysis', 'chromium_experimental_dp4a', 'chromium_experimental_full_ptr_parameters', 'chromium_experimental_push_constant', 'f16')");
|
||||||
auto program = p->program();
|
auto program = p->program();
|
||||||
auto& ast = program.AST();
|
auto& ast = program.AST();
|
||||||
EXPECT_EQ(ast.Enables().Length(), 0u);
|
EXPECT_EQ(ast.Enables().Length(), 0u);
|
||||||
@ -145,7 +145,7 @@ Possible values: 'chromium_disable_uniformity_analysis', 'chromium_experimental_
|
|||||||
p->translation_unit();
|
p->translation_unit();
|
||||||
EXPECT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), R"(1:8: expected extension
|
EXPECT_EQ(p->error(), R"(1:8: expected extension
|
||||||
Possible values: 'chromium_disable_uniformity_analysis', 'chromium_experimental_dp4a', 'chromium_experimental_push_constant', 'f16')");
|
Possible values: 'chromium_disable_uniformity_analysis', 'chromium_experimental_dp4a', 'chromium_experimental_full_ptr_parameters', 'chromium_experimental_push_constant', 'f16')");
|
||||||
auto program = p->program();
|
auto program = p->program();
|
||||||
auto& ast = program.AST();
|
auto& ast = program.AST();
|
||||||
EXPECT_EQ(ast.Enables().Length(), 0u);
|
EXPECT_EQ(ast.Enables().Length(), 0u);
|
||||||
|
@ -114,7 +114,25 @@ TEST_F(ResolverCallValidationTest, PointerArgument_VariableIdentExpr) {
|
|||||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverCallValidationTest, PointerArgument_NotWholeVar) {
|
TEST_F(ResolverCallValidationTest, PointerArgument_LetIdentExpr) {
|
||||||
|
// fn foo(p: ptr<function, i32>) {}
|
||||||
|
// fn main() {
|
||||||
|
// let z: i32 = 1i;
|
||||||
|
// foo(&z);
|
||||||
|
// }
|
||||||
|
auto* param = Param("p", ty.pointer<i32>(ast::AddressSpace::kFunction));
|
||||||
|
Func("foo", utils::Vector{param}, ty.void_(), utils::Empty);
|
||||||
|
Func("main", utils::Empty, ty.void_(),
|
||||||
|
utils::Vector{
|
||||||
|
Decl(Let("z", ty.i32(), Expr(1_i))),
|
||||||
|
CallStmt(Call("foo", AddressOf(Expr(Source{{12, 34}}, "z")))),
|
||||||
|
});
|
||||||
|
|
||||||
|
EXPECT_FALSE(r()->Resolve());
|
||||||
|
EXPECT_EQ(r()->error(), "12:34 error: cannot take the address of expression");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ResolverCallValidationTest, PointerArgument_AddressOfFunctionMember) {
|
||||||
// struct S { m: i32; };
|
// struct S { m: i32; };
|
||||||
// fn foo(p: ptr<function, i32>) {}
|
// fn foo(p: ptr<function, i32>) {}
|
||||||
// fn main() {
|
// fn main() {
|
||||||
@ -138,6 +156,51 @@ TEST_F(ResolverCallValidationTest, PointerArgument_NotWholeVar) {
|
|||||||
"originating variable");
|
"originating variable");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ResolverCallValidationTest,
|
||||||
|
PointerArgument_AddressOfFunctionMember_WithFullPtrParametersExt) {
|
||||||
|
// enable chromium_experimental_full_ptr_parameters;
|
||||||
|
// struct S { m: i32; };
|
||||||
|
// fn foo(p: ptr<function, i32>) {}
|
||||||
|
// fn main() {
|
||||||
|
// var v : S;
|
||||||
|
// foo(&v.m);
|
||||||
|
// }
|
||||||
|
Enable(ast::Extension::kChromiumExperimentalFullPtrParameters);
|
||||||
|
auto* S = Structure("S", utils::Vector{
|
||||||
|
Member("m", ty.i32()),
|
||||||
|
});
|
||||||
|
auto* param = Param("p", ty.pointer<i32>(ast::AddressSpace::kFunction));
|
||||||
|
Func("foo", utils::Vector{param}, ty.void_(), utils::Empty);
|
||||||
|
Func("main", utils::Empty, ty.void_(),
|
||||||
|
utils::Vector{
|
||||||
|
Decl(Var("v", ty.Of(S))),
|
||||||
|
CallStmt(Call("foo", AddressOf(Source{{12, 34}}, MemberAccessor("v", "m")))),
|
||||||
|
});
|
||||||
|
|
||||||
|
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||||
|
}
|
||||||
|
TEST_F(ResolverCallValidationTest, PointerArgument_AddressOfLetMember) {
|
||||||
|
// struct S { m: i32; };
|
||||||
|
// fn foo(p: ptr<function, i32>) {}
|
||||||
|
// fn main() {
|
||||||
|
// let v: S = S();
|
||||||
|
// foo(&v.m);
|
||||||
|
// }
|
||||||
|
auto* S = Structure("S", utils::Vector{
|
||||||
|
Member("m", ty.i32()),
|
||||||
|
});
|
||||||
|
auto* param = Param("p", ty.pointer<i32>(ast::AddressSpace::kFunction));
|
||||||
|
Func("foo", utils::Vector{param}, ty.void_(), utils::Empty);
|
||||||
|
Func("main", utils::Empty, ty.void_(),
|
||||||
|
utils::Vector{
|
||||||
|
Decl(Let("v", ty.Of(S), Construct(ty.Of(S)))),
|
||||||
|
CallStmt(Call("foo", AddressOf(MemberAccessor(Source{{12, 34}}, "v", "m")))),
|
||||||
|
});
|
||||||
|
|
||||||
|
EXPECT_FALSE(r()->Resolve());
|
||||||
|
EXPECT_EQ(r()->error(), "12:34 error: cannot take the address of expression");
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(ResolverCallValidationTest, PointerArgument_FunctionParam) {
|
TEST_F(ResolverCallValidationTest, PointerArgument_FunctionParam) {
|
||||||
// fn foo(p: ptr<function, i32>) {}
|
// fn foo(p: ptr<function, i32>) {}
|
||||||
// fn bar(p: ptr<function, i32>) {
|
// fn bar(p: ptr<function, i32>) {
|
||||||
@ -181,12 +244,12 @@ TEST_F(ResolverCallValidationTest, PointerArgument_FunctionParamWithMain) {
|
|||||||
},
|
},
|
||||||
ty.void_(),
|
ty.void_(),
|
||||||
utils::Vector{
|
utils::Vector{
|
||||||
CallStmt(Call("foo", Expr("p"))),
|
CallStmt(Call("foo", "p")),
|
||||||
});
|
});
|
||||||
Func("main", utils::Empty, ty.void_(),
|
Func("main", utils::Empty, ty.void_(),
|
||||||
utils::Vector{
|
utils::Vector{
|
||||||
Decl(Var("v", ty.i32(), Expr(1_i))),
|
Decl(Var("v", ty.i32(), Expr(1_i))),
|
||||||
CallStmt(Call("foo", AddressOf(Expr("v")))),
|
CallStmt(Call("foo", AddressOf("v"))),
|
||||||
},
|
},
|
||||||
utils::Vector{
|
utils::Vector{
|
||||||
Stage(ast::PipelineStage::kFragment),
|
Stage(ast::PipelineStage::kFragment),
|
||||||
@ -195,40 +258,15 @@ TEST_F(ResolverCallValidationTest, PointerArgument_FunctionParamWithMain) {
|
|||||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverCallValidationTest, PointerArgument_FunctionParam_NotWholeVar) {
|
|
||||||
// fn foo(p: ptr<function, i32>) {}
|
|
||||||
// fn bar(p: ptr<function, array<i32, 4>>) {
|
|
||||||
// foo(&(*p)[0]);
|
|
||||||
// }
|
|
||||||
Func("foo",
|
|
||||||
utils::Vector{
|
|
||||||
Param("p", ty.pointer<i32>(ast::AddressSpace::kFunction)),
|
|
||||||
},
|
|
||||||
ty.void_(), utils::Empty);
|
|
||||||
Func("bar",
|
|
||||||
utils::Vector{
|
|
||||||
Param("p", ty.pointer(ty.array<i32, 4>(), ast::AddressSpace::kFunction)),
|
|
||||||
},
|
|
||||||
ty.void_(),
|
|
||||||
utils::Vector{
|
|
||||||
CallStmt(Call("foo", AddressOf(Source{{12, 34}}, IndexAccessor(Deref("p"), 0_a)))),
|
|
||||||
});
|
|
||||||
|
|
||||||
EXPECT_FALSE(r()->Resolve());
|
|
||||||
EXPECT_EQ(r()->error(),
|
|
||||||
"12:34 error: arguments of pointer type must not point to a subset of the "
|
|
||||||
"originating variable");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(ResolverCallValidationTest, LetPointer) {
|
TEST_F(ResolverCallValidationTest, LetPointer) {
|
||||||
// fn foo(p : ptr<function, i32>) {}
|
// fn foo(p : ptr<function, i32>) {}
|
||||||
// @fragment
|
// @fragment
|
||||||
// fn main() {
|
// fn main() {
|
||||||
// var v: i32;
|
// var v: i32;
|
||||||
// let p: ptr<function, i32> = &v;
|
// let p: ptr<function, i32> = &v;
|
||||||
// foo(p);
|
// x(p);
|
||||||
// }
|
// }
|
||||||
Func("foo",
|
Func("x",
|
||||||
utils::Vector{
|
utils::Vector{
|
||||||
Param("p", ty.pointer<i32>(ast::AddressSpace::kFunction)),
|
Param("p", ty.pointer<i32>(ast::AddressSpace::kFunction)),
|
||||||
},
|
},
|
||||||
@ -237,7 +275,7 @@ TEST_F(ResolverCallValidationTest, LetPointer) {
|
|||||||
utils::Vector{
|
utils::Vector{
|
||||||
Decl(Var("v", ty.i32())),
|
Decl(Var("v", ty.i32())),
|
||||||
Decl(Let("p", ty.pointer(ty.i32(), ast::AddressSpace::kFunction), AddressOf("v"))),
|
Decl(Let("p", ty.pointer(ty.i32(), ast::AddressSpace::kFunction), AddressOf("v"))),
|
||||||
CallStmt(Call("foo", Expr(Source{{12, 34}}, "p"))),
|
CallStmt(Call("x", "p")),
|
||||||
},
|
},
|
||||||
utils::Vector{
|
utils::Vector{
|
||||||
Stage(ast::PipelineStage::kFragment),
|
Stage(ast::PipelineStage::kFragment),
|
||||||
@ -247,7 +285,7 @@ TEST_F(ResolverCallValidationTest, LetPointer) {
|
|||||||
|
|
||||||
TEST_F(ResolverCallValidationTest, LetPointerPrivate) {
|
TEST_F(ResolverCallValidationTest, LetPointerPrivate) {
|
||||||
// fn foo(p : ptr<private, i32>) {}
|
// fn foo(p : ptr<private, i32>) {}
|
||||||
// var<private> v: i32;
|
// var v : i32;
|
||||||
// @fragment
|
// @fragment
|
||||||
// fn main() {
|
// fn main() {
|
||||||
// let p : ptr<private, i32> = &v;
|
// let p : ptr<private, i32> = &v;
|
||||||
@ -299,6 +337,34 @@ TEST_F(ResolverCallValidationTest, LetPointer_NotWholeVar) {
|
|||||||
"originating variable");
|
"originating variable");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ResolverCallValidationTest, LetPointer_NotWholeVar_WithFullPtrParametersExt) {
|
||||||
|
// enable chromium_experimental_full_ptr_parameters;
|
||||||
|
// fn foo(p : ptr<function, i32>) {}
|
||||||
|
// @fragment
|
||||||
|
// fn main() {
|
||||||
|
// var v: array<i32, 4>;
|
||||||
|
// let p: ptr<function, i32> = &(v[0]);
|
||||||
|
// x(p);
|
||||||
|
// }
|
||||||
|
Enable(ast::Extension::kChromiumExperimentalFullPtrParameters);
|
||||||
|
Func("foo",
|
||||||
|
utils::Vector{
|
||||||
|
Param("p", ty.pointer<i32>(ast::AddressSpace::kFunction)),
|
||||||
|
},
|
||||||
|
ty.void_(), utils::Empty);
|
||||||
|
Func("main", utils::Empty, ty.void_(),
|
||||||
|
utils::Vector{
|
||||||
|
Decl(Var("v", ty.array<i32, 4>())),
|
||||||
|
Decl(Let("p", ty.pointer(ty.i32(), ast::AddressSpace::kFunction),
|
||||||
|
AddressOf(IndexAccessor("v", 0_a)))),
|
||||||
|
CallStmt(Call("foo", Expr(Source{{12, 34}}, "p"))),
|
||||||
|
},
|
||||||
|
utils::Vector{
|
||||||
|
Stage(ast::PipelineStage::kFragment),
|
||||||
|
});
|
||||||
|
EXPECT_TRUE(r()->Resolve());
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(ResolverCallValidationTest, ComplexPointerChain) {
|
TEST_F(ResolverCallValidationTest, ComplexPointerChain) {
|
||||||
// fn foo(p : ptr<function, array<i32, 4>>) {}
|
// fn foo(p : ptr<function, array<i32, 4>>) {}
|
||||||
// @fragment
|
// @fragment
|
||||||
@ -360,6 +426,37 @@ TEST_F(ResolverCallValidationTest, ComplexPointerChain_NotWholeVar) {
|
|||||||
"originating variable");
|
"originating variable");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ResolverCallValidationTest, ComplexPointerChain_NotWholeVar_WithFullPtrParametersExt) {
|
||||||
|
// enable chromium_experimental_full_ptr_parameters;
|
||||||
|
// fn foo(p : ptr<function, i32>) {}
|
||||||
|
// @fragment
|
||||||
|
// fn main() {
|
||||||
|
// var v: array<i32, 4>;
|
||||||
|
// let p1 = &v;
|
||||||
|
// let p2 = p1;
|
||||||
|
// let p3 = &(*p2)[0];
|
||||||
|
// foo(&*p);
|
||||||
|
// }
|
||||||
|
Enable(ast::Extension::kChromiumExperimentalFullPtrParameters);
|
||||||
|
Func("foo",
|
||||||
|
utils::Vector{
|
||||||
|
Param("p", ty.pointer<i32>(ast::AddressSpace::kFunction)),
|
||||||
|
},
|
||||||
|
ty.void_(), utils::Empty);
|
||||||
|
Func("main", utils::Empty, ty.void_(),
|
||||||
|
utils::Vector{
|
||||||
|
Decl(Var("v", ty.array<i32, 4>())),
|
||||||
|
Decl(Let("p1", AddressOf("v"))),
|
||||||
|
Decl(Let("p2", Expr("p1"))),
|
||||||
|
Decl(Let("p3", AddressOf(IndexAccessor(Deref("p2"), 0_a)))),
|
||||||
|
CallStmt(Call("foo", AddressOf(Source{{12, 34}}, Deref("p3")))),
|
||||||
|
},
|
||||||
|
utils::Vector{
|
||||||
|
Stage(ast::PipelineStage::kFragment),
|
||||||
|
});
|
||||||
|
EXPECT_TRUE(r()->Resolve());
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(ResolverCallValidationTest, CallVariable) {
|
TEST_F(ResolverCallValidationTest, CallVariable) {
|
||||||
// var v : i32;
|
// var v : i32;
|
||||||
// fn f() {
|
// fn f() {
|
||||||
|
@ -1041,21 +1041,26 @@ TEST_F(ResolverFunctionValidationTest, ParameterMatrixNoType) {
|
|||||||
EXPECT_EQ(r()->error(), "12:34 error: missing matrix element type");
|
EXPECT_EQ(r()->error(), "12:34 error: missing matrix element type");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class Expectation {
|
||||||
|
kAlwaysPass,
|
||||||
|
kPassWithFullPtrParameterExtension,
|
||||||
|
kAlwaysFail,
|
||||||
|
};
|
||||||
struct TestParams {
|
struct TestParams {
|
||||||
ast::AddressSpace address_space;
|
ast::AddressSpace address_space;
|
||||||
bool should_pass;
|
Expectation expectation;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TestWithParams : ResolverTestWithParam<TestParams> {};
|
struct TestWithParams : ResolverTestWithParam<TestParams> {};
|
||||||
|
|
||||||
using ResolverFunctionParameterValidationTest = TestWithParams;
|
using ResolverFunctionParameterValidationTest = TestWithParams;
|
||||||
TEST_P(ResolverFunctionParameterValidationTest, AddressSpace) {
|
TEST_P(ResolverFunctionParameterValidationTest, AddressSpaceNoExtension) {
|
||||||
auto& param = GetParam();
|
auto& param = GetParam();
|
||||||
auto* ptr_type = ty.pointer(Source{{12, 34}}, ty.i32(), param.address_space);
|
auto* ptr_type = ty.pointer(Source{{12, 34}}, ty.i32(), param.address_space);
|
||||||
auto* arg = Param(Source{{12, 34}}, "p", ptr_type);
|
auto* arg = Param(Source{{12, 34}}, "p", ptr_type);
|
||||||
Func("f", utils::Vector{arg}, ty.void_(), utils::Empty);
|
Func("f", utils::Vector{arg}, ty.void_(), utils::Empty);
|
||||||
|
|
||||||
if (param.should_pass) {
|
if (param.expectation == Expectation::kAlwaysPass) {
|
||||||
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
||||||
} else {
|
} else {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
@ -1065,17 +1070,36 @@ TEST_P(ResolverFunctionParameterValidationTest, AddressSpace) {
|
|||||||
ss.str() + "' address space");
|
ss.str() + "' address space");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
INSTANTIATE_TEST_SUITE_P(ResolverTest,
|
TEST_P(ResolverFunctionParameterValidationTest, AddressSpaceWithExtension) {
|
||||||
|
auto& param = GetParam();
|
||||||
|
auto* ptr_type = ty.pointer(Source{{12, 34}}, ty.i32(), param.address_space);
|
||||||
|
auto* arg = Param(Source{{12, 34}}, "p", ptr_type);
|
||||||
|
Enable(ast::Extension::kChromiumExperimentalFullPtrParameters);
|
||||||
|
Func("f", utils::Vector{arg}, ty.void_(), utils::Empty);
|
||||||
|
|
||||||
|
if (param.expectation != Expectation::kAlwaysFail) {
|
||||||
|
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
||||||
|
} else {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << param.address_space;
|
||||||
|
EXPECT_FALSE(r()->Resolve());
|
||||||
|
EXPECT_EQ(r()->error(), "12:34 error: function parameter of pointer type cannot be in '" +
|
||||||
|
ss.str() + "' address space");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
INSTANTIATE_TEST_SUITE_P(
|
||||||
|
ResolverTest,
|
||||||
ResolverFunctionParameterValidationTest,
|
ResolverFunctionParameterValidationTest,
|
||||||
testing::Values(TestParams{ast::AddressSpace::kNone, false},
|
testing::Values(
|
||||||
TestParams{ast::AddressSpace::kIn, false},
|
TestParams{ast::AddressSpace::kNone, Expectation::kAlwaysFail},
|
||||||
TestParams{ast::AddressSpace::kOut, false},
|
TestParams{ast::AddressSpace::kIn, Expectation::kAlwaysFail},
|
||||||
TestParams{ast::AddressSpace::kUniform, false},
|
TestParams{ast::AddressSpace::kOut, Expectation::kAlwaysFail},
|
||||||
TestParams{ast::AddressSpace::kWorkgroup, false},
|
TestParams{ast::AddressSpace::kUniform, Expectation::kPassWithFullPtrParameterExtension},
|
||||||
TestParams{ast::AddressSpace::kHandle, false},
|
TestParams{ast::AddressSpace::kWorkgroup, Expectation::kPassWithFullPtrParameterExtension},
|
||||||
TestParams{ast::AddressSpace::kStorage, false},
|
TestParams{ast::AddressSpace::kHandle, Expectation::kAlwaysFail},
|
||||||
TestParams{ast::AddressSpace::kPrivate, true},
|
TestParams{ast::AddressSpace::kStorage, Expectation::kPassWithFullPtrParameterExtension},
|
||||||
TestParams{ast::AddressSpace::kFunction, true}));
|
TestParams{ast::AddressSpace::kPrivate, Expectation::kAlwaysPass},
|
||||||
|
TestParams{ast::AddressSpace::kFunction, Expectation::kAlwaysPass}));
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace tint::resolver
|
} // namespace tint::resolver
|
||||||
|
@ -800,17 +800,33 @@ bool Validator::Parameter(const ast::Function* func, const sem::Variable* var) c
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (auto* ref = var->Type()->As<sem::Pointer>()) {
|
if (auto* ref = var->Type()->As<sem::Pointer>()) {
|
||||||
auto address_space = ref->AddressSpace();
|
if (IsValidationEnabled(decl->attributes, ast::DisabledValidation::kIgnoreAddressSpace)) {
|
||||||
if (!(address_space == ast::AddressSpace::kFunction ||
|
bool ok = false;
|
||||||
address_space == ast::AddressSpace::kPrivate) &&
|
|
||||||
IsValidationEnabled(decl->attributes, ast::DisabledValidation::kIgnoreAddressSpace)) {
|
auto sc = ref->AddressSpace();
|
||||||
|
switch (sc) {
|
||||||
|
case ast::AddressSpace::kFunction:
|
||||||
|
case ast::AddressSpace::kPrivate:
|
||||||
|
ok = true;
|
||||||
|
break;
|
||||||
|
case ast::AddressSpace::kStorage:
|
||||||
|
case ast::AddressSpace::kUniform:
|
||||||
|
case ast::AddressSpace::kWorkgroup:
|
||||||
|
ok = enabled_extensions_.Contains(
|
||||||
|
ast::Extension::kChromiumExperimentalFullPtrParameters);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!ok) {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "function parameter of pointer type cannot be in '" << address_space
|
ss << "function parameter of pointer type cannot be in '" << sc
|
||||||
<< "' address space";
|
<< "' address space";
|
||||||
AddError(ss.str(), decl->source);
|
AddError(ss.str(), decl->source);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (IsPlain(var->Type())) {
|
if (IsPlain(var->Type())) {
|
||||||
if (!var->Type()->IsConstructible()) {
|
if (!var->Type()->IsConstructible()) {
|
||||||
@ -1654,7 +1670,8 @@ bool Validator::FunctionCall(const sem::Call* call, sem::Statement* current_stat
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (param_type->Is<sem::Pointer>()) {
|
if (param_type->Is<sem::Pointer>() &&
|
||||||
|
!enabled_extensions_.Contains(ast::Extension::kChromiumExperimentalFullPtrParameters)) {
|
||||||
// https://gpuweb.github.io/gpuweb/wgsl/#function-restriction
|
// https://gpuweb.github.io/gpuweb/wgsl/#function-restriction
|
||||||
// Each argument of pointer type to a user-defined function must have the same memory
|
// Each argument of pointer type to a user-defined function must have the same memory
|
||||||
// view as its root identifier.
|
// view as its root identifier.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user