resolver: Validate that a call statement has no return value
Also split out validation tests from call_test.cc into call_validation_test.cc. Bug: tint:886 Change-Id: I1e1dee9b7c348363e89080cdecd3119cc004658f Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/54063 Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: David Neto <dneto@google.com>
This commit is contained in:
parent
0f1efe04c3
commit
7fe0106b12
|
@ -590,6 +590,7 @@ if(${TINT_BUILD_TESTS})
|
||||||
resolver/block_test.cc
|
resolver/block_test.cc
|
||||||
resolver/builtins_validation_test.cc
|
resolver/builtins_validation_test.cc
|
||||||
resolver/call_test.cc
|
resolver/call_test.cc
|
||||||
|
resolver/call_validation_test.cc
|
||||||
resolver/control_block_validation_test.cc
|
resolver/control_block_validation_test.cc
|
||||||
resolver/decoration_validation_test.cc
|
resolver/decoration_validation_test.cc
|
||||||
resolver/entry_point_validation_test.cc
|
resolver/entry_point_validation_test.cc
|
||||||
|
|
|
@ -97,7 +97,7 @@ fn f1(p0 : f32, p1 : i32) -> f32 {
|
||||||
|
|
||||||
[[stage(fragment)]]
|
[[stage(fragment)]]
|
||||||
fn main() {
|
fn main() {
|
||||||
f1(1.0, 2);
|
ignore(f1(1.0, 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
let declaration_order_check_0 : i32 = 1;
|
let declaration_order_check_0 : i32 = 1;
|
||||||
|
|
|
@ -2755,8 +2755,8 @@ TEST_P(InspectorGetMultisampledTextureResourceBindingsTestWithParam,
|
||||||
|
|
||||||
Func("ep", ast::VariableList(), ty.void_(),
|
Func("ep", ast::VariableList(), ty.void_(),
|
||||||
ast::StatementList{
|
ast::StatementList{
|
||||||
create<ast::CallStatement>(Call("textureLoad", "foo_texture",
|
Ignore(Call("textureLoad", "foo_texture", "foo_coords",
|
||||||
"foo_coords", "foo_sample_index")),
|
"foo_sample_index")),
|
||||||
},
|
},
|
||||||
ast::DecorationList{
|
ast::DecorationList{
|
||||||
Stage(ast::PipelineStage::kFragment),
|
Stage(ast::PipelineStage::kFragment),
|
||||||
|
@ -3013,8 +3013,7 @@ TEST_P(InspectorGetDepthTextureResourceBindingsTestWithParam,
|
||||||
|
|
||||||
Func("ep", ast::VariableList(), ty.void_(),
|
Func("ep", ast::VariableList(), ty.void_(),
|
||||||
ast::StatementList{
|
ast::StatementList{
|
||||||
create<ast::CallStatement>(
|
Ignore(Call("textureDimensions", "dt", "dt_level")),
|
||||||
Call("textureDimensions", "dt", "dt_level")),
|
|
||||||
},
|
},
|
||||||
ast::DecorationList{
|
ast::DecorationList{
|
||||||
Stage(ast::PipelineStage::kFragment),
|
Stage(ast::PipelineStage::kFragment),
|
||||||
|
@ -3056,7 +3055,7 @@ TEST_F(InspectorGetExternalTextureResourceBindingsTest, Simple) {
|
||||||
|
|
||||||
Func("ep", ast::VariableList(), ty.void_(),
|
Func("ep", ast::VariableList(), ty.void_(),
|
||||||
ast::StatementList{
|
ast::StatementList{
|
||||||
create<ast::CallStatement>(Call("textureDimensions", "et")),
|
Ignore(Call("textureDimensions", "et")),
|
||||||
},
|
},
|
||||||
ast::DecorationList{
|
ast::DecorationList{
|
||||||
Stage(ast::PipelineStage::kFragment),
|
Stage(ast::PipelineStage::kFragment),
|
||||||
|
|
|
@ -123,7 +123,7 @@ ast::Statement* ProgramBuilder::WrapInStatement(ast::Literal* lit) {
|
||||||
|
|
||||||
ast::Statement* ProgramBuilder::WrapInStatement(ast::Expression* expr) {
|
ast::Statement* ProgramBuilder::WrapInStatement(ast::Expression* expr) {
|
||||||
if (auto* ce = expr->As<ast::CallExpression>()) {
|
if (auto* ce = expr->As<ast::CallExpression>()) {
|
||||||
return create<ast::CallStatement>(ce);
|
return Ignore(ce);
|
||||||
}
|
}
|
||||||
// Create a temporary variable of inferred type from expr.
|
// Create a temporary variable of inferred type from expr.
|
||||||
return Decl(Const(symbols_.New(), nullptr, expr));
|
return Decl(Const(symbols_.New(), nullptr, expr));
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "src/ast/bool.h"
|
#include "src/ast/bool.h"
|
||||||
#include "src/ast/bool_literal.h"
|
#include "src/ast/bool_literal.h"
|
||||||
#include "src/ast/call_expression.h"
|
#include "src/ast/call_expression.h"
|
||||||
|
#include "src/ast/call_statement.h"
|
||||||
#include "src/ast/case_statement.h"
|
#include "src/ast/case_statement.h"
|
||||||
#include "src/ast/depth_texture.h"
|
#include "src/ast/depth_texture.h"
|
||||||
#include "src/ast/external_texture.h"
|
#include "src/ast/external_texture.h"
|
||||||
|
@ -1426,6 +1427,14 @@ class ProgramBuilder {
|
||||||
ExprList(std::forward<ARGS>(args)...));
|
ExprList(std::forward<ARGS>(args)...));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @param expr the expression to ignore
|
||||||
|
/// @returns a `ast::CallStatement` that calls the `ignore` intrinsic which is
|
||||||
|
/// passed the single `expr` argument
|
||||||
|
template <typename EXPR>
|
||||||
|
ast::CallStatement* Ignore(EXPR&& expr) {
|
||||||
|
return create<ast::CallStatement>(Call("ignore", Expr(expr)));
|
||||||
|
}
|
||||||
|
|
||||||
/// @param lhs the left hand argument to the addition operation
|
/// @param lhs the left hand argument to the addition operation
|
||||||
/// @param rhs the right hand argument to the addition operation
|
/// @param rhs the right hand argument to the addition operation
|
||||||
/// @returns a `ast::BinaryExpression` summing the arguments `lhs` and `rhs`
|
/// @returns a `ast::BinaryExpression` summing the arguments `lhs` and `rhs`
|
||||||
|
|
|
@ -351,7 +351,7 @@ TEST_P(FloatAllMatching, Scalar) {
|
||||||
params.push_back(Expr(1.0f));
|
params.push_back(Expr(1.0f));
|
||||||
}
|
}
|
||||||
auto* builtin = Call(name, params);
|
auto* builtin = Call(name, params);
|
||||||
Func("func", {}, ty.void_(), {create<ast::CallStatement>(builtin)},
|
Func("func", {}, ty.void_(), {Ignore(builtin)},
|
||||||
{create<ast::StageDecoration>(ast::PipelineStage::kFragment)});
|
{create<ast::StageDecoration>(ast::PipelineStage::kFragment)});
|
||||||
|
|
||||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||||
|
@ -367,7 +367,7 @@ TEST_P(FloatAllMatching, Vec2) {
|
||||||
params.push_back(vec2<f32>(1.0f, 1.0f));
|
params.push_back(vec2<f32>(1.0f, 1.0f));
|
||||||
}
|
}
|
||||||
auto* builtin = Call(name, params);
|
auto* builtin = Call(name, params);
|
||||||
Func("func", {}, ty.void_(), {create<ast::CallStatement>(builtin)},
|
Func("func", {}, ty.void_(), {Ignore(builtin)},
|
||||||
{create<ast::StageDecoration>(ast::PipelineStage::kFragment)});
|
{create<ast::StageDecoration>(ast::PipelineStage::kFragment)});
|
||||||
|
|
||||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||||
|
@ -383,7 +383,7 @@ TEST_P(FloatAllMatching, Vec3) {
|
||||||
params.push_back(vec3<f32>(1.0f, 1.0f, 1.0f));
|
params.push_back(vec3<f32>(1.0f, 1.0f, 1.0f));
|
||||||
}
|
}
|
||||||
auto* builtin = Call(name, params);
|
auto* builtin = Call(name, params);
|
||||||
Func("func", {}, ty.void_(), {create<ast::CallStatement>(builtin)},
|
Func("func", {}, ty.void_(), {Ignore(builtin)},
|
||||||
{create<ast::StageDecoration>(ast::PipelineStage::kFragment)});
|
{create<ast::StageDecoration>(ast::PipelineStage::kFragment)});
|
||||||
|
|
||||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||||
|
@ -399,7 +399,7 @@ TEST_P(FloatAllMatching, Vec4) {
|
||||||
params.push_back(vec4<f32>(1.0f, 1.0f, 1.0f, 1.0f));
|
params.push_back(vec4<f32>(1.0f, 1.0f, 1.0f, 1.0f));
|
||||||
}
|
}
|
||||||
auto* builtin = Call(name, params);
|
auto* builtin = Call(name, params);
|
||||||
Func("func", {}, ty.void_(), {create<ast::CallStatement>(builtin)},
|
Func("func", {}, ty.void_(), {Ignore(builtin)},
|
||||||
{create<ast::StageDecoration>(ast::PipelineStage::kFragment)});
|
{create<ast::StageDecoration>(ast::PipelineStage::kFragment)});
|
||||||
|
|
||||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||||
|
|
|
@ -58,56 +58,6 @@ using u32 = builder::u32;
|
||||||
|
|
||||||
using ResolverCallTest = ResolverTest;
|
using ResolverCallTest = ResolverTest;
|
||||||
|
|
||||||
TEST_F(ResolverCallTest, Recursive_Invalid) {
|
|
||||||
// fn main() {main(); }
|
|
||||||
|
|
||||||
SetSource(Source::Location{12, 34});
|
|
||||||
auto* call_expr = Call("main");
|
|
||||||
ast::VariableList params0;
|
|
||||||
|
|
||||||
Func("main", params0, ty.void_(),
|
|
||||||
ast::StatementList{
|
|
||||||
create<ast::CallStatement>(call_expr),
|
|
||||||
},
|
|
||||||
ast::DecorationList{
|
|
||||||
Stage(ast::PipelineStage::kVertex),
|
|
||||||
});
|
|
||||||
|
|
||||||
EXPECT_FALSE(r()->Resolve());
|
|
||||||
|
|
||||||
EXPECT_EQ(r()->error(),
|
|
||||||
"12:34 error v-0004: recursion is not permitted. 'main' attempted "
|
|
||||||
"to call "
|
|
||||||
"itself.");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(ResolverCallTest, Undeclared_Invalid) {
|
|
||||||
// fn main() {func(); return; }
|
|
||||||
// fn func() { return; }
|
|
||||||
|
|
||||||
SetSource(Source::Location{12, 34});
|
|
||||||
auto* call_expr = Call("func");
|
|
||||||
ast::VariableList params0;
|
|
||||||
|
|
||||||
Func("main", params0, ty.f32(),
|
|
||||||
ast::StatementList{
|
|
||||||
create<ast::CallStatement>(call_expr),
|
|
||||||
Return(),
|
|
||||||
},
|
|
||||||
ast::DecorationList{});
|
|
||||||
|
|
||||||
Func("func", params0, ty.f32(),
|
|
||||||
ast::StatementList{
|
|
||||||
Return(),
|
|
||||||
},
|
|
||||||
ast::DecorationList{});
|
|
||||||
|
|
||||||
EXPECT_FALSE(r()->Resolve());
|
|
||||||
|
|
||||||
EXPECT_EQ(r()->error(),
|
|
||||||
"12:34 error: v-0006: unable to find called function: func");
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Params {
|
struct Params {
|
||||||
builder::ast_expr_func_ptr create_value;
|
builder::ast_expr_func_ptr create_value;
|
||||||
builder::ast_type_func_ptr create_type;
|
builder::ast_type_func_ptr create_type;
|
||||||
|
@ -153,42 +103,6 @@ TEST_F(ResolverCallTest, Valid) {
|
||||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverCallTest, TooFewArgs) {
|
|
||||||
Func("foo", {Param(Sym(), ty.i32()), Param(Sym(), ty.f32())}, ty.void_(),
|
|
||||||
{Return()});
|
|
||||||
auto* call = Call(Source{{12, 34}}, "foo", 1);
|
|
||||||
WrapInFunction(call);
|
|
||||||
|
|
||||||
EXPECT_FALSE(r()->Resolve());
|
|
||||||
EXPECT_EQ(
|
|
||||||
r()->error(),
|
|
||||||
"12:34 error: too few arguments in call to 'foo', expected 2, got 1");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(ResolverCallTest, TooManyArgs) {
|
|
||||||
Func("foo", {Param(Sym(), ty.i32()), Param(Sym(), ty.f32())}, ty.void_(),
|
|
||||||
{Return()});
|
|
||||||
auto* call = Call(Source{{12, 34}}, "foo", 1, 1.0f, 1.0f);
|
|
||||||
WrapInFunction(call);
|
|
||||||
|
|
||||||
EXPECT_FALSE(r()->Resolve());
|
|
||||||
EXPECT_EQ(
|
|
||||||
r()->error(),
|
|
||||||
"12:34 error: too many arguments in call to 'foo', expected 2, got 3");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(ResolverCallTest, MismatchedArgs) {
|
|
||||||
Func("foo", {Param(Sym(), ty.i32()), Param(Sym(), ty.f32())}, ty.void_(),
|
|
||||||
{Return()});
|
|
||||||
auto* call = Call("foo", Expr(Source{{12, 34}}, true), 1.0f);
|
|
||||||
WrapInFunction(call);
|
|
||||||
|
|
||||||
EXPECT_FALSE(r()->Resolve());
|
|
||||||
EXPECT_EQ(r()->error(),
|
|
||||||
"12:34 error: type mismatch for argument 1 in call to 'foo', "
|
|
||||||
"expected 'i32', got 'bool'");
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace resolver
|
} // namespace resolver
|
||||||
} // namespace tint
|
} // namespace tint
|
||||||
|
|
|
@ -0,0 +1,135 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
#include "src/resolver/resolver.h"
|
||||||
|
|
||||||
|
#include "gmock/gmock.h"
|
||||||
|
#include "src/ast/call_statement.h"
|
||||||
|
#include "src/resolver/resolver_test_helper.h"
|
||||||
|
|
||||||
|
namespace tint {
|
||||||
|
namespace resolver {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using ResolverCallValidationTest = ResolverTest;
|
||||||
|
|
||||||
|
TEST_F(ResolverCallValidationTest, Recursive_Invalid) {
|
||||||
|
// fn main() {main(); }
|
||||||
|
|
||||||
|
SetSource(Source::Location{12, 34});
|
||||||
|
auto* call_expr = Call("main");
|
||||||
|
ast::VariableList params0;
|
||||||
|
|
||||||
|
Func("main", params0, ty.void_(),
|
||||||
|
ast::StatementList{
|
||||||
|
create<ast::CallStatement>(call_expr),
|
||||||
|
},
|
||||||
|
ast::DecorationList{
|
||||||
|
Stage(ast::PipelineStage::kVertex),
|
||||||
|
});
|
||||||
|
|
||||||
|
EXPECT_FALSE(r()->Resolve());
|
||||||
|
|
||||||
|
EXPECT_EQ(r()->error(),
|
||||||
|
"12:34 error v-0004: recursion is not permitted. 'main' attempted "
|
||||||
|
"to call "
|
||||||
|
"itself.");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ResolverCallValidationTest, Undeclared_Invalid) {
|
||||||
|
// fn main() {func(); return; }
|
||||||
|
// fn func() { return; }
|
||||||
|
|
||||||
|
SetSource(Source::Location{12, 34});
|
||||||
|
auto* call_expr = Call("func");
|
||||||
|
ast::VariableList params0;
|
||||||
|
|
||||||
|
Func("main", params0, ty.f32(),
|
||||||
|
ast::StatementList{
|
||||||
|
create<ast::CallStatement>(call_expr),
|
||||||
|
Return(),
|
||||||
|
},
|
||||||
|
ast::DecorationList{});
|
||||||
|
|
||||||
|
Func("func", params0, ty.f32(),
|
||||||
|
ast::StatementList{
|
||||||
|
Return(),
|
||||||
|
},
|
||||||
|
ast::DecorationList{});
|
||||||
|
|
||||||
|
EXPECT_FALSE(r()->Resolve());
|
||||||
|
|
||||||
|
EXPECT_EQ(r()->error(),
|
||||||
|
"12:34 error: v-0006: unable to find called function: func");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ResolverCallValidationTest, TooFewArgs) {
|
||||||
|
Func("foo", {Param(Sym(), ty.i32()), Param(Sym(), ty.f32())}, ty.void_(),
|
||||||
|
{Return()});
|
||||||
|
auto* call = Call(Source{{12, 34}}, "foo", 1);
|
||||||
|
WrapInFunction(call);
|
||||||
|
|
||||||
|
EXPECT_FALSE(r()->Resolve());
|
||||||
|
EXPECT_EQ(
|
||||||
|
r()->error(),
|
||||||
|
"12:34 error: too few arguments in call to 'foo', expected 2, got 1");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ResolverCallValidationTest, TooManyArgs) {
|
||||||
|
Func("foo", {Param(Sym(), ty.i32()), Param(Sym(), ty.f32())}, ty.void_(),
|
||||||
|
{Return()});
|
||||||
|
auto* call = Call(Source{{12, 34}}, "foo", 1, 1.0f, 1.0f);
|
||||||
|
WrapInFunction(call);
|
||||||
|
|
||||||
|
EXPECT_FALSE(r()->Resolve());
|
||||||
|
EXPECT_EQ(
|
||||||
|
r()->error(),
|
||||||
|
"12:34 error: too many arguments in call to 'foo', expected 2, got 3");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ResolverCallValidationTest, MismatchedArgs) {
|
||||||
|
Func("foo", {Param(Sym(), ty.i32()), Param(Sym(), ty.f32())}, ty.void_(),
|
||||||
|
{Return()});
|
||||||
|
auto* call = Call("foo", Expr(Source{{12, 34}}, true), 1.0f);
|
||||||
|
WrapInFunction(call);
|
||||||
|
|
||||||
|
EXPECT_FALSE(r()->Resolve());
|
||||||
|
EXPECT_EQ(r()->error(),
|
||||||
|
"12:34 error: type mismatch for argument 1 in call to 'foo', "
|
||||||
|
"expected 'i32', got 'bool'");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ResolverCallValidationTest, UnusedRetval) {
|
||||||
|
// fn main() {func(); return; }
|
||||||
|
// fn func() { return; }
|
||||||
|
|
||||||
|
Func("func", {}, ty.f32(), {Return(Expr(1.0f))}, {});
|
||||||
|
|
||||||
|
Func("main", {}, ty.f32(),
|
||||||
|
ast::StatementList{
|
||||||
|
create<ast::CallStatement>(Source{{12, 34}}, Call("func")),
|
||||||
|
Return(),
|
||||||
|
},
|
||||||
|
{});
|
||||||
|
|
||||||
|
EXPECT_FALSE(r()->Resolve());
|
||||||
|
|
||||||
|
EXPECT_EQ(r()->error(),
|
||||||
|
"12:34 error: result of called function was not used. If this was "
|
||||||
|
"intentional wrap the function call in ignore()");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
} // namespace resolver
|
||||||
|
} // namespace tint
|
|
@ -55,7 +55,7 @@ TEST_P(ResolverIntrinsicDerivativeTest, Scalar) {
|
||||||
Global("ident", ty.f32(), ast::StorageClass::kInput);
|
Global("ident", ty.f32(), ast::StorageClass::kInput);
|
||||||
|
|
||||||
auto* expr = Call(name, "ident");
|
auto* expr = Call(name, "ident");
|
||||||
Func("func", {}, ty.void_(), {create<ast::CallStatement>(expr)},
|
Func("func", {}, ty.void_(), {Ignore(expr)},
|
||||||
{create<ast::StageDecoration>(ast::PipelineStage::kFragment)});
|
{create<ast::StageDecoration>(ast::PipelineStage::kFragment)});
|
||||||
|
|
||||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||||
|
@ -69,7 +69,7 @@ TEST_P(ResolverIntrinsicDerivativeTest, Vector) {
|
||||||
Global("ident", ty.vec4<f32>(), ast::StorageClass::kInput);
|
Global("ident", ty.vec4<f32>(), ast::StorageClass::kInput);
|
||||||
|
|
||||||
auto* expr = Call(name, "ident");
|
auto* expr = Call(name, "ident");
|
||||||
Func("func", {}, ty.void_(), {create<ast::CallStatement>(expr)},
|
Func("func", {}, ty.void_(), {Ignore(expr)},
|
||||||
{create<ast::StageDecoration>(ast::PipelineStage::kFragment)});
|
{create<ast::StageDecoration>(ast::PipelineStage::kFragment)});
|
||||||
|
|
||||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||||
|
@ -1938,7 +1938,7 @@ TEST_P(ResolverIntrinsicTest_Texture, Call) {
|
||||||
param.buildSamplerVariable(this);
|
param.buildSamplerVariable(this);
|
||||||
|
|
||||||
auto* call = Call(param.function, param.args(this));
|
auto* call = Call(param.function, param.args(this));
|
||||||
Func("func", {}, ty.void_(), {create<ast::CallStatement>(call)},
|
Func("func", {}, ty.void_(), {Ignore(call)},
|
||||||
{create<ast::StageDecoration>(ast::PipelineStage::kFragment)});
|
{create<ast::StageDecoration>(ast::PipelineStage::kFragment)});
|
||||||
|
|
||||||
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
||||||
|
|
|
@ -53,8 +53,7 @@ TEST_F(ResolverIntrinsicValidationTest, InvalidPipelineStageDirect) {
|
||||||
|
|
||||||
auto* dpdx = create<ast::CallExpression>(Source{{3, 4}}, Expr("dpdx"),
|
auto* dpdx = create<ast::CallExpression>(Source{{3, 4}}, Expr("dpdx"),
|
||||||
ast::ExpressionList{Expr(1.0f)});
|
ast::ExpressionList{Expr(1.0f)});
|
||||||
Func(Source{{1, 2}}, "func", ast::VariableList{}, ty.void_(),
|
Func(Source{{1, 2}}, "func", ast::VariableList{}, ty.void_(), {Ignore(dpdx)},
|
||||||
{create<ast::CallStatement>(dpdx)},
|
|
||||||
{Stage(ast::PipelineStage::kCompute)});
|
{Stage(ast::PipelineStage::kCompute)});
|
||||||
|
|
||||||
EXPECT_FALSE(r()->Resolve());
|
EXPECT_FALSE(r()->Resolve());
|
||||||
|
@ -70,18 +69,16 @@ TEST_F(ResolverIntrinsicValidationTest, InvalidPipelineStageIndirect) {
|
||||||
|
|
||||||
auto* dpdx = create<ast::CallExpression>(Source{{3, 4}}, Expr("dpdx"),
|
auto* dpdx = create<ast::CallExpression>(Source{{3, 4}}, Expr("dpdx"),
|
||||||
ast::ExpressionList{Expr(1.0f)});
|
ast::ExpressionList{Expr(1.0f)});
|
||||||
Func(Source{{1, 2}}, "f0", ast::VariableList{}, ty.void_(),
|
Func(Source{{1, 2}}, "f0", ast::VariableList{}, ty.void_(), {Ignore(dpdx)});
|
||||||
{create<ast::CallStatement>(dpdx)});
|
|
||||||
|
|
||||||
Func(Source{{3, 4}}, "f1", ast::VariableList{}, ty.void_(),
|
Func(Source{{3, 4}}, "f1", ast::VariableList{}, ty.void_(),
|
||||||
{create<ast::CallStatement>(Call("f0"))});
|
{Ignore(Call("f0"))});
|
||||||
|
|
||||||
Func(Source{{5, 6}}, "f2", ast::VariableList{}, ty.void_(),
|
Func(Source{{5, 6}}, "f2", ast::VariableList{}, ty.void_(),
|
||||||
{create<ast::CallStatement>(Call("f1"))});
|
{Ignore(Call("f1"))});
|
||||||
|
|
||||||
Func(Source{{7, 8}}, "main", ast::VariableList{}, ty.void_(),
|
Func(Source{{7, 8}}, "main", ast::VariableList{}, ty.void_(),
|
||||||
{create<ast::CallStatement>(Call("f2"))},
|
{Ignore(Call("f2"))}, {Stage(ast::PipelineStage::kCompute)});
|
||||||
{Stage(ast::PipelineStage::kCompute)});
|
|
||||||
|
|
||||||
EXPECT_FALSE(r()->Resolve());
|
EXPECT_FALSE(r()->Resolve());
|
||||||
EXPECT_EQ(r()->error(),
|
EXPECT_EQ(r()->error(),
|
||||||
|
|
|
@ -1436,7 +1436,13 @@ bool Resolver::Statement(ast::Statement* stmt) {
|
||||||
}
|
}
|
||||||
if (auto* c = stmt->As<ast::CallStatement>()) {
|
if (auto* c = stmt->As<ast::CallStatement>()) {
|
||||||
Mark(c->expr());
|
Mark(c->expr());
|
||||||
return Expression(c->expr());
|
if (!Expression(c->expr())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!ValidateCallStatement(c)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
if (auto* c = stmt->As<ast::CaseStatement>()) {
|
if (auto* c = stmt->As<ast::CaseStatement>()) {
|
||||||
return CaseStatement(c);
|
return CaseStatement(c);
|
||||||
|
@ -1710,6 +1716,40 @@ bool Resolver::Call(ast::CallExpression* call) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Resolver::ValidateCallStatement(ast::CallStatement* stmt) {
|
||||||
|
const sem::Type* return_type = nullptr;
|
||||||
|
// A function call is made to either a user declared function or an intrinsic.
|
||||||
|
// function_calls_ only maps CallExpression to user declared functions
|
||||||
|
auto it = function_calls_.find(stmt->expr());
|
||||||
|
if (it != function_calls_.end()) {
|
||||||
|
return_type = it->second.function->return_type;
|
||||||
|
} else {
|
||||||
|
// Must be an intrinsic call
|
||||||
|
auto* target = builder_->Sem().Get(stmt->expr())->Target();
|
||||||
|
if (auto* intrinsic = target->As<sem::Intrinsic>()) {
|
||||||
|
return_type = intrinsic->ReturnType();
|
||||||
|
} else {
|
||||||
|
TINT_ICE(diagnostics_) << "call target was not an intrinsic, but a "
|
||||||
|
<< intrinsic->TypeInfo().name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!return_type->Is<sem::Void>()) {
|
||||||
|
// https://gpuweb.github.io/gpuweb/wgsl/#function-call-statement
|
||||||
|
// A function call statement executes a function call where the called
|
||||||
|
// function does not return a value. If the called function returns a value,
|
||||||
|
// that value must be consumed either through assignment, evaluation in
|
||||||
|
// another expression or through use of the ignore built-in function (see
|
||||||
|
// § 16.13 Value-steering functions).
|
||||||
|
diagnostics_.add_error(
|
||||||
|
"result of called function was not used. If this was intentional wrap "
|
||||||
|
"the function call in ignore()",
|
||||||
|
stmt->source());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool Resolver::IntrinsicCall(ast::CallExpression* call,
|
bool Resolver::IntrinsicCall(ast::CallExpression* call,
|
||||||
sem::IntrinsicType intrinsic_type) {
|
sem::IntrinsicType intrinsic_type) {
|
||||||
std::vector<const sem::Type*> arg_tys;
|
std::vector<const sem::Type*> arg_tys;
|
||||||
|
|
|
@ -39,6 +39,7 @@ class BinaryExpression;
|
||||||
class BitcastExpression;
|
class BitcastExpression;
|
||||||
class CallExpression;
|
class CallExpression;
|
||||||
class CaseStatement;
|
class CaseStatement;
|
||||||
|
class CallStatement;
|
||||||
class ConstructorExpression;
|
class ConstructorExpression;
|
||||||
class Function;
|
class Function;
|
||||||
class IdentifierExpression;
|
class IdentifierExpression;
|
||||||
|
@ -255,6 +256,7 @@ class Resolver {
|
||||||
uint32_t el_align,
|
uint32_t el_align,
|
||||||
const Source& source);
|
const Source& source);
|
||||||
bool ValidateAssignment(const ast::AssignmentStatement* a);
|
bool ValidateAssignment(const ast::AssignmentStatement* a);
|
||||||
|
bool ValidateCallStatement(ast::CallStatement* stmt);
|
||||||
bool ValidateEntryPoint(const ast::Function* func, const FunctionInfo* info);
|
bool ValidateEntryPoint(const ast::Function* func, const FunctionInfo* info);
|
||||||
bool ValidateFunction(const ast::Function* func, const FunctionInfo* info);
|
bool ValidateFunction(const ast::Function* func, const FunctionInfo* info);
|
||||||
bool ValidateGlobalVariable(const VariableInfo* var);
|
bool ValidateGlobalVariable(const VariableInfo* var);
|
||||||
|
|
|
@ -266,7 +266,7 @@ TEST_F(ResolverTest, Stmt_Switch) {
|
||||||
|
|
||||||
TEST_F(ResolverTest, Stmt_Call) {
|
TEST_F(ResolverTest, Stmt_Call) {
|
||||||
ast::VariableList params;
|
ast::VariableList params;
|
||||||
Func("my_func", params, ty.f32(), {Return(0.0f)}, ast::DecorationList{});
|
Func("my_func", params, ty.void_(), {Return()}, ast::DecorationList{});
|
||||||
|
|
||||||
auto* expr = Call("my_func");
|
auto* expr = Call("my_func");
|
||||||
|
|
||||||
|
@ -276,7 +276,7 @@ TEST_F(ResolverTest, Stmt_Call) {
|
||||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||||
|
|
||||||
ASSERT_NE(TypeOf(expr), nullptr);
|
ASSERT_NE(TypeOf(expr), nullptr);
|
||||||
EXPECT_TRUE(TypeOf(expr)->Is<sem::F32>());
|
EXPECT_TRUE(TypeOf(expr)->Is<sem::Void>());
|
||||||
EXPECT_EQ(StmtOf(expr), call);
|
EXPECT_EQ(StmtOf(expr), call);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@ fn test(vert_idx : u32) -> u32 {
|
||||||
|
|
||||||
[[stage(vertex)]]
|
[[stage(vertex)]]
|
||||||
fn entry([[builtin(vertex_index)]] vert_idx : u32) -> [[builtin(position)]] vec4<f32> {
|
fn entry([[builtin(vertex_index)]] vert_idx : u32) -> [[builtin(position)]] vec4<f32> {
|
||||||
test(vert_idx);
|
ignore(test(vert_idx));
|
||||||
return vec4<f32>();
|
return vec4<f32>();
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
@ -72,7 +72,7 @@ fn test(vert_idx : u32) -> u32 {
|
||||||
|
|
||||||
[[stage(vertex)]]
|
[[stage(vertex)]]
|
||||||
fn entry([[builtin(vertex_index)]] vert_idx : u32) -> [[builtin(position)]] vec4<f32> {
|
fn entry([[builtin(vertex_index)]] vert_idx : u32) -> [[builtin(position)]] vec4<f32> {
|
||||||
test((vert_idx + tint_symbol_1.first_vertex_index));
|
ignore(test((vert_idx + tint_symbol_1.first_vertex_index)));
|
||||||
return vec4<f32>();
|
return vec4<f32>();
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
@ -100,7 +100,7 @@ fn test(inst_idx : u32) -> u32 {
|
||||||
|
|
||||||
[[stage(vertex)]]
|
[[stage(vertex)]]
|
||||||
fn entry([[builtin(instance_index)]] inst_idx : u32) -> [[builtin(position)]] vec4<f32> {
|
fn entry([[builtin(instance_index)]] inst_idx : u32) -> [[builtin(position)]] vec4<f32> {
|
||||||
test(inst_idx);
|
ignore(test(inst_idx));
|
||||||
return vec4<f32>();
|
return vec4<f32>();
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
@ -119,7 +119,7 @@ fn test(inst_idx : u32) -> u32 {
|
||||||
|
|
||||||
[[stage(vertex)]]
|
[[stage(vertex)]]
|
||||||
fn entry([[builtin(instance_index)]] inst_idx : u32) -> [[builtin(position)]] vec4<f32> {
|
fn entry([[builtin(instance_index)]] inst_idx : u32) -> [[builtin(position)]] vec4<f32> {
|
||||||
test((inst_idx + tint_symbol_1.first_instance_index));
|
ignore(test((inst_idx + tint_symbol_1.first_instance_index)));
|
||||||
return vec4<f32>();
|
return vec4<f32>();
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
@ -152,7 +152,7 @@ struct Inputs {
|
||||||
|
|
||||||
[[stage(vertex)]]
|
[[stage(vertex)]]
|
||||||
fn entry(inputs : Inputs) -> [[builtin(position)]] vec4<f32> {
|
fn entry(inputs : Inputs) -> [[builtin(position)]] vec4<f32> {
|
||||||
test(inputs.instance_idx, inputs.vert_idx);
|
ignore(test(inputs.instance_idx, inputs.vert_idx));
|
||||||
return vec4<f32>();
|
return vec4<f32>();
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
@ -179,7 +179,7 @@ struct Inputs {
|
||||||
|
|
||||||
[[stage(vertex)]]
|
[[stage(vertex)]]
|
||||||
fn entry(inputs : Inputs) -> [[builtin(position)]] vec4<f32> {
|
fn entry(inputs : Inputs) -> [[builtin(position)]] vec4<f32> {
|
||||||
test((inputs.instance_idx + tint_symbol_1.first_instance_index), (inputs.vert_idx + tint_symbol_1.first_vertex_index));
|
ignore(test((inputs.instance_idx + tint_symbol_1.first_instance_index), (inputs.vert_idx + tint_symbol_1.first_vertex_index)));
|
||||||
return vec4<f32>();
|
return vec4<f32>();
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
@ -211,7 +211,7 @@ fn func2(vert_idx : u32) -> u32 {
|
||||||
|
|
||||||
[[stage(vertex)]]
|
[[stage(vertex)]]
|
||||||
fn entry([[builtin(vertex_index)]] vert_idx : u32) -> [[builtin(position)]] vec4<f32> {
|
fn entry([[builtin(vertex_index)]] vert_idx : u32) -> [[builtin(position)]] vec4<f32> {
|
||||||
func2(vert_idx);
|
ignore(func2(vert_idx));
|
||||||
return vec4<f32>();
|
return vec4<f32>();
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
@ -234,7 +234,7 @@ fn func2(vert_idx : u32) -> u32 {
|
||||||
|
|
||||||
[[stage(vertex)]]
|
[[stage(vertex)]]
|
||||||
fn entry([[builtin(vertex_index)]] vert_idx : u32) -> [[builtin(position)]] vec4<f32> {
|
fn entry([[builtin(vertex_index)]] vert_idx : u32) -> [[builtin(position)]] vec4<f32> {
|
||||||
func2((vert_idx + tint_symbol_1.first_vertex_index));
|
ignore(func2((vert_idx + tint_symbol_1.first_vertex_index)));
|
||||||
return vec4<f32>();
|
return vec4<f32>();
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
@ -262,19 +262,19 @@ fn func(i : u32) -> u32 {
|
||||||
|
|
||||||
[[stage(vertex)]]
|
[[stage(vertex)]]
|
||||||
fn entry_a([[builtin(vertex_index)]] vert_idx : u32) -> [[builtin(position)]] vec4<f32> {
|
fn entry_a([[builtin(vertex_index)]] vert_idx : u32) -> [[builtin(position)]] vec4<f32> {
|
||||||
func(vert_idx);
|
ignore(func(vert_idx));
|
||||||
return vec4<f32>();
|
return vec4<f32>();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[stage(vertex)]]
|
[[stage(vertex)]]
|
||||||
fn entry_b([[builtin(vertex_index)]] vert_idx : u32, [[builtin(instance_index)]] inst_idx : u32) -> [[builtin(position)]] vec4<f32> {
|
fn entry_b([[builtin(vertex_index)]] vert_idx : u32, [[builtin(instance_index)]] inst_idx : u32) -> [[builtin(position)]] vec4<f32> {
|
||||||
func(vert_idx + inst_idx);
|
ignore(func(vert_idx + inst_idx));
|
||||||
return vec4<f32>();
|
return vec4<f32>();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[stage(vertex)]]
|
[[stage(vertex)]]
|
||||||
fn entry_c([[builtin(instance_index)]] inst_idx : u32) -> [[builtin(position)]] vec4<f32> {
|
fn entry_c([[builtin(instance_index)]] inst_idx : u32) -> [[builtin(position)]] vec4<f32> {
|
||||||
func(inst_idx);
|
ignore(func(inst_idx));
|
||||||
return vec4<f32>();
|
return vec4<f32>();
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
@ -294,19 +294,19 @@ fn func(i : u32) -> u32 {
|
||||||
|
|
||||||
[[stage(vertex)]]
|
[[stage(vertex)]]
|
||||||
fn entry_a([[builtin(vertex_index)]] vert_idx : u32) -> [[builtin(position)]] vec4<f32> {
|
fn entry_a([[builtin(vertex_index)]] vert_idx : u32) -> [[builtin(position)]] vec4<f32> {
|
||||||
func((vert_idx + tint_symbol_1.first_vertex_index));
|
ignore(func((vert_idx + tint_symbol_1.first_vertex_index)));
|
||||||
return vec4<f32>();
|
return vec4<f32>();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[stage(vertex)]]
|
[[stage(vertex)]]
|
||||||
fn entry_b([[builtin(vertex_index)]] vert_idx : u32, [[builtin(instance_index)]] inst_idx : u32) -> [[builtin(position)]] vec4<f32> {
|
fn entry_b([[builtin(vertex_index)]] vert_idx : u32, [[builtin(instance_index)]] inst_idx : u32) -> [[builtin(position)]] vec4<f32> {
|
||||||
func(((vert_idx + tint_symbol_1.first_vertex_index) + (inst_idx + tint_symbol_1.first_instance_index)));
|
ignore(func(((vert_idx + tint_symbol_1.first_vertex_index) + (inst_idx + tint_symbol_1.first_instance_index))));
|
||||||
return vec4<f32>();
|
return vec4<f32>();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[stage(vertex)]]
|
[[stage(vertex)]]
|
||||||
fn entry_c([[builtin(instance_index)]] inst_idx : u32) -> [[builtin(position)]] vec4<f32> {
|
fn entry_c([[builtin(instance_index)]] inst_idx : u32) -> [[builtin(position)]] vec4<f32> {
|
||||||
func((inst_idx + tint_symbol_1.first_instance_index));
|
ignore(func((inst_idx + tint_symbol_1.first_instance_index)));
|
||||||
return vec4<f32>();
|
return vec4<f32>();
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
@ -338,7 +338,7 @@ fn test() -> u32 {
|
||||||
|
|
||||||
[[stage(vertex)]]
|
[[stage(vertex)]]
|
||||||
fn entry() {
|
fn entry() {
|
||||||
test();
|
ignore(test());
|
||||||
pos = vec4<f32>();
|
pos = vec4<f32>();
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
@ -361,7 +361,7 @@ fn test() -> u32 {
|
||||||
|
|
||||||
[[stage(vertex)]]
|
[[stage(vertex)]]
|
||||||
fn entry() {
|
fn entry() {
|
||||||
test();
|
ignore(test());
|
||||||
pos = vec4<f32>();
|
pos = vec4<f32>();
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
@ -393,7 +393,7 @@ fn test() -> u32 {
|
||||||
|
|
||||||
[[stage(vertex)]]
|
[[stage(vertex)]]
|
||||||
fn entry() {
|
fn entry() {
|
||||||
test();
|
ignore(test());
|
||||||
pos = vec4<f32>();
|
pos = vec4<f32>();
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
@ -416,7 +416,7 @@ fn test() -> u32 {
|
||||||
|
|
||||||
[[stage(vertex)]]
|
[[stage(vertex)]]
|
||||||
fn entry() {
|
fn entry() {
|
||||||
test();
|
ignore(test());
|
||||||
pos = vec4<f32>();
|
pos = vec4<f32>();
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
@ -448,7 +448,7 @@ fn test() -> u32 {
|
||||||
|
|
||||||
[[stage(vertex)]]
|
[[stage(vertex)]]
|
||||||
fn entry() {
|
fn entry() {
|
||||||
test();
|
ignore(test());
|
||||||
pos = vec4<f32>();
|
pos = vec4<f32>();
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
@ -474,7 +474,7 @@ fn test() -> u32 {
|
||||||
|
|
||||||
[[stage(vertex)]]
|
[[stage(vertex)]]
|
||||||
fn entry() {
|
fn entry() {
|
||||||
test();
|
ignore(test());
|
||||||
pos = vec4<f32>();
|
pos = vec4<f32>();
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
@ -509,7 +509,7 @@ fn func2() -> u32 {
|
||||||
|
|
||||||
[[stage(vertex)]]
|
[[stage(vertex)]]
|
||||||
fn entry() {
|
fn entry() {
|
||||||
func2();
|
ignore(func2());
|
||||||
pos = vec4<f32>();
|
pos = vec4<f32>();
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
@ -536,7 +536,7 @@ fn func2() -> u32 {
|
||||||
|
|
||||||
[[stage(vertex)]]
|
[[stage(vertex)]]
|
||||||
fn entry() {
|
fn entry() {
|
||||||
func2();
|
ignore(func2());
|
||||||
pos = vec4<f32>();
|
pos = vec4<f32>();
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
|
|
@ -50,7 +50,7 @@ fn test() -> u32 {
|
||||||
|
|
||||||
[[stage(vertex)]]
|
[[stage(vertex)]]
|
||||||
fn entry() -> [[builtin(position)]] vec4<f32> {
|
fn entry() -> [[builtin(position)]] vec4<f32> {
|
||||||
test();
|
ignore(test());
|
||||||
return vec4<f32>();
|
return vec4<f32>();
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
@ -64,7 +64,7 @@ fn tint_symbol_1() -> u32 {
|
||||||
|
|
||||||
[[stage(vertex)]]
|
[[stage(vertex)]]
|
||||||
fn tint_symbol_2() -> [[builtin(position)]] vec4<f32> {
|
fn tint_symbol_2() -> [[builtin(position)]] vec4<f32> {
|
||||||
tint_symbol_1();
|
ignore(tint_symbol_1());
|
||||||
return vec4<f32>();
|
return vec4<f32>();
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
|
|
@ -166,7 +166,7 @@ TEST_P(HlslIntrinsicTest, Emit) {
|
||||||
|
|
||||||
auto* call = GenerateCall(param.intrinsic, param.type, this);
|
auto* call = GenerateCall(param.intrinsic, param.type, this);
|
||||||
ASSERT_NE(nullptr, call) << "Unhandled intrinsic";
|
ASSERT_NE(nullptr, call) << "Unhandled intrinsic";
|
||||||
Func("func", {}, ty.void_(), {create<ast::CallStatement>(call)},
|
Func("func", {}, ty.void_(), {Ignore(call)},
|
||||||
{create<ast::StageDecoration>(ast::PipelineStage::kFragment)});
|
{create<ast::StageDecoration>(ast::PipelineStage::kFragment)});
|
||||||
|
|
||||||
GeneratorImpl& gen = Build();
|
GeneratorImpl& gen = Build();
|
||||||
|
@ -327,7 +327,7 @@ TEST_F(HlslGeneratorImplTest_Intrinsic, Frexp_Scalar_i32) {
|
||||||
float tint_tmp;
|
float tint_tmp;
|
||||||
float tint_tmp_1 = frexp(1.0f, tint_tmp);
|
float tint_tmp_1 = frexp(1.0f, tint_tmp);
|
||||||
exp = int(tint_tmp);
|
exp = int(tint_tmp);
|
||||||
(void) tint_tmp_1;
|
tint_tmp_1;
|
||||||
)"));
|
)"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,7 +343,7 @@ TEST_F(HlslGeneratorImplTest_Intrinsic, Frexp_Vector_i32) {
|
||||||
float3 tint_tmp;
|
float3 tint_tmp;
|
||||||
float3 tint_tmp_1 = frexp(float3(0.0f, 0.0f, 0.0f), tint_tmp);
|
float3 tint_tmp_1 = frexp(float3(0.0f, 0.0f, 0.0f), tint_tmp);
|
||||||
res = int3(tint_tmp);
|
res = int3(tint_tmp);
|
||||||
(void) tint_tmp_1;
|
tint_tmp_1;
|
||||||
)"));
|
)"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -361,7 +361,7 @@ TEST_P(HlslGeneratorIntrinsicTextureTest, Call) {
|
||||||
|
|
||||||
Func("main", ast::VariableList{}, ty.void_(),
|
Func("main", ast::VariableList{}, ty.void_(),
|
||||||
ast::StatementList{
|
ast::StatementList{
|
||||||
create<ast::CallStatement>(call),
|
Ignore(call),
|
||||||
},
|
},
|
||||||
ast::DecorationList{
|
ast::DecorationList{
|
||||||
Stage(ast::PipelineStage::kFragment),
|
Stage(ast::PipelineStage::kFragment),
|
||||||
|
|
|
@ -360,8 +360,7 @@ TEST_P(HlslDepthTexturesTest, Emit) {
|
||||||
create<ast::GroupDecoration>(2),
|
create<ast::GroupDecoration>(2),
|
||||||
});
|
});
|
||||||
|
|
||||||
Func("main", {}, ty.void_(),
|
Func("main", {}, ty.void_(), {Ignore(Call("textureDimensions", "tex"))},
|
||||||
{create<ast::CallStatement>(Call("textureDimensions", "tex"))},
|
|
||||||
{Stage(ast::PipelineStage::kFragment)});
|
{Stage(ast::PipelineStage::kFragment)});
|
||||||
|
|
||||||
GeneratorImpl& gen = Build();
|
GeneratorImpl& gen = Build();
|
||||||
|
@ -419,8 +418,7 @@ TEST_P(HlslSampledTexturesTest, Emit) {
|
||||||
create<ast::GroupDecoration>(2),
|
create<ast::GroupDecoration>(2),
|
||||||
});
|
});
|
||||||
|
|
||||||
Func("main", {}, ty.void_(),
|
Func("main", {}, ty.void_(), {Ignore(Call("textureDimensions", "tex"))},
|
||||||
{create<ast::CallStatement>(Call("textureDimensions", "tex"))},
|
|
||||||
{Stage(ast::PipelineStage::kFragment)});
|
{Stage(ast::PipelineStage::kFragment)});
|
||||||
|
|
||||||
GeneratorImpl& gen = Build();
|
GeneratorImpl& gen = Build();
|
||||||
|
@ -562,8 +560,7 @@ TEST_P(HlslStorageTexturesTest, Emit) {
|
||||||
create<ast::GroupDecoration>(2),
|
create<ast::GroupDecoration>(2),
|
||||||
});
|
});
|
||||||
|
|
||||||
Func("main", {}, ty.void_(),
|
Func("main", {}, ty.void_(), {Ignore(Call("textureDimensions", "tex"))},
|
||||||
{create<ast::CallStatement>(Call("textureDimensions", "tex"))},
|
|
||||||
{Stage(ast::PipelineStage::kFragment)});
|
{Stage(ast::PipelineStage::kFragment)});
|
||||||
|
|
||||||
GeneratorImpl& gen = Build();
|
GeneratorImpl& gen = Build();
|
||||||
|
|
|
@ -180,7 +180,7 @@ TEST_P(MslIntrinsicTest, Emit) {
|
||||||
|
|
||||||
auto* call = GenerateCall(param.intrinsic, param.type, this);
|
auto* call = GenerateCall(param.intrinsic, param.type, this);
|
||||||
ASSERT_NE(nullptr, call) << "Unhandled intrinsic";
|
ASSERT_NE(nullptr, call) << "Unhandled intrinsic";
|
||||||
Func("func", {}, ty.void_(), {create<ast::CallStatement>(call)},
|
Func("func", {}, ty.void_(), {Ignore(call)},
|
||||||
{create<ast::StageDecoration>(ast::PipelineStage::kFragment)});
|
{create<ast::StageDecoration>(ast::PipelineStage::kFragment)});
|
||||||
|
|
||||||
GeneratorImpl& gen = Build();
|
GeneratorImpl& gen = Build();
|
||||||
|
@ -346,8 +346,7 @@ TEST_F(MslGeneratorImplTest, Ignore) {
|
||||||
Func("f", {Param("a", ty.i32()), Param("b", ty.i32()), Param("c", ty.i32())},
|
Func("f", {Param("a", ty.i32()), Param("b", ty.i32()), Param("c", ty.i32())},
|
||||||
ty.i32(), {Return(Mul(Add("a", "b"), "c"))});
|
ty.i32(), {Return(Mul(Add("a", "b"), "c"))});
|
||||||
|
|
||||||
Func("func", {}, ty.void_(),
|
Func("func", {}, ty.void_(), {Ignore(Call("f", 1, 2, 3))},
|
||||||
{create<ast::CallStatement>(Call("ignore", Call("f", 1, 2, 3)))},
|
|
||||||
{Stage(ast::PipelineStage::kCompute)});
|
{Stage(ast::PipelineStage::kCompute)});
|
||||||
|
|
||||||
GeneratorImpl& gen = Build();
|
GeneratorImpl& gen = Build();
|
||||||
|
|
|
@ -263,7 +263,7 @@ TEST_P(MslGeneratorIntrinsicTextureTest, Call) {
|
||||||
|
|
||||||
Func("main", ast::VariableList{}, ty.void_(),
|
Func("main", ast::VariableList{}, ty.void_(),
|
||||||
ast::StatementList{
|
ast::StatementList{
|
||||||
create<ast::CallStatement>(call),
|
Ignore(call),
|
||||||
},
|
},
|
||||||
ast::DecorationList{
|
ast::DecorationList{
|
||||||
Stage(ast::PipelineStage::kFragment),
|
Stage(ast::PipelineStage::kFragment),
|
||||||
|
|
|
@ -82,7 +82,7 @@ TEST_F(BuilderTest, Statement_Call) {
|
||||||
auto* func =
|
auto* func =
|
||||||
Func("main", {}, ty.void_(), ast::StatementList{}, ast::DecorationList{});
|
Func("main", {}, ty.void_(), ast::StatementList{}, ast::DecorationList{});
|
||||||
|
|
||||||
auto* expr = create<ast::CallStatement>(Call("a_func", 1.f, 1.f));
|
auto* expr = Ignore(Call("a_func", 1.f, 1.f));
|
||||||
|
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ OpName %10 "main"
|
||||||
%1 = OpTypeFunction %2 %2 %2
|
%1 = OpTypeFunction %2 %2 %2
|
||||||
%9 = OpTypeVoid
|
%9 = OpTypeVoid
|
||||||
%8 = OpTypeFunction %9
|
%8 = OpTypeFunction %9
|
||||||
%13 = OpConstant %2 1
|
%14 = OpConstant %2 1
|
||||||
%3 = OpFunction %2 None %1
|
%3 = OpFunction %2 None %1
|
||||||
%4 = OpFunctionParameter %2
|
%4 = OpFunctionParameter %2
|
||||||
%5 = OpFunctionParameter %2
|
%5 = OpFunctionParameter %2
|
||||||
|
@ -110,7 +110,7 @@ OpReturnValue %7
|
||||||
OpFunctionEnd
|
OpFunctionEnd
|
||||||
%10 = OpFunction %9 None %8
|
%10 = OpFunction %9 None %8
|
||||||
%11 = OpLabel
|
%11 = OpLabel
|
||||||
%12 = OpFunctionCall %2 %3 %13 %13
|
%13 = OpFunctionCall %2 %3 %14 %14
|
||||||
OpReturn
|
OpReturn
|
||||||
OpFunctionEnd
|
OpFunctionEnd
|
||||||
)");
|
)");
|
||||||
|
|
|
@ -414,7 +414,7 @@ TEST_P(IntrinsicDeriveTest, Call_Derivative_Scalar) {
|
||||||
auto* var = Global("v", ty.f32(), ast::StorageClass::kPrivate);
|
auto* var = Global("v", ty.f32(), ast::StorageClass::kPrivate);
|
||||||
|
|
||||||
auto* expr = Call(param.name, "v");
|
auto* expr = Call(param.name, "v");
|
||||||
Func("func", {}, ty.void_(), {create<ast::CallStatement>(expr)},
|
Func("func", {}, ty.void_(), {Ignore(expr)},
|
||||||
{create<ast::StageDecoration>(ast::PipelineStage::kFragment)});
|
{create<ast::StageDecoration>(ast::PipelineStage::kFragment)});
|
||||||
|
|
||||||
spirv::Builder& b = Build();
|
spirv::Builder& b = Build();
|
||||||
|
@ -440,7 +440,7 @@ TEST_P(IntrinsicDeriveTest, Call_Derivative_Vector) {
|
||||||
auto* var = Global("v", ty.vec3<f32>(), ast::StorageClass::kPrivate);
|
auto* var = Global("v", ty.vec3<f32>(), ast::StorageClass::kPrivate);
|
||||||
|
|
||||||
auto* expr = Call(param.name, "v");
|
auto* expr = Call(param.name, "v");
|
||||||
Func("func", {}, ty.void_(), {create<ast::CallStatement>(expr)},
|
Func("func", {}, ty.void_(), {Ignore(expr)},
|
||||||
{create<ast::StageDecoration>(ast::PipelineStage::kFragment)});
|
{create<ast::StageDecoration>(ast::PipelineStage::kFragment)});
|
||||||
|
|
||||||
spirv::Builder& b = Build();
|
spirv::Builder& b = Build();
|
||||||
|
@ -538,8 +538,8 @@ TEST_F(IntrinsicBuilderTest, Call_TextureSampleCompare_Twice) {
|
||||||
auto* expr2 = Call("textureSampleCompare", "texture", "sampler",
|
auto* expr2 = Call("textureSampleCompare", "texture", "sampler",
|
||||||
vec2<f32>(1.0f, 2.0f), 2.0f);
|
vec2<f32>(1.0f, 2.0f), 2.0f);
|
||||||
|
|
||||||
Func("f1", {}, ty.void_(), {create<ast::CallStatement>(expr1)}, {});
|
Func("f1", {}, ty.void_(), {Ignore(expr1)}, {});
|
||||||
Func("f2", {}, ty.void_(), {create<ast::CallStatement>(expr2)}, {});
|
Func("f2", {}, ty.void_(), {Ignore(expr2)}, {});
|
||||||
|
|
||||||
spirv::Builder& b = Build();
|
spirv::Builder& b = Build();
|
||||||
|
|
||||||
|
@ -1414,7 +1414,7 @@ TEST_F(IntrinsicBuilderTest, Call_Modf) {
|
||||||
Func("a_func", ast::VariableList{}, ty.void_(),
|
Func("a_func", ast::VariableList{}, ty.void_(),
|
||||||
ast::StatementList{
|
ast::StatementList{
|
||||||
Decl(out),
|
Decl(out),
|
||||||
create<ast::CallStatement>(expr),
|
Ignore(expr),
|
||||||
},
|
},
|
||||||
ast::DecorationList{
|
ast::DecorationList{
|
||||||
Stage(ast::PipelineStage::kFragment),
|
Stage(ast::PipelineStage::kFragment),
|
||||||
|
@ -1425,7 +1425,7 @@ TEST_F(IntrinsicBuilderTest, Call_Modf) {
|
||||||
ASSERT_TRUE(b.Build()) << b.error();
|
ASSERT_TRUE(b.Build()) << b.error();
|
||||||
auto got = DumpBuilder(b);
|
auto got = DumpBuilder(b);
|
||||||
auto* expect = R"(OpCapability Shader
|
auto* expect = R"(OpCapability Shader
|
||||||
%11 = OpExtInstImport "GLSL.std.450"
|
%12 = OpExtInstImport "GLSL.std.450"
|
||||||
OpMemoryModel Logical GLSL450
|
OpMemoryModel Logical GLSL450
|
||||||
OpEntryPoint Fragment %3 "a_func"
|
OpEntryPoint Fragment %3 "a_func"
|
||||||
OpExecutionMode %3 OriginUpperLeft
|
OpExecutionMode %3 OriginUpperLeft
|
||||||
|
@ -1437,13 +1437,13 @@ OpName %5 "out"
|
||||||
%7 = OpTypeVector %8 2
|
%7 = OpTypeVector %8 2
|
||||||
%6 = OpTypePointer Function %7
|
%6 = OpTypePointer Function %7
|
||||||
%9 = OpConstantNull %7
|
%9 = OpConstantNull %7
|
||||||
%12 = OpConstant %8 1
|
%13 = OpConstant %8 1
|
||||||
%13 = OpConstant %8 2
|
%14 = OpConstant %8 2
|
||||||
%14 = OpConstantComposite %7 %12 %13
|
%15 = OpConstantComposite %7 %13 %14
|
||||||
%3 = OpFunction %2 None %1
|
%3 = OpFunction %2 None %1
|
||||||
%4 = OpLabel
|
%4 = OpLabel
|
||||||
%5 = OpVariable %6 Function %9
|
%5 = OpVariable %6 Function %9
|
||||||
%10 = OpExtInst %7 %11 Modf %14 %5
|
%11 = OpExtInst %7 %12 Modf %15 %5
|
||||||
OpReturn
|
OpReturn
|
||||||
OpFunctionEnd
|
OpFunctionEnd
|
||||||
)";
|
)";
|
||||||
|
@ -1458,7 +1458,7 @@ TEST_F(IntrinsicBuilderTest, Call_Frexp) {
|
||||||
Func("a_func", ast::VariableList{}, ty.void_(),
|
Func("a_func", ast::VariableList{}, ty.void_(),
|
||||||
ast::StatementList{
|
ast::StatementList{
|
||||||
Decl(out),
|
Decl(out),
|
||||||
create<ast::CallStatement>(expr),
|
Ignore(expr),
|
||||||
},
|
},
|
||||||
ast::DecorationList{
|
ast::DecorationList{
|
||||||
Stage(ast::PipelineStage::kFragment),
|
Stage(ast::PipelineStage::kFragment),
|
||||||
|
@ -1469,7 +1469,7 @@ TEST_F(IntrinsicBuilderTest, Call_Frexp) {
|
||||||
ASSERT_TRUE(b.Build()) << b.error();
|
ASSERT_TRUE(b.Build()) << b.error();
|
||||||
auto got = DumpBuilder(b);
|
auto got = DumpBuilder(b);
|
||||||
auto* expect = R"(OpCapability Shader
|
auto* expect = R"(OpCapability Shader
|
||||||
%13 = OpExtInstImport "GLSL.std.450"
|
%14 = OpExtInstImport "GLSL.std.450"
|
||||||
OpMemoryModel Logical GLSL450
|
OpMemoryModel Logical GLSL450
|
||||||
OpEntryPoint Fragment %3 "a_func"
|
OpEntryPoint Fragment %3 "a_func"
|
||||||
OpExecutionMode %3 OriginUpperLeft
|
OpExecutionMode %3 OriginUpperLeft
|
||||||
|
@ -1481,15 +1481,15 @@ OpName %5 "out"
|
||||||
%7 = OpTypeVector %8 2
|
%7 = OpTypeVector %8 2
|
||||||
%6 = OpTypePointer Function %7
|
%6 = OpTypePointer Function %7
|
||||||
%9 = OpConstantNull %7
|
%9 = OpConstantNull %7
|
||||||
%12 = OpTypeFloat 32
|
%13 = OpTypeFloat 32
|
||||||
%11 = OpTypeVector %12 2
|
%12 = OpTypeVector %13 2
|
||||||
%14 = OpConstant %12 1
|
%15 = OpConstant %13 1
|
||||||
%15 = OpConstant %12 2
|
%16 = OpConstant %13 2
|
||||||
%16 = OpConstantComposite %11 %14 %15
|
%17 = OpConstantComposite %12 %15 %16
|
||||||
%3 = OpFunction %2 None %1
|
%3 = OpFunction %2 None %1
|
||||||
%4 = OpLabel
|
%4 = OpLabel
|
||||||
%5 = OpVariable %6 Function %9
|
%5 = OpVariable %6 Function %9
|
||||||
%10 = OpExtInst %11 %13 Frexp %16 %5
|
%11 = OpExtInst %12 %14 Frexp %17 %5
|
||||||
OpReturn
|
OpReturn
|
||||||
OpFunctionEnd
|
OpFunctionEnd
|
||||||
)";
|
)";
|
||||||
|
@ -1585,7 +1585,7 @@ TEST_F(IntrinsicBuilderTest, Call_ArrayLength_DEPRECATED) {
|
||||||
|
|
||||||
Func("a_func", ast::VariableList{}, ty.void_(),
|
Func("a_func", ast::VariableList{}, ty.void_(),
|
||||||
ast::StatementList{
|
ast::StatementList{
|
||||||
create<ast::CallStatement>(expr),
|
Ignore(expr),
|
||||||
},
|
},
|
||||||
ast::DecorationList{
|
ast::DecorationList{
|
||||||
Stage(ast::PipelineStage::kFragment),
|
Stage(ast::PipelineStage::kFragment),
|
||||||
|
@ -1604,12 +1604,12 @@ TEST_F(IntrinsicBuilderTest, Call_ArrayLength_DEPRECATED) {
|
||||||
%1 = OpVariable %2 StorageBuffer
|
%1 = OpVariable %2 StorageBuffer
|
||||||
%7 = OpTypeVoid
|
%7 = OpTypeVoid
|
||||||
%6 = OpTypeFunction %7
|
%6 = OpTypeFunction %7
|
||||||
%11 = OpTypeInt 32 0
|
%12 = OpTypeInt 32 0
|
||||||
)";
|
)";
|
||||||
auto got_types = DumpInstructions(b.types());
|
auto got_types = DumpInstructions(b.types());
|
||||||
EXPECT_EQ(expected_types, got_types);
|
EXPECT_EQ(expected_types, got_types);
|
||||||
|
|
||||||
auto* expected_instructions = R"(%10 = OpArrayLength %11 %1 0
|
auto* expected_instructions = R"(%11 = OpArrayLength %12 %1 0
|
||||||
)";
|
)";
|
||||||
auto got_instructions = DumpInstructions(b.functions()[0].instructions());
|
auto got_instructions = DumpInstructions(b.functions()[0].instructions());
|
||||||
EXPECT_EQ(expected_instructions, got_instructions);
|
EXPECT_EQ(expected_instructions, got_instructions);
|
||||||
|
@ -1635,7 +1635,7 @@ TEST_F(IntrinsicBuilderTest, Call_ArrayLength_OtherMembersInStruct_DEPRECATED) {
|
||||||
|
|
||||||
Func("a_func", ast::VariableList{}, ty.void_(),
|
Func("a_func", ast::VariableList{}, ty.void_(),
|
||||||
ast::StatementList{
|
ast::StatementList{
|
||||||
create<ast::CallStatement>(expr),
|
Ignore(expr),
|
||||||
},
|
},
|
||||||
ast::DecorationList{
|
ast::DecorationList{
|
||||||
Stage(ast::PipelineStage::kFragment),
|
Stage(ast::PipelineStage::kFragment),
|
||||||
|
@ -1654,12 +1654,12 @@ TEST_F(IntrinsicBuilderTest, Call_ArrayLength_OtherMembersInStruct_DEPRECATED) {
|
||||||
%1 = OpVariable %2 StorageBuffer
|
%1 = OpVariable %2 StorageBuffer
|
||||||
%7 = OpTypeVoid
|
%7 = OpTypeVoid
|
||||||
%6 = OpTypeFunction %7
|
%6 = OpTypeFunction %7
|
||||||
%11 = OpTypeInt 32 0
|
%12 = OpTypeInt 32 0
|
||||||
)";
|
)";
|
||||||
auto got_types = DumpInstructions(b.types());
|
auto got_types = DumpInstructions(b.types());
|
||||||
EXPECT_EQ(expected_types, got_types);
|
EXPECT_EQ(expected_types, got_types);
|
||||||
|
|
||||||
auto* expected_instructions = R"(%10 = OpArrayLength %11 %1 1
|
auto* expected_instructions = R"(%11 = OpArrayLength %12 %1 1
|
||||||
)";
|
)";
|
||||||
auto got_instructions = DumpInstructions(b.functions()[0].instructions());
|
auto got_instructions = DumpInstructions(b.functions()[0].instructions());
|
||||||
EXPECT_EQ(expected_instructions, got_instructions);
|
EXPECT_EQ(expected_instructions, got_instructions);
|
||||||
|
@ -1680,7 +1680,7 @@ TEST_F(IntrinsicBuilderTest, Call_ArrayLength) {
|
||||||
|
|
||||||
Func("a_func", ast::VariableList{}, ty.void_(),
|
Func("a_func", ast::VariableList{}, ty.void_(),
|
||||||
ast::StatementList{
|
ast::StatementList{
|
||||||
create<ast::CallStatement>(expr),
|
Ignore(expr),
|
||||||
},
|
},
|
||||||
ast::DecorationList{
|
ast::DecorationList{
|
||||||
Stage(ast::PipelineStage::kFragment),
|
Stage(ast::PipelineStage::kFragment),
|
||||||
|
@ -1699,12 +1699,12 @@ TEST_F(IntrinsicBuilderTest, Call_ArrayLength) {
|
||||||
%1 = OpVariable %2 StorageBuffer
|
%1 = OpVariable %2 StorageBuffer
|
||||||
%7 = OpTypeVoid
|
%7 = OpTypeVoid
|
||||||
%6 = OpTypeFunction %7
|
%6 = OpTypeFunction %7
|
||||||
%11 = OpTypeInt 32 0
|
%12 = OpTypeInt 32 0
|
||||||
)";
|
)";
|
||||||
auto got_types = DumpInstructions(b.types());
|
auto got_types = DumpInstructions(b.types());
|
||||||
EXPECT_EQ(expected_types, got_types);
|
EXPECT_EQ(expected_types, got_types);
|
||||||
|
|
||||||
auto* expected_instructions = R"(%10 = OpArrayLength %11 %1 0
|
auto* expected_instructions = R"(%11 = OpArrayLength %12 %1 0
|
||||||
)";
|
)";
|
||||||
auto got_instructions = DumpInstructions(b.functions()[0].instructions());
|
auto got_instructions = DumpInstructions(b.functions()[0].instructions());
|
||||||
EXPECT_EQ(expected_instructions, got_instructions);
|
EXPECT_EQ(expected_instructions, got_instructions);
|
||||||
|
@ -1729,7 +1729,7 @@ TEST_F(IntrinsicBuilderTest, Call_ArrayLength_OtherMembersInStruct) {
|
||||||
|
|
||||||
Func("a_func", ast::VariableList{}, ty.void_(),
|
Func("a_func", ast::VariableList{}, ty.void_(),
|
||||||
ast::StatementList{
|
ast::StatementList{
|
||||||
create<ast::CallStatement>(expr),
|
Ignore(expr),
|
||||||
},
|
},
|
||||||
ast::DecorationList{
|
ast::DecorationList{
|
||||||
Stage(ast::PipelineStage::kFragment),
|
Stage(ast::PipelineStage::kFragment),
|
||||||
|
@ -1748,12 +1748,12 @@ TEST_F(IntrinsicBuilderTest, Call_ArrayLength_OtherMembersInStruct) {
|
||||||
%1 = OpVariable %2 StorageBuffer
|
%1 = OpVariable %2 StorageBuffer
|
||||||
%7 = OpTypeVoid
|
%7 = OpTypeVoid
|
||||||
%6 = OpTypeFunction %7
|
%6 = OpTypeFunction %7
|
||||||
%11 = OpTypeInt 32 0
|
%12 = OpTypeInt 32 0
|
||||||
)";
|
)";
|
||||||
auto got_types = DumpInstructions(b.types());
|
auto got_types = DumpInstructions(b.types());
|
||||||
EXPECT_EQ(expected_types, got_types);
|
EXPECT_EQ(expected_types, got_types);
|
||||||
|
|
||||||
auto* expected_instructions = R"(%10 = OpArrayLength %11 %1 1
|
auto* expected_instructions = R"(%11 = OpArrayLength %12 %1 1
|
||||||
)";
|
)";
|
||||||
auto got_instructions = DumpInstructions(b.functions()[0].instructions());
|
auto got_instructions = DumpInstructions(b.functions()[0].instructions());
|
||||||
EXPECT_EQ(expected_instructions, got_instructions);
|
EXPECT_EQ(expected_instructions, got_instructions);
|
||||||
|
@ -1778,7 +1778,7 @@ TEST_F(IntrinsicBuilderTest, Call_ArrayLength_ViaLets) {
|
||||||
ast::StatementList{
|
ast::StatementList{
|
||||||
Decl(p),
|
Decl(p),
|
||||||
Decl(p2),
|
Decl(p2),
|
||||||
create<ast::CallStatement>(expr),
|
Ignore(expr),
|
||||||
},
|
},
|
||||||
ast::DecorationList{
|
ast::DecorationList{
|
||||||
Stage(ast::PipelineStage::kFragment),
|
Stage(ast::PipelineStage::kFragment),
|
||||||
|
@ -1797,12 +1797,12 @@ TEST_F(IntrinsicBuilderTest, Call_ArrayLength_ViaLets) {
|
||||||
%1 = OpVariable %2 StorageBuffer
|
%1 = OpVariable %2 StorageBuffer
|
||||||
%7 = OpTypeVoid
|
%7 = OpTypeVoid
|
||||||
%6 = OpTypeFunction %7
|
%6 = OpTypeFunction %7
|
||||||
%11 = OpTypeInt 32 0
|
%12 = OpTypeInt 32 0
|
||||||
)";
|
)";
|
||||||
auto got_types = DumpInstructions(b.types());
|
auto got_types = DumpInstructions(b.types());
|
||||||
EXPECT_EQ(expected_types, got_types);
|
EXPECT_EQ(expected_types, got_types);
|
||||||
|
|
||||||
auto* expected_instructions = R"(%10 = OpArrayLength %11 %1 0
|
auto* expected_instructions = R"(%11 = OpArrayLength %12 %1 0
|
||||||
)";
|
)";
|
||||||
auto got_instructions = DumpInstructions(b.functions()[0].instructions());
|
auto got_instructions = DumpInstructions(b.functions()[0].instructions());
|
||||||
EXPECT_EQ(expected_instructions, got_instructions);
|
EXPECT_EQ(expected_instructions, got_instructions);
|
||||||
|
@ -1839,7 +1839,7 @@ TEST_F(IntrinsicBuilderTest, Call_ArrayLength_ViaLets_WithPtrNoise) {
|
||||||
Decl(p),
|
Decl(p),
|
||||||
Decl(p2),
|
Decl(p2),
|
||||||
Decl(p3),
|
Decl(p3),
|
||||||
create<ast::CallStatement>(expr),
|
Ignore(expr),
|
||||||
},
|
},
|
||||||
ast::DecorationList{
|
ast::DecorationList{
|
||||||
Stage(ast::PipelineStage::kFragment),
|
Stage(ast::PipelineStage::kFragment),
|
||||||
|
@ -1858,12 +1858,12 @@ TEST_F(IntrinsicBuilderTest, Call_ArrayLength_ViaLets_WithPtrNoise) {
|
||||||
%1 = OpVariable %2 StorageBuffer
|
%1 = OpVariable %2 StorageBuffer
|
||||||
%7 = OpTypeVoid
|
%7 = OpTypeVoid
|
||||||
%6 = OpTypeFunction %7
|
%6 = OpTypeFunction %7
|
||||||
%11 = OpTypeInt 32 0
|
%12 = OpTypeInt 32 0
|
||||||
)";
|
)";
|
||||||
auto got_types = DumpInstructions(b.types());
|
auto got_types = DumpInstructions(b.types());
|
||||||
EXPECT_EQ(expected_types, got_types);
|
EXPECT_EQ(expected_types, got_types);
|
||||||
|
|
||||||
auto* expected_instructions = R"(%10 = OpArrayLength %11 %1 0
|
auto* expected_instructions = R"(%11 = OpArrayLength %12 %1 0
|
||||||
)";
|
)";
|
||||||
auto got_instructions = DumpInstructions(b.functions()[0].instructions());
|
auto got_instructions = DumpInstructions(b.functions()[0].instructions());
|
||||||
EXPECT_EQ(expected_instructions, got_instructions);
|
EXPECT_EQ(expected_instructions, got_instructions);
|
||||||
|
|
|
@ -3460,10 +3460,9 @@ TEST_P(IntrinsicTextureTest, Call) {
|
||||||
auto* texture = param.buildTextureVariable(this);
|
auto* texture = param.buildTextureVariable(this);
|
||||||
auto* sampler = param.buildSamplerVariable(this);
|
auto* sampler = param.buildSamplerVariable(this);
|
||||||
|
|
||||||
auto* call =
|
auto* call = Call(param.function, param.args(this));
|
||||||
create<ast::CallExpression>(Expr(param.function), param.args(this));
|
|
||||||
|
|
||||||
Func("func", {}, ty.void_(), {create<ast::CallStatement>(call)},
|
Func("func", {}, ty.void_(), {Ignore(call)},
|
||||||
{create<ast::StageDecoration>(ast::PipelineStage::kFragment)});
|
{create<ast::StageDecoration>(ast::PipelineStage::kFragment)});
|
||||||
|
|
||||||
spirv::Builder& b = Build();
|
spirv::Builder& b = Build();
|
||||||
|
@ -3488,12 +3487,11 @@ TEST_P(IntrinsicTextureTest, ValidateSPIRV) {
|
||||||
param.buildTextureVariable(this);
|
param.buildTextureVariable(this);
|
||||||
param.buildSamplerVariable(this);
|
param.buildSamplerVariable(this);
|
||||||
|
|
||||||
auto* call =
|
auto* call = Call(param.function, param.args(this));
|
||||||
create<ast::CallExpression>(Expr(param.function), param.args(this));
|
|
||||||
|
|
||||||
Func("main", ast::VariableList{}, ty.void_(),
|
Func("main", ast::VariableList{}, ty.void_(),
|
||||||
ast::StatementList{
|
ast::StatementList{
|
||||||
create<ast::CallStatement>(call),
|
Ignore(call),
|
||||||
},
|
},
|
||||||
ast::DecorationList{
|
ast::DecorationList{
|
||||||
Stage(ast::PipelineStage::kFragment),
|
Stage(ast::PipelineStage::kFragment),
|
||||||
|
@ -3515,9 +3513,8 @@ TEST_P(IntrinsicTextureTest, OutsideFunction_IsError) {
|
||||||
auto* texture = param.buildTextureVariable(this);
|
auto* texture = param.buildTextureVariable(this);
|
||||||
auto* sampler = param.buildSamplerVariable(this);
|
auto* sampler = param.buildSamplerVariable(this);
|
||||||
|
|
||||||
auto* call =
|
auto* call = Call(param.function, param.args(this));
|
||||||
create<ast::CallExpression>(Expr(param.function), param.args(this));
|
Func("func", {}, ty.void_(), {Ignore(call)},
|
||||||
Func("func", {}, ty.void_(), {create<ast::CallStatement>(call)},
|
|
||||||
{create<ast::StageDecoration>(ast::PipelineStage::kFragment)});
|
{create<ast::StageDecoration>(ast::PipelineStage::kFragment)});
|
||||||
|
|
||||||
spirv::Builder& b = Build();
|
spirv::Builder& b = Build();
|
||||||
|
|
|
@ -226,6 +226,7 @@ tint_unittests_source_set("tint_unittests_core_src") {
|
||||||
"../src/resolver/block_test.cc",
|
"../src/resolver/block_test.cc",
|
||||||
"../src/resolver/builtins_validation_test.cc",
|
"../src/resolver/builtins_validation_test.cc",
|
||||||
"../src/resolver/call_test.cc",
|
"../src/resolver/call_test.cc",
|
||||||
|
"../src/resolver/call_validation_test.cc",
|
||||||
"../src/resolver/control_block_validation_test.cc",
|
"../src/resolver/control_block_validation_test.cc",
|
||||||
"../src/resolver/decoration_validation_test.cc",
|
"../src/resolver/decoration_validation_test.cc",
|
||||||
"../src/resolver/entry_point_validation_test.cc",
|
"../src/resolver/entry_point_validation_test.cc",
|
||||||
|
|
Loading…
Reference in New Issue