Remove cast operator.
This CL removes the cast operator and converts the tests over to using type constructors. Bug: tint:241 Change-Id: I2526acb61f5624b2e1c068612a2ddcc748c92aed Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/28860 Commit-Queue: dan sinclair <dsinclair@chromium.org> Reviewed-by: Ryan Harrison <rharrison@chromium.org>
This commit is contained in:
parent
f367eadeef
commit
3c02592718
4
BUILD.gn
4
BUILD.gn
|
@ -243,8 +243,6 @@ source_set("libtint_core_src") {
|
||||||
"src/ast/call_statement.h",
|
"src/ast/call_statement.h",
|
||||||
"src/ast/case_statement.cc",
|
"src/ast/case_statement.cc",
|
||||||
"src/ast/case_statement.h",
|
"src/ast/case_statement.h",
|
||||||
"src/ast/cast_expression.cc",
|
|
||||||
"src/ast/cast_expression.h",
|
|
||||||
"src/ast/constructor_expression.cc",
|
"src/ast/constructor_expression.cc",
|
||||||
"src/ast/constructor_expression.h",
|
"src/ast/constructor_expression.h",
|
||||||
"src/ast/continue_statement.cc",
|
"src/ast/continue_statement.cc",
|
||||||
|
@ -697,7 +695,6 @@ source_set("tint_unittests_core_src") {
|
||||||
"src/ast/call_expression_test.cc",
|
"src/ast/call_expression_test.cc",
|
||||||
"src/ast/call_statement_test.cc",
|
"src/ast/call_statement_test.cc",
|
||||||
"src/ast/case_statement_test.cc",
|
"src/ast/case_statement_test.cc",
|
||||||
"src/ast/cast_expression_test.cc",
|
|
||||||
"src/ast/continue_statement_test.cc",
|
"src/ast/continue_statement_test.cc",
|
||||||
"src/ast/decorated_variable_test.cc",
|
"src/ast/decorated_variable_test.cc",
|
||||||
"src/ast/discard_statement_test.cc",
|
"src/ast/discard_statement_test.cc",
|
||||||
|
@ -831,7 +828,6 @@ source_set("tint_unittests_spv_writer_src") {
|
||||||
"src/writer/spirv/builder_bitcast_expression_test.cc",
|
"src/writer/spirv/builder_bitcast_expression_test.cc",
|
||||||
"src/writer/spirv/builder_block_test.cc",
|
"src/writer/spirv/builder_block_test.cc",
|
||||||
"src/writer/spirv/builder_call_test.cc",
|
"src/writer/spirv/builder_call_test.cc",
|
||||||
"src/writer/spirv/builder_cast_expression_test.cc",
|
|
||||||
"src/writer/spirv/builder_constructor_expression_test.cc",
|
"src/writer/spirv/builder_constructor_expression_test.cc",
|
||||||
"src/writer/spirv/builder_discard_test.cc",
|
"src/writer/spirv/builder_discard_test.cc",
|
||||||
"src/writer/spirv/builder_format_conversion_test.cc",
|
"src/writer/spirv/builder_format_conversion_test.cc",
|
||||||
|
|
|
@ -64,8 +64,6 @@ set(TINT_LIB_SRCS
|
||||||
ast/call_statement.h
|
ast/call_statement.h
|
||||||
ast/case_statement.cc
|
ast/case_statement.cc
|
||||||
ast/case_statement.h
|
ast/case_statement.h
|
||||||
ast/cast_expression.cc
|
|
||||||
ast/cast_expression.h
|
|
||||||
ast/constructor_expression.cc
|
ast/constructor_expression.cc
|
||||||
ast/constructor_expression.h
|
ast/constructor_expression.h
|
||||||
ast/continue_statement.cc
|
ast/continue_statement.cc
|
||||||
|
@ -306,7 +304,6 @@ set(TINT_TEST_SRCS
|
||||||
ast/call_expression_test.cc
|
ast/call_expression_test.cc
|
||||||
ast/call_statement_test.cc
|
ast/call_statement_test.cc
|
||||||
ast/case_statement_test.cc
|
ast/case_statement_test.cc
|
||||||
ast/cast_expression_test.cc
|
|
||||||
ast/continue_statement_test.cc
|
ast/continue_statement_test.cc
|
||||||
ast/discard_statement_test.cc
|
ast/discard_statement_test.cc
|
||||||
ast/decorated_variable_test.cc
|
ast/decorated_variable_test.cc
|
||||||
|
@ -489,7 +486,6 @@ if(${TINT_BUILD_SPV_WRITER})
|
||||||
writer/spirv/builder_bitcast_expression_test.cc
|
writer/spirv/builder_bitcast_expression_test.cc
|
||||||
writer/spirv/builder_block_test.cc
|
writer/spirv/builder_block_test.cc
|
||||||
writer/spirv/builder_call_test.cc
|
writer/spirv/builder_call_test.cc
|
||||||
writer/spirv/builder_cast_expression_test.cc
|
|
||||||
writer/spirv/builder_constructor_expression_test.cc
|
writer/spirv/builder_constructor_expression_test.cc
|
||||||
writer/spirv/builder_discard_test.cc
|
writer/spirv/builder_discard_test.cc
|
||||||
writer/spirv/builder_format_conversion_test.cc
|
writer/spirv/builder_format_conversion_test.cc
|
||||||
|
|
|
@ -1,54 +0,0 @@
|
||||||
// Copyright 2020 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/ast/cast_expression.h"
|
|
||||||
|
|
||||||
namespace tint {
|
|
||||||
namespace ast {
|
|
||||||
|
|
||||||
CastExpression::CastExpression() : Expression() {}
|
|
||||||
|
|
||||||
CastExpression::CastExpression(type::Type* type,
|
|
||||||
std::unique_ptr<Expression> expr)
|
|
||||||
: Expression(), type_(type), expr_(std::move(expr)) {}
|
|
||||||
|
|
||||||
CastExpression::CastExpression(const Source& source,
|
|
||||||
type::Type* type,
|
|
||||||
std::unique_ptr<Expression> expr)
|
|
||||||
: Expression(source), type_(type), expr_(std::move(expr)) {}
|
|
||||||
|
|
||||||
CastExpression::CastExpression(CastExpression&&) = default;
|
|
||||||
|
|
||||||
CastExpression::~CastExpression() = default;
|
|
||||||
|
|
||||||
bool CastExpression::IsCast() const {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CastExpression::IsValid() const {
|
|
||||||
if (expr_ == nullptr || !expr_->IsValid())
|
|
||||||
return false;
|
|
||||||
return type_ != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CastExpression::to_str(std::ostream& out, size_t indent) const {
|
|
||||||
make_indent(out, indent);
|
|
||||||
out << "Cast<" << type_->type_name() << ">(" << std::endl;
|
|
||||||
expr_->to_str(out, indent + 2);
|
|
||||||
make_indent(out, indent);
|
|
||||||
out << ")" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ast
|
|
||||||
} // namespace tint
|
|
|
@ -1,81 +0,0 @@
|
||||||
// Copyright 2020 The Tint Authors.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#ifndef SRC_AST_CAST_EXPRESSION_H_
|
|
||||||
#define SRC_AST_CAST_EXPRESSION_H_
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
#include "src/ast/expression.h"
|
|
||||||
#include "src/ast/literal.h"
|
|
||||||
#include "src/ast/type/type.h"
|
|
||||||
|
|
||||||
namespace tint {
|
|
||||||
namespace ast {
|
|
||||||
|
|
||||||
/// A cast expression
|
|
||||||
class CastExpression : public Expression {
|
|
||||||
public:
|
|
||||||
/// Constructor
|
|
||||||
CastExpression();
|
|
||||||
/// Constructor
|
|
||||||
/// @param type the type
|
|
||||||
/// @param expr the expr
|
|
||||||
CastExpression(type::Type* type, std::unique_ptr<Expression> expr);
|
|
||||||
/// Constructor
|
|
||||||
/// @param source the cast expression source
|
|
||||||
/// @param type the type
|
|
||||||
/// @param expr the expr
|
|
||||||
CastExpression(const Source& source,
|
|
||||||
type::Type* type,
|
|
||||||
std::unique_ptr<Expression> expr);
|
|
||||||
/// Move constructor
|
|
||||||
CastExpression(CastExpression&&);
|
|
||||||
~CastExpression() override;
|
|
||||||
|
|
||||||
/// Sets the type
|
|
||||||
/// @param type the type
|
|
||||||
void set_type(type::Type* type) { type_ = std::move(type); }
|
|
||||||
/// @returns the left side expression
|
|
||||||
type::Type* type() const { return type_; }
|
|
||||||
|
|
||||||
/// Sets the expr
|
|
||||||
/// @param expr the expression
|
|
||||||
void set_expr(std::unique_ptr<Expression> expr) { expr_ = std::move(expr); }
|
|
||||||
/// @returns the expression
|
|
||||||
Expression* expr() const { return expr_.get(); }
|
|
||||||
|
|
||||||
/// @returns true if this is a cast expression
|
|
||||||
bool IsCast() const override;
|
|
||||||
|
|
||||||
/// @returns true if the node is valid
|
|
||||||
bool IsValid() const override;
|
|
||||||
|
|
||||||
/// Writes a representation of the node to the output stream
|
|
||||||
/// @param out the stream to write to
|
|
||||||
/// @param indent number of spaces to indent the node when writing
|
|
||||||
void to_str(std::ostream& out, size_t indent) const override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
CastExpression(const CastExpression&) = delete;
|
|
||||||
|
|
||||||
type::Type* type_ = nullptr;
|
|
||||||
std::unique_ptr<Expression> expr_;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace ast
|
|
||||||
} // namespace tint
|
|
||||||
|
|
||||||
#endif // SRC_AST_CAST_EXPRESSION_H_
|
|
|
@ -1,98 +0,0 @@
|
||||||
// Copyright 2020 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/ast/cast_expression.h"
|
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
|
||||||
#include "src/ast/identifier_expression.h"
|
|
||||||
#include "src/ast/type/f32_type.h"
|
|
||||||
|
|
||||||
namespace tint {
|
|
||||||
namespace ast {
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
using CastExpressionTest = testing::Test;
|
|
||||||
|
|
||||||
TEST_F(CastExpressionTest, Creation) {
|
|
||||||
type::F32Type f32;
|
|
||||||
auto expr = std::make_unique<IdentifierExpression>("expr");
|
|
||||||
auto* expr_ptr = expr.get();
|
|
||||||
|
|
||||||
CastExpression c(&f32, std::move(expr));
|
|
||||||
EXPECT_EQ(c.type(), &f32);
|
|
||||||
EXPECT_EQ(c.expr(), expr_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(CastExpressionTest, Creation_withSource) {
|
|
||||||
type::F32Type f32;
|
|
||||||
auto expr = std::make_unique<IdentifierExpression>("expr");
|
|
||||||
|
|
||||||
CastExpression c(Source{20, 2}, &f32, std::move(expr));
|
|
||||||
auto src = c.source();
|
|
||||||
EXPECT_EQ(src.line, 20u);
|
|
||||||
EXPECT_EQ(src.column, 2u);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(CastExpressionTest, IsCast) {
|
|
||||||
CastExpression c;
|
|
||||||
EXPECT_TRUE(c.IsCast());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(CastExpressionTest, IsValid) {
|
|
||||||
type::F32Type f32;
|
|
||||||
auto expr = std::make_unique<IdentifierExpression>("expr");
|
|
||||||
|
|
||||||
CastExpression c(&f32, std::move(expr));
|
|
||||||
EXPECT_TRUE(c.IsValid());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(CastExpressionTest, IsValid_MissingType) {
|
|
||||||
auto expr = std::make_unique<IdentifierExpression>("expr");
|
|
||||||
|
|
||||||
CastExpression c;
|
|
||||||
c.set_expr(std::move(expr));
|
|
||||||
EXPECT_FALSE(c.IsValid());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(CastExpressionTest, IsValid_MissingExpression) {
|
|
||||||
type::F32Type f32;
|
|
||||||
|
|
||||||
CastExpression c;
|
|
||||||
c.set_type(&f32);
|
|
||||||
EXPECT_FALSE(c.IsValid());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(CastExpressionTest, IsValid_InvalidExpression) {
|
|
||||||
type::F32Type f32;
|
|
||||||
auto expr = std::make_unique<IdentifierExpression>("");
|
|
||||||
CastExpression c(&f32, std::move(expr));
|
|
||||||
EXPECT_FALSE(c.IsValid());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(CastExpressionTest, ToStr) {
|
|
||||||
type::F32Type f32;
|
|
||||||
auto expr = std::make_unique<IdentifierExpression>("expr");
|
|
||||||
|
|
||||||
CastExpression c(Source{20, 2}, &f32, std::move(expr));
|
|
||||||
std::ostringstream out;
|
|
||||||
c.to_str(out, 2);
|
|
||||||
EXPECT_EQ(out.str(), R"( Cast<__f32>(
|
|
||||||
Identifier{expr}
|
|
||||||
)
|
|
||||||
)");
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
} // namespace ast
|
|
||||||
} // namespace tint
|
|
|
@ -20,7 +20,6 @@
|
||||||
#include "src/ast/binary_expression.h"
|
#include "src/ast/binary_expression.h"
|
||||||
#include "src/ast/bitcast_expression.h"
|
#include "src/ast/bitcast_expression.h"
|
||||||
#include "src/ast/call_expression.h"
|
#include "src/ast/call_expression.h"
|
||||||
#include "src/ast/cast_expression.h"
|
|
||||||
#include "src/ast/constructor_expression.h"
|
#include "src/ast/constructor_expression.h"
|
||||||
#include "src/ast/identifier_expression.h"
|
#include "src/ast/identifier_expression.h"
|
||||||
#include "src/ast/member_accessor_expression.h"
|
#include "src/ast/member_accessor_expression.h"
|
||||||
|
@ -96,11 +95,6 @@ const CallExpression* Expression::AsCall() const {
|
||||||
return static_cast<const CallExpression*>(this);
|
return static_cast<const CallExpression*>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
const CastExpression* Expression::AsCast() const {
|
|
||||||
assert(IsCast());
|
|
||||||
return static_cast<const CastExpression*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
const ConstructorExpression* Expression::AsConstructor() const {
|
const ConstructorExpression* Expression::AsConstructor() const {
|
||||||
assert(IsConstructor());
|
assert(IsConstructor());
|
||||||
return static_cast<const ConstructorExpression*>(this);
|
return static_cast<const ConstructorExpression*>(this);
|
||||||
|
@ -141,11 +135,6 @@ CallExpression* Expression::AsCall() {
|
||||||
return static_cast<CallExpression*>(this);
|
return static_cast<CallExpression*>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
CastExpression* Expression::AsCast() {
|
|
||||||
assert(IsCast());
|
|
||||||
return static_cast<CastExpression*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
ConstructorExpression* Expression::AsConstructor() {
|
ConstructorExpression* Expression::AsConstructor() {
|
||||||
assert(IsConstructor());
|
assert(IsConstructor());
|
||||||
return static_cast<ConstructorExpression*>(this);
|
return static_cast<ConstructorExpression*>(this);
|
||||||
|
|
|
@ -28,7 +28,6 @@ class ArrayAccessorExpression;
|
||||||
class BinaryExpression;
|
class BinaryExpression;
|
||||||
class BitcastExpression;
|
class BitcastExpression;
|
||||||
class CallExpression;
|
class CallExpression;
|
||||||
class CastExpression;
|
|
||||||
class IdentifierExpression;
|
class IdentifierExpression;
|
||||||
class ConstructorExpression;
|
class ConstructorExpression;
|
||||||
class MemberAccessorExpression;
|
class MemberAccessorExpression;
|
||||||
|
@ -70,8 +69,6 @@ class Expression : public Node {
|
||||||
const BitcastExpression* AsBitcast() const;
|
const BitcastExpression* AsBitcast() const;
|
||||||
/// @returns the expression as a call
|
/// @returns the expression as a call
|
||||||
const CallExpression* AsCall() const;
|
const CallExpression* AsCall() const;
|
||||||
/// @returns the expression as a cast
|
|
||||||
const CastExpression* AsCast() const;
|
|
||||||
/// @returns the expression as an identifier
|
/// @returns the expression as an identifier
|
||||||
const IdentifierExpression* AsIdentifier() const;
|
const IdentifierExpression* AsIdentifier() const;
|
||||||
/// @returns the expression as an constructor
|
/// @returns the expression as an constructor
|
||||||
|
@ -89,8 +86,6 @@ class Expression : public Node {
|
||||||
BitcastExpression* AsBitcast();
|
BitcastExpression* AsBitcast();
|
||||||
/// @returns the expression as a call
|
/// @returns the expression as a call
|
||||||
CallExpression* AsCall();
|
CallExpression* AsCall();
|
||||||
/// @returns the expression as a cast
|
|
||||||
CastExpression* AsCast();
|
|
||||||
/// @returns the expression as an identifier
|
/// @returns the expression as an identifier
|
||||||
IdentifierExpression* AsIdentifier();
|
IdentifierExpression* AsIdentifier();
|
||||||
/// @returns the expression as an constructor
|
/// @returns the expression as an constructor
|
||||||
|
|
|
@ -109,6 +109,10 @@ bool Type::IsVoid() const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Type::is_scalar() {
|
||||||
|
return is_float_scalar() || is_integer_scalar() || IsBool();
|
||||||
|
}
|
||||||
|
|
||||||
bool Type::is_float_scalar() {
|
bool Type::is_float_scalar() {
|
||||||
return IsF32();
|
return IsF32();
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,6 +90,8 @@ class Type {
|
||||||
/// @returns the unwrapped type
|
/// @returns the unwrapped type
|
||||||
Type* UnwrapAliasPtrAlias();
|
Type* UnwrapAliasPtrAlias();
|
||||||
|
|
||||||
|
/// @returns true if this type is a scalar
|
||||||
|
bool is_scalar();
|
||||||
/// @returns true if this type is a float scalar
|
/// @returns true if this type is a float scalar
|
||||||
bool is_float_scalar();
|
bool is_float_scalar();
|
||||||
/// @returns true if this type is a float matrix
|
/// @returns true if this type is a float matrix
|
||||||
|
|
|
@ -36,7 +36,6 @@
|
||||||
#include "src/ast/call_expression.h"
|
#include "src/ast/call_expression.h"
|
||||||
#include "src/ast/call_statement.h"
|
#include "src/ast/call_statement.h"
|
||||||
#include "src/ast/case_statement.h"
|
#include "src/ast/case_statement.h"
|
||||||
#include "src/ast/cast_expression.h"
|
|
||||||
#include "src/ast/continue_statement.h"
|
#include "src/ast/continue_statement.h"
|
||||||
#include "src/ast/discard_statement.h"
|
#include "src/ast/discard_statement.h"
|
||||||
#include "src/ast/else_statement.h"
|
#include "src/ast/else_statement.h"
|
||||||
|
@ -3463,8 +3462,11 @@ TypedExpression FunctionEmitter::MakeNumericConversion(
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
TypedExpression result(expr_type, std::make_unique<ast::CastExpression>(
|
ast::ExpressionList params;
|
||||||
expr_type, std::move(arg_expr.expr)));
|
params.push_back(std::move(arg_expr.expr));
|
||||||
|
TypedExpression result(expr_type,
|
||||||
|
std::make_unique<ast::TypeConstructorExpression>(
|
||||||
|
expr_type, std::move(params)));
|
||||||
|
|
||||||
if (requested_type == expr_type) {
|
if (requested_type == expr_type) {
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -243,9 +243,10 @@ TEST_F(SpvUnaryConversionTest, ConvertSToF_Scalar_FromSigned) {
|
||||||
none
|
none
|
||||||
__f32
|
__f32
|
||||||
{
|
{
|
||||||
Cast<__f32>(
|
TypeConstructor{
|
||||||
|
__f32
|
||||||
Identifier{x_30}
|
Identifier{x_30}
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
})"))
|
})"))
|
||||||
<< ToString(fe.ast_body());
|
<< ToString(fe.ast_body());
|
||||||
|
@ -269,11 +270,12 @@ TEST_F(SpvUnaryConversionTest, ConvertSToF_Scalar_FromUnsigned) {
|
||||||
none
|
none
|
||||||
__f32
|
__f32
|
||||||
{
|
{
|
||||||
Cast<__f32>(
|
TypeConstructor{
|
||||||
|
__f32
|
||||||
Bitcast<__i32>{
|
Bitcast<__i32>{
|
||||||
Identifier{x_30}
|
Identifier{x_30}
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
})"))
|
})"))
|
||||||
<< ToString(fe.ast_body());
|
<< ToString(fe.ast_body());
|
||||||
|
@ -297,9 +299,10 @@ TEST_F(SpvUnaryConversionTest, ConvertSToF_Vector_FromSigned) {
|
||||||
none
|
none
|
||||||
__vec_2__f32
|
__vec_2__f32
|
||||||
{
|
{
|
||||||
Cast<__vec_2__f32>(
|
TypeConstructor{
|
||||||
|
__vec_2__f32
|
||||||
Identifier{x_30}
|
Identifier{x_30}
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
})"))
|
})"))
|
||||||
<< ToString(fe.ast_body());
|
<< ToString(fe.ast_body());
|
||||||
|
@ -323,11 +326,12 @@ TEST_F(SpvUnaryConversionTest, ConvertSToF_Vector_FromUnsigned) {
|
||||||
none
|
none
|
||||||
__vec_2__f32
|
__vec_2__f32
|
||||||
{
|
{
|
||||||
Cast<__vec_2__f32>(
|
TypeConstructor{
|
||||||
|
__vec_2__f32
|
||||||
Bitcast<__vec_2__i32>{
|
Bitcast<__vec_2__i32>{
|
||||||
Identifier{x_30}
|
Identifier{x_30}
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
})"))
|
})"))
|
||||||
<< ToString(fe.ast_body());
|
<< ToString(fe.ast_body());
|
||||||
|
@ -384,11 +388,12 @@ TEST_F(SpvUnaryConversionTest, ConvertUToF_Scalar_FromSigned) {
|
||||||
none
|
none
|
||||||
__f32
|
__f32
|
||||||
{
|
{
|
||||||
Cast<__f32>(
|
TypeConstructor{
|
||||||
|
__f32
|
||||||
Bitcast<__u32>{
|
Bitcast<__u32>{
|
||||||
Identifier{x_30}
|
Identifier{x_30}
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
})"))
|
})"))
|
||||||
<< ToString(fe.ast_body());
|
<< ToString(fe.ast_body());
|
||||||
|
@ -412,9 +417,10 @@ TEST_F(SpvUnaryConversionTest, ConvertUToF_Scalar_FromUnsigned) {
|
||||||
none
|
none
|
||||||
__f32
|
__f32
|
||||||
{
|
{
|
||||||
Cast<__f32>(
|
TypeConstructor{
|
||||||
|
__f32
|
||||||
Identifier{x_30}
|
Identifier{x_30}
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
})"))
|
})"))
|
||||||
<< ToString(fe.ast_body());
|
<< ToString(fe.ast_body());
|
||||||
|
@ -438,11 +444,12 @@ TEST_F(SpvUnaryConversionTest, ConvertUToF_Vector_FromSigned) {
|
||||||
none
|
none
|
||||||
__vec_2__f32
|
__vec_2__f32
|
||||||
{
|
{
|
||||||
Cast<__vec_2__f32>(
|
TypeConstructor{
|
||||||
|
__vec_2__f32
|
||||||
Bitcast<__vec_2__u32>{
|
Bitcast<__vec_2__u32>{
|
||||||
Identifier{x_30}
|
Identifier{x_30}
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
})"))
|
})"))
|
||||||
<< ToString(fe.ast_body());
|
<< ToString(fe.ast_body());
|
||||||
|
@ -466,9 +473,10 @@ TEST_F(SpvUnaryConversionTest, ConvertUToF_Vector_FromUnsigned) {
|
||||||
none
|
none
|
||||||
__vec_2__f32
|
__vec_2__f32
|
||||||
{
|
{
|
||||||
Cast<__vec_2__f32>(
|
TypeConstructor{
|
||||||
|
__vec_2__f32
|
||||||
Identifier{x_30}
|
Identifier{x_30}
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
})"))
|
})"))
|
||||||
<< ToString(fe.ast_body());
|
<< ToString(fe.ast_body());
|
||||||
|
@ -526,9 +534,10 @@ TEST_F(SpvUnaryConversionTest, ConvertFToS_Scalar_ToSigned) {
|
||||||
none
|
none
|
||||||
__i32
|
__i32
|
||||||
{
|
{
|
||||||
Cast<__i32>(
|
TypeConstructor{
|
||||||
|
__i32
|
||||||
Identifier{x_30}
|
Identifier{x_30}
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
})"))
|
})"))
|
||||||
<< ToString(fe.ast_body());
|
<< ToString(fe.ast_body());
|
||||||
|
@ -553,9 +562,10 @@ TEST_F(SpvUnaryConversionTest, ConvertFToS_Scalar_ToUnsigned) {
|
||||||
__u32
|
__u32
|
||||||
{
|
{
|
||||||
Bitcast<__u32>{
|
Bitcast<__u32>{
|
||||||
Cast<__i32>(
|
TypeConstructor{
|
||||||
|
__i32
|
||||||
Identifier{x_30}
|
Identifier{x_30}
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})"))
|
})"))
|
||||||
|
@ -580,9 +590,10 @@ TEST_F(SpvUnaryConversionTest, ConvertFToS_Vector_ToSigned) {
|
||||||
none
|
none
|
||||||
__vec_2__i32
|
__vec_2__i32
|
||||||
{
|
{
|
||||||
Cast<__vec_2__i32>(
|
TypeConstructor{
|
||||||
|
__vec_2__i32
|
||||||
Identifier{x_30}
|
Identifier{x_30}
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
})"))
|
})"))
|
||||||
<< ToString(fe.ast_body());
|
<< ToString(fe.ast_body());
|
||||||
|
@ -607,9 +618,10 @@ TEST_F(SpvUnaryConversionTest, ConvertFToS_Vector_ToUnsigned) {
|
||||||
__vec_2__u32
|
__vec_2__u32
|
||||||
{
|
{
|
||||||
Bitcast<__vec_2__u32>{
|
Bitcast<__vec_2__u32>{
|
||||||
Cast<__vec_2__i32>(
|
TypeConstructor{
|
||||||
|
__vec_2__i32
|
||||||
Identifier{x_30}
|
Identifier{x_30}
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})"))
|
})"))
|
||||||
|
@ -669,9 +681,10 @@ TEST_F(SpvUnaryConversionTest, ConvertFToU_Scalar_ToSigned) {
|
||||||
__i32
|
__i32
|
||||||
{
|
{
|
||||||
Bitcast<__i32>{
|
Bitcast<__i32>{
|
||||||
Cast<__u32>(
|
TypeConstructor{
|
||||||
|
__u32
|
||||||
Identifier{x_30}
|
Identifier{x_30}
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})"))
|
})"))
|
||||||
|
@ -696,9 +709,10 @@ TEST_F(SpvUnaryConversionTest, ConvertFToU_Scalar_ToUnsigned) {
|
||||||
none
|
none
|
||||||
__u32
|
__u32
|
||||||
{
|
{
|
||||||
Cast<__u32>(
|
TypeConstructor{
|
||||||
|
__u32
|
||||||
Identifier{x_30}
|
Identifier{x_30}
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
})"))
|
})"))
|
||||||
<< ToString(fe.ast_body());
|
<< ToString(fe.ast_body());
|
||||||
|
@ -723,9 +737,10 @@ TEST_F(SpvUnaryConversionTest, ConvertFToU_Vector_ToSigned) {
|
||||||
__vec_2__i32
|
__vec_2__i32
|
||||||
{
|
{
|
||||||
Bitcast<__vec_2__i32>{
|
Bitcast<__vec_2__i32>{
|
||||||
Cast<__vec_2__u32>(
|
TypeConstructor{
|
||||||
|
__vec_2__u32
|
||||||
Identifier{x_30}
|
Identifier{x_30}
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})"))
|
})"))
|
||||||
|
@ -750,9 +765,10 @@ TEST_F(SpvUnaryConversionTest, ConvertFToU_Vector_ToUnsigned) {
|
||||||
none
|
none
|
||||||
__vec_2__u32
|
__vec_2__u32
|
||||||
{
|
{
|
||||||
Cast<__vec_2__u32>(
|
TypeConstructor{
|
||||||
|
__vec_2__u32
|
||||||
Identifier{x_30}
|
Identifier{x_30}
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
})"))
|
})"))
|
||||||
<< ToString(fe.ast_body());
|
<< ToString(fe.ast_body());
|
||||||
|
|
|
@ -485,8 +485,6 @@ Token Lexer::check_keyword(const Source& source, const std::string& str) {
|
||||||
return {Token::Type::kBuiltin, source, "builtin"};
|
return {Token::Type::kBuiltin, source, "builtin"};
|
||||||
if (str == "case")
|
if (str == "case")
|
||||||
return {Token::Type::kCase, source, "case"};
|
return {Token::Type::kCase, source, "case"};
|
||||||
if (str == "cast")
|
|
||||||
return {Token::Type::kCast, source, "cast"};
|
|
||||||
if (str == "compute")
|
if (str == "compute")
|
||||||
return {Token::Type::kCompute, source, "compute"};
|
return {Token::Type::kCompute, source, "compute"};
|
||||||
if (str == "const")
|
if (str == "const")
|
||||||
|
|
|
@ -420,7 +420,6 @@ INSTANTIATE_TEST_SUITE_P(
|
||||||
TokenData{"break", Token::Type::kBreak},
|
TokenData{"break", Token::Type::kBreak},
|
||||||
TokenData{"builtin", Token::Type::kBuiltin},
|
TokenData{"builtin", Token::Type::kBuiltin},
|
||||||
TokenData{"case", Token::Type::kCase},
|
TokenData{"case", Token::Type::kCase},
|
||||||
TokenData{"cast", Token::Type::kCast},
|
|
||||||
TokenData{"compute", Token::Type::kCompute},
|
TokenData{"compute", Token::Type::kCompute},
|
||||||
TokenData{"const", Token::Type::kConst},
|
TokenData{"const", Token::Type::kConst},
|
||||||
TokenData{"continue", Token::Type::kContinue},
|
TokenData{"continue", Token::Type::kContinue},
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
#include "src/ast/builtin_decoration.h"
|
#include "src/ast/builtin_decoration.h"
|
||||||
#include "src/ast/call_expression.h"
|
#include "src/ast/call_expression.h"
|
||||||
#include "src/ast/case_statement.h"
|
#include "src/ast/case_statement.h"
|
||||||
#include "src/ast/cast_expression.h"
|
|
||||||
#include "src/ast/continue_statement.h"
|
#include "src/ast/continue_statement.h"
|
||||||
#include "src/ast/decorated_variable.h"
|
#include "src/ast/decorated_variable.h"
|
||||||
#include "src/ast/discard_statement.h"
|
#include "src/ast/discard_statement.h"
|
||||||
|
@ -2767,8 +2766,7 @@ std::unique_ptr<ast::BlockStatement> ParserImpl::continuing_stmt() {
|
||||||
// | type_decl PAREN_LEFT argument_expression_list* PAREN_RIGHT
|
// | type_decl PAREN_LEFT argument_expression_list* PAREN_RIGHT
|
||||||
// | const_literal
|
// | const_literal
|
||||||
// | paren_rhs_stmt
|
// | paren_rhs_stmt
|
||||||
// | CAST LESS_THAN type_decl GREATER_THAN paren_rhs_stmt
|
// | BITCAST LESS_THAN type_decl GREATER_THAN paren_rhs_stmt
|
||||||
// | AS LESS_THAN type_decl GREATER_THAN paren_rhs_stmt
|
|
||||||
std::unique_ptr<ast::Expression> ParserImpl::primary_expression() {
|
std::unique_ptr<ast::Expression> ParserImpl::primary_expression() {
|
||||||
auto t = peek();
|
auto t = peek();
|
||||||
auto source = t.source();
|
auto source = t.source();
|
||||||
|
@ -2790,14 +2788,14 @@ std::unique_ptr<ast::Expression> ParserImpl::primary_expression() {
|
||||||
return paren;
|
return paren;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t.IsCast() || t.IsBitcast()) {
|
if (t.IsBitcast()) {
|
||||||
auto src = t;
|
auto src = t;
|
||||||
|
|
||||||
next(); // Consume the peek
|
next(); // Consume the peek
|
||||||
|
|
||||||
t = next();
|
t = next();
|
||||||
if (!t.IsLessThan()) {
|
if (!t.IsLessThan()) {
|
||||||
set_error(t, "missing < for " + src.to_name() + " expression");
|
set_error(t, "missing < for bitcast expression");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2805,13 +2803,13 @@ std::unique_ptr<ast::Expression> ParserImpl::primary_expression() {
|
||||||
if (has_error())
|
if (has_error())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
if (type == nullptr) {
|
if (type == nullptr) {
|
||||||
set_error(peek(), "missing type for " + src.to_name() + " expression");
|
set_error(peek(), "missing type for bitcast expression");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
t = next();
|
t = next();
|
||||||
if (!t.IsGreaterThan()) {
|
if (!t.IsGreaterThan()) {
|
||||||
set_error(t, "missing > for " + src.to_name() + " expression");
|
set_error(t, "missing > for bitcast expression");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2823,14 +2821,8 @@ std::unique_ptr<ast::Expression> ParserImpl::primary_expression() {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (src.IsCast()) {
|
return std::make_unique<ast::BitcastExpression>(source, type,
|
||||||
return std::make_unique<ast::CastExpression>(source, type,
|
std::move(params));
|
||||||
std::move(params));
|
|
||||||
} else {
|
|
||||||
return std::make_unique<ast::BitcastExpression>(source, type,
|
|
||||||
std::move(params));
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (t.IsIdentifier()) {
|
} else if (t.IsIdentifier()) {
|
||||||
next(); // Consume the peek
|
next(); // Consume the peek
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
#include "src/ast/array_accessor_expression.h"
|
#include "src/ast/array_accessor_expression.h"
|
||||||
#include "src/ast/bitcast_expression.h"
|
#include "src/ast/bitcast_expression.h"
|
||||||
#include "src/ast/bool_literal.h"
|
#include "src/ast/bool_literal.h"
|
||||||
#include "src/ast/cast_expression.h"
|
|
||||||
#include "src/ast/identifier_expression.h"
|
#include "src/ast/identifier_expression.h"
|
||||||
#include "src/ast/scalar_constructor_expression.h"
|
#include "src/ast/scalar_constructor_expression.h"
|
||||||
#include "src/ast/sint_literal.h"
|
#include "src/ast/sint_literal.h"
|
||||||
|
@ -170,73 +169,19 @@ TEST_F(ParserImplTest, PrimaryExpression_ParenExpr_InvalidExpr) {
|
||||||
TEST_F(ParserImplTest, PrimaryExpression_Cast) {
|
TEST_F(ParserImplTest, PrimaryExpression_Cast) {
|
||||||
auto* f32_type = tm()->Get(std::make_unique<ast::type::F32Type>());
|
auto* f32_type = tm()->Get(std::make_unique<ast::type::F32Type>());
|
||||||
|
|
||||||
auto* p = parser("cast<f32>(1)");
|
auto* p = parser("f32(1)");
|
||||||
auto e = p->primary_expression();
|
auto e = p->primary_expression();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e, nullptr);
|
ASSERT_NE(e, nullptr);
|
||||||
ASSERT_TRUE(e->IsCast());
|
ASSERT_TRUE(e->IsConstructor());
|
||||||
|
ASSERT_TRUE(e->AsConstructor()->IsTypeConstructor());
|
||||||
|
|
||||||
auto* c = e->AsCast();
|
auto* c = e->AsConstructor()->AsTypeConstructor();
|
||||||
ASSERT_EQ(c->type(), f32_type);
|
ASSERT_EQ(c->type(), f32_type);
|
||||||
|
ASSERT_EQ(c->values().size(), 1u);
|
||||||
|
|
||||||
ASSERT_TRUE(c->expr()->IsConstructor());
|
ASSERT_TRUE(c->values()[0]->IsConstructor());
|
||||||
ASSERT_TRUE(c->expr()->AsConstructor()->IsScalarConstructor());
|
ASSERT_TRUE(c->values()[0]->AsConstructor()->IsScalarConstructor());
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(ParserImplTest, PrimaryExpression_Cast_MissingGreaterThan) {
|
|
||||||
auto* p = parser("cast<f32(1)");
|
|
||||||
auto e = p->primary_expression();
|
|
||||||
ASSERT_TRUE(p->has_error());
|
|
||||||
ASSERT_EQ(e, nullptr);
|
|
||||||
EXPECT_EQ(p->error(), "1:9: missing > for cast expression");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(ParserImplTest, PrimaryExpression_Cast_MissingType) {
|
|
||||||
auto* p = parser("cast<>(1)");
|
|
||||||
auto e = p->primary_expression();
|
|
||||||
ASSERT_TRUE(p->has_error());
|
|
||||||
ASSERT_EQ(e, nullptr);
|
|
||||||
EXPECT_EQ(p->error(), "1:6: missing type for cast expression");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(ParserImplTest, PrimaryExpression_Cast_InvalidType) {
|
|
||||||
auto* p = parser("cast<invalid>(1)");
|
|
||||||
auto e = p->primary_expression();
|
|
||||||
ASSERT_TRUE(p->has_error());
|
|
||||||
ASSERT_EQ(e, nullptr);
|
|
||||||
EXPECT_EQ(p->error(), "1:6: unknown type alias 'invalid'");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(ParserImplTest, PrimaryExpression_Cast_MissingLeftParen) {
|
|
||||||
auto* p = parser("cast<f32>1)");
|
|
||||||
auto e = p->primary_expression();
|
|
||||||
ASSERT_TRUE(p->has_error());
|
|
||||||
ASSERT_EQ(e, nullptr);
|
|
||||||
EXPECT_EQ(p->error(), "1:10: expected (");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(ParserImplTest, PrimaryExpression_Cast_MissingRightParen) {
|
|
||||||
auto* p = parser("cast<f32>(1");
|
|
||||||
auto e = p->primary_expression();
|
|
||||||
ASSERT_TRUE(p->has_error());
|
|
||||||
ASSERT_EQ(e, nullptr);
|
|
||||||
EXPECT_EQ(p->error(), "1:12: expected )");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(ParserImplTest, PrimaryExpression_Cast_MissingExpression) {
|
|
||||||
auto* p = parser("cast<f32>()");
|
|
||||||
auto e = p->primary_expression();
|
|
||||||
ASSERT_TRUE(p->has_error());
|
|
||||||
ASSERT_EQ(e, nullptr);
|
|
||||||
EXPECT_EQ(p->error(), "1:11: unable to parse expression");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(ParserImplTest, PrimaryExpression_Cast_InvalidExpression) {
|
|
||||||
auto* p = parser("cast<f32>(if (a) {})");
|
|
||||||
auto e = p->primary_expression();
|
|
||||||
ASSERT_TRUE(p->has_error());
|
|
||||||
ASSERT_EQ(e, nullptr);
|
|
||||||
EXPECT_EQ(p->error(), "1:11: unable to parse expression");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, PrimaryExpression_Bitcast) {
|
TEST_F(ParserImplTest, PrimaryExpression_Bitcast) {
|
||||||
|
|
|
@ -121,8 +121,6 @@ std::string Token::TypeToName(Type type) {
|
||||||
return "builtin";
|
return "builtin";
|
||||||
case Token::Type::kCase:
|
case Token::Type::kCase:
|
||||||
return "case";
|
return "case";
|
||||||
case Token::Type::kCast:
|
|
||||||
return "cast";
|
|
||||||
case Token::Type::kCompute:
|
case Token::Type::kCompute:
|
||||||
return "compute";
|
return "compute";
|
||||||
case Token::Type::kConst:
|
case Token::Type::kConst:
|
||||||
|
|
|
@ -132,8 +132,6 @@ class Token {
|
||||||
kBuiltin,
|
kBuiltin,
|
||||||
/// A 'case'
|
/// A 'case'
|
||||||
kCase,
|
kCase,
|
||||||
/// A 'cast'
|
|
||||||
kCast,
|
|
||||||
/// A 'compute'
|
/// A 'compute'
|
||||||
kCompute,
|
kCompute,
|
||||||
/// A 'const'
|
/// A 'const'
|
||||||
|
@ -509,8 +507,6 @@ class Token {
|
||||||
bool IsBuiltin() const { return type_ == Type::kBuiltin; }
|
bool IsBuiltin() const { return type_ == Type::kBuiltin; }
|
||||||
/// @returns true if token is a 'case'
|
/// @returns true if token is a 'case'
|
||||||
bool IsCase() const { return type_ == Type::kCase; }
|
bool IsCase() const { return type_ == Type::kCase; }
|
||||||
/// @returns true if token is a 'cast'
|
|
||||||
bool IsCast() const { return type_ == Type::kCast; }
|
|
||||||
/// @returns true if token is a 'sampler_comparison'
|
/// @returns true if token is a 'sampler_comparison'
|
||||||
bool IsComparisonSampler() const { return type_ == Type::kComparisonSampler; }
|
bool IsComparisonSampler() const { return type_ == Type::kComparisonSampler; }
|
||||||
/// @returns true if token is a 'compute'
|
/// @returns true if token is a 'compute'
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
#include "src/ast/call_expression.h"
|
#include "src/ast/call_expression.h"
|
||||||
#include "src/ast/call_statement.h"
|
#include "src/ast/call_statement.h"
|
||||||
#include "src/ast/case_statement.h"
|
#include "src/ast/case_statement.h"
|
||||||
#include "src/ast/cast_expression.h"
|
|
||||||
#include "src/ast/continue_statement.h"
|
#include "src/ast/continue_statement.h"
|
||||||
#include "src/ast/else_statement.h"
|
#include "src/ast/else_statement.h"
|
||||||
#include "src/ast/identifier_expression.h"
|
#include "src/ast/identifier_expression.h"
|
||||||
|
@ -305,9 +304,6 @@ bool TypeDeterminer::DetermineResultType(ast::Expression* expr) {
|
||||||
if (expr->IsCall()) {
|
if (expr->IsCall()) {
|
||||||
return DetermineCall(expr->AsCall());
|
return DetermineCall(expr->AsCall());
|
||||||
}
|
}
|
||||||
if (expr->IsCast()) {
|
|
||||||
return DetermineCast(expr->AsCast());
|
|
||||||
}
|
|
||||||
if (expr->IsConstructor()) {
|
if (expr->IsConstructor()) {
|
||||||
return DetermineConstructor(expr->AsConstructor());
|
return DetermineConstructor(expr->AsConstructor());
|
||||||
}
|
}
|
||||||
|
@ -737,15 +733,6 @@ bool TypeDeterminer::DetermineIntrinsic(ast::IdentifierExpression* ident,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TypeDeterminer::DetermineCast(ast::CastExpression* expr) {
|
|
||||||
if (!DetermineResultType(expr->expr())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
expr->set_result_type(expr->type());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TypeDeterminer::DetermineConstructor(ast::ConstructorExpression* expr) {
|
bool TypeDeterminer::DetermineConstructor(ast::ConstructorExpression* expr) {
|
||||||
if (expr->IsTypeConstructor()) {
|
if (expr->IsTypeConstructor()) {
|
||||||
auto* ty = expr->AsTypeConstructor();
|
auto* ty = expr->AsTypeConstructor();
|
||||||
|
|
|
@ -30,7 +30,6 @@ class ArrayAccessorExpression;
|
||||||
class BinaryExpression;
|
class BinaryExpression;
|
||||||
class BitcastExpression;
|
class BitcastExpression;
|
||||||
class CallExpression;
|
class CallExpression;
|
||||||
class CastExpression;
|
|
||||||
class ConstructorExpression;
|
class ConstructorExpression;
|
||||||
class Function;
|
class Function;
|
||||||
class IdentifierExpression;
|
class IdentifierExpression;
|
||||||
|
@ -120,7 +119,6 @@ class TypeDeterminer {
|
||||||
bool DetermineBinary(ast::BinaryExpression* expr);
|
bool DetermineBinary(ast::BinaryExpression* expr);
|
||||||
bool DetermineBitcast(ast::BitcastExpression* expr);
|
bool DetermineBitcast(ast::BitcastExpression* expr);
|
||||||
bool DetermineCall(ast::CallExpression* expr);
|
bool DetermineCall(ast::CallExpression* expr);
|
||||||
bool DetermineCast(ast::CastExpression* expr);
|
|
||||||
bool DetermineConstructor(ast::ConstructorExpression* expr);
|
bool DetermineConstructor(ast::ConstructorExpression* expr);
|
||||||
bool DetermineIdentifier(ast::IdentifierExpression* expr);
|
bool DetermineIdentifier(ast::IdentifierExpression* expr);
|
||||||
bool DetermineIntrinsic(ast::IdentifierExpression* name,
|
bool DetermineIntrinsic(ast::IdentifierExpression* name,
|
||||||
|
|
|
@ -29,7 +29,6 @@
|
||||||
#include "src/ast/call_expression.h"
|
#include "src/ast/call_expression.h"
|
||||||
#include "src/ast/call_statement.h"
|
#include "src/ast/call_statement.h"
|
||||||
#include "src/ast/case_statement.h"
|
#include "src/ast/case_statement.h"
|
||||||
#include "src/ast/cast_expression.h"
|
|
||||||
#include "src/ast/continue_statement.h"
|
#include "src/ast/continue_statement.h"
|
||||||
#include "src/ast/else_statement.h"
|
#include "src/ast/else_statement.h"
|
||||||
#include "src/ast/float_literal.h"
|
#include "src/ast/float_literal.h"
|
||||||
|
@ -686,8 +685,11 @@ TEST_F(TypeDeterminerTest, Expr_Call_Intrinsic) {
|
||||||
|
|
||||||
TEST_F(TypeDeterminerTest, Expr_Cast) {
|
TEST_F(TypeDeterminerTest, Expr_Cast) {
|
||||||
ast::type::F32Type f32;
|
ast::type::F32Type f32;
|
||||||
ast::CastExpression cast(&f32,
|
|
||||||
std::make_unique<ast::IdentifierExpression>("name"));
|
ast::ExpressionList params;
|
||||||
|
params.push_back(std::make_unique<ast::IdentifierExpression>("name"));
|
||||||
|
|
||||||
|
ast::TypeConstructorExpression cast(&f32, std::move(params));
|
||||||
|
|
||||||
EXPECT_TRUE(td()->DetermineResultType(&cast));
|
EXPECT_TRUE(td()->DetermineResultType(&cast));
|
||||||
ASSERT_NE(cast.result_type(), nullptr);
|
ASSERT_NE(cast.result_type(), nullptr);
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
#include "src/ast/call_expression.h"
|
#include "src/ast/call_expression.h"
|
||||||
#include "src/ast/call_statement.h"
|
#include "src/ast/call_statement.h"
|
||||||
#include "src/ast/case_statement.h"
|
#include "src/ast/case_statement.h"
|
||||||
#include "src/ast/cast_expression.h"
|
|
||||||
#include "src/ast/continue_statement.h"
|
#include "src/ast/continue_statement.h"
|
||||||
#include "src/ast/else_statement.h"
|
#include "src/ast/else_statement.h"
|
||||||
#include "src/ast/float_literal.h"
|
#include "src/ast/float_literal.h"
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
#include "src/ast/call_expression.h"
|
#include "src/ast/call_expression.h"
|
||||||
#include "src/ast/call_statement.h"
|
#include "src/ast/call_statement.h"
|
||||||
#include "src/ast/case_statement.h"
|
#include "src/ast/case_statement.h"
|
||||||
#include "src/ast/cast_expression.h"
|
|
||||||
#include "src/ast/decorated_variable.h"
|
#include "src/ast/decorated_variable.h"
|
||||||
#include "src/ast/else_statement.h"
|
#include "src/ast/else_statement.h"
|
||||||
#include "src/ast/float_literal.h"
|
#include "src/ast/float_literal.h"
|
||||||
|
@ -724,21 +723,6 @@ bool GeneratorImpl::EmitBuiltinName(std::ostream&,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GeneratorImpl::EmitCast(std::ostream& pre,
|
|
||||||
std::ostream& out,
|
|
||||||
ast::CastExpression* expr) {
|
|
||||||
if (!EmitType(out, expr->type(), "")) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
out << "(";
|
|
||||||
if (!EmitExpression(pre, out, expr->expr())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
out << ")";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GeneratorImpl::EmitCase(std::ostream& out, ast::CaseStatement* stmt) {
|
bool GeneratorImpl::EmitCase(std::ostream& out, ast::CaseStatement* stmt) {
|
||||||
make_indent(out);
|
make_indent(out);
|
||||||
|
|
||||||
|
@ -868,9 +852,6 @@ bool GeneratorImpl::EmitExpression(std::ostream& pre,
|
||||||
if (expr->IsCall()) {
|
if (expr->IsCall()) {
|
||||||
return EmitCall(pre, out, expr->AsCall());
|
return EmitCall(pre, out, expr->AsCall());
|
||||||
}
|
}
|
||||||
if (expr->IsCast()) {
|
|
||||||
return EmitCast(pre, out, expr->AsCast());
|
|
||||||
}
|
|
||||||
if (expr->IsConstructor()) {
|
if (expr->IsConstructor()) {
|
||||||
return EmitConstructor(pre, out, expr->AsConstructor());
|
return EmitConstructor(pre, out, expr->AsConstructor());
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,14 +128,6 @@ class GeneratorImpl {
|
||||||
/// @param stmt the statement
|
/// @param stmt the statement
|
||||||
/// @returns true if the statment was emitted successfully
|
/// @returns true if the statment was emitted successfully
|
||||||
bool EmitCase(std::ostream& out, ast::CaseStatement* stmt);
|
bool EmitCase(std::ostream& out, ast::CaseStatement* stmt);
|
||||||
/// Handles generating a cast expression
|
|
||||||
/// @param pre the preamble for the expression stream
|
|
||||||
/// @param out the output of the expression stream
|
|
||||||
/// @param expr the cast expression
|
|
||||||
/// @returns true if the cast was emitted
|
|
||||||
bool EmitCast(std::ostream& pre,
|
|
||||||
std::ostream& out,
|
|
||||||
ast::CastExpression* expr);
|
|
||||||
/// Handles generating constructor expressions
|
/// Handles generating constructor expressions
|
||||||
/// @param pre the preamble for the expression stream
|
/// @param pre the preamble for the expression stream
|
||||||
/// @param out the output of the expression stream
|
/// @param out the output of the expression stream
|
||||||
|
|
|
@ -14,11 +14,11 @@
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "src/ast/cast_expression.h"
|
|
||||||
#include "src/ast/identifier_expression.h"
|
#include "src/ast/identifier_expression.h"
|
||||||
#include "src/ast/module.h"
|
#include "src/ast/module.h"
|
||||||
#include "src/ast/type/f32_type.h"
|
#include "src/ast/type/f32_type.h"
|
||||||
#include "src/ast/type/vector_type.h"
|
#include "src/ast/type/vector_type.h"
|
||||||
|
#include "src/ast/type_constructor_expression.h"
|
||||||
#include "src/writer/hlsl/test_helper.h"
|
#include "src/writer/hlsl/test_helper.h"
|
||||||
|
|
||||||
namespace tint {
|
namespace tint {
|
||||||
|
@ -30,8 +30,11 @@ using HlslGeneratorImplTest_Cast = TestHelper;
|
||||||
|
|
||||||
TEST_F(HlslGeneratorImplTest_Cast, EmitExpression_Cast_Scalar) {
|
TEST_F(HlslGeneratorImplTest_Cast, EmitExpression_Cast_Scalar) {
|
||||||
ast::type::F32Type f32;
|
ast::type::F32Type f32;
|
||||||
auto id = std::make_unique<ast::IdentifierExpression>("id");
|
|
||||||
ast::CastExpression cast(&f32, std::move(id));
|
ast::ExpressionList params;
|
||||||
|
params.push_back(std::make_unique<ast::IdentifierExpression>("id"));
|
||||||
|
|
||||||
|
ast::TypeConstructorExpression cast(&f32, std::move(params));
|
||||||
|
|
||||||
ASSERT_TRUE(gen().EmitExpression(pre(), out(), &cast)) << gen().error();
|
ASSERT_TRUE(gen().EmitExpression(pre(), out(), &cast)) << gen().error();
|
||||||
EXPECT_EQ(result(), "float(id)");
|
EXPECT_EQ(result(), "float(id)");
|
||||||
|
@ -41,8 +44,10 @@ TEST_F(HlslGeneratorImplTest_Cast, EmitExpression_Cast_Vector) {
|
||||||
ast::type::F32Type f32;
|
ast::type::F32Type f32;
|
||||||
ast::type::VectorType vec3(&f32, 3);
|
ast::type::VectorType vec3(&f32, 3);
|
||||||
|
|
||||||
auto id = std::make_unique<ast::IdentifierExpression>("id");
|
ast::ExpressionList params;
|
||||||
ast::CastExpression cast(&vec3, std::move(id));
|
params.push_back(std::make_unique<ast::IdentifierExpression>("id"));
|
||||||
|
|
||||||
|
ast::TypeConstructorExpression cast(&vec3, std::move(params));
|
||||||
|
|
||||||
ASSERT_TRUE(gen().EmitExpression(pre(), out(), &cast)) << gen().error();
|
ASSERT_TRUE(gen().EmitExpression(pre(), out(), &cast)) << gen().error();
|
||||||
EXPECT_EQ(result(), "vector<float, 3>(id)");
|
EXPECT_EQ(result(), "vector<float, 3>(id)");
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
#include "src/ast/call_expression.h"
|
#include "src/ast/call_expression.h"
|
||||||
#include "src/ast/call_statement.h"
|
#include "src/ast/call_statement.h"
|
||||||
#include "src/ast/case_statement.h"
|
#include "src/ast/case_statement.h"
|
||||||
#include "src/ast/cast_expression.h"
|
|
||||||
#include "src/ast/continue_statement.h"
|
#include "src/ast/continue_statement.h"
|
||||||
#include "src/ast/decorated_variable.h"
|
#include "src/ast/decorated_variable.h"
|
||||||
#include "src/ast/else_statement.h"
|
#include "src/ast/else_statement.h"
|
||||||
|
@ -744,19 +743,6 @@ bool GeneratorImpl::EmitCase(ast::CaseStatement* stmt) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GeneratorImpl::EmitCast(ast::CastExpression* expr) {
|
|
||||||
if (!EmitType(expr->type(), "")) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
out_ << "(";
|
|
||||||
if (!EmitExpression(expr->expr())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
out_ << ")";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GeneratorImpl::EmitConstructor(ast::ConstructorExpression* expr) {
|
bool GeneratorImpl::EmitConstructor(ast::ConstructorExpression* expr) {
|
||||||
if (expr->IsScalarConstructor()) {
|
if (expr->IsScalarConstructor()) {
|
||||||
return EmitScalarConstructor(expr->AsScalarConstructor());
|
return EmitScalarConstructor(expr->AsScalarConstructor());
|
||||||
|
@ -992,9 +978,6 @@ bool GeneratorImpl::EmitExpression(ast::Expression* expr) {
|
||||||
if (expr->IsCall()) {
|
if (expr->IsCall()) {
|
||||||
return EmitCall(expr->AsCall());
|
return EmitCall(expr->AsCall());
|
||||||
}
|
}
|
||||||
if (expr->IsCast()) {
|
|
||||||
return EmitCast(expr->AsCast());
|
|
||||||
}
|
|
||||||
if (expr->IsConstructor()) {
|
if (expr->IsConstructor()) {
|
||||||
return EmitConstructor(expr->AsConstructor());
|
return EmitConstructor(expr->AsConstructor());
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,10 +98,6 @@ class GeneratorImpl : public TextGenerator {
|
||||||
/// @param stmt the statement
|
/// @param stmt the statement
|
||||||
/// @returns true if the statement was emitted successfully
|
/// @returns true if the statement was emitted successfully
|
||||||
bool EmitCase(ast::CaseStatement* stmt);
|
bool EmitCase(ast::CaseStatement* stmt);
|
||||||
/// Handles generating a cast expression
|
|
||||||
/// @param expr the cast expression
|
|
||||||
/// @returns true if the cast was emitted
|
|
||||||
bool EmitCast(ast::CastExpression* expr);
|
|
||||||
/// Handles generating constructor expressions
|
/// Handles generating constructor expressions
|
||||||
/// @param expr the constructor expression
|
/// @param expr the constructor expression
|
||||||
/// @returns true if the expression was emitted
|
/// @returns true if the expression was emitted
|
||||||
|
|
|
@ -15,11 +15,11 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
#include "src/ast/cast_expression.h"
|
|
||||||
#include "src/ast/identifier_expression.h"
|
#include "src/ast/identifier_expression.h"
|
||||||
#include "src/ast/module.h"
|
#include "src/ast/module.h"
|
||||||
#include "src/ast/type/f32_type.h"
|
#include "src/ast/type/f32_type.h"
|
||||||
#include "src/ast/type/vector_type.h"
|
#include "src/ast/type/vector_type.h"
|
||||||
|
#include "src/ast/type_constructor_expression.h"
|
||||||
#include "src/writer/msl/generator_impl.h"
|
#include "src/writer/msl/generator_impl.h"
|
||||||
|
|
||||||
namespace tint {
|
namespace tint {
|
||||||
|
@ -31,8 +31,11 @@ using MslGeneratorImplTest = testing::Test;
|
||||||
|
|
||||||
TEST_F(MslGeneratorImplTest, EmitExpression_Cast_Scalar) {
|
TEST_F(MslGeneratorImplTest, EmitExpression_Cast_Scalar) {
|
||||||
ast::type::F32Type f32;
|
ast::type::F32Type f32;
|
||||||
auto id = std::make_unique<ast::IdentifierExpression>("id");
|
|
||||||
ast::CastExpression cast(&f32, std::move(id));
|
ast::ExpressionList params;
|
||||||
|
params.push_back(std::make_unique<ast::IdentifierExpression>("id"));
|
||||||
|
|
||||||
|
ast::TypeConstructorExpression cast(&f32, std::move(params));
|
||||||
|
|
||||||
ast::Module m;
|
ast::Module m;
|
||||||
GeneratorImpl g(&m);
|
GeneratorImpl g(&m);
|
||||||
|
@ -44,8 +47,10 @@ TEST_F(MslGeneratorImplTest, EmitExpression_Cast_Vector) {
|
||||||
ast::type::F32Type f32;
|
ast::type::F32Type f32;
|
||||||
ast::type::VectorType vec3(&f32, 3);
|
ast::type::VectorType vec3(&f32, 3);
|
||||||
|
|
||||||
auto id = std::make_unique<ast::IdentifierExpression>("id");
|
ast::ExpressionList params;
|
||||||
ast::CastExpression cast(&vec3, std::move(id));
|
params.push_back(std::make_unique<ast::IdentifierExpression>("id"));
|
||||||
|
|
||||||
|
ast::TypeConstructorExpression cast(&vec3, std::move(params));
|
||||||
|
|
||||||
ast::Module m;
|
ast::Module m;
|
||||||
GeneratorImpl g(&m);
|
GeneratorImpl g(&m);
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
#include "src/ast/call_expression.h"
|
#include "src/ast/call_expression.h"
|
||||||
#include "src/ast/call_statement.h"
|
#include "src/ast/call_statement.h"
|
||||||
#include "src/ast/case_statement.h"
|
#include "src/ast/case_statement.h"
|
||||||
#include "src/ast/cast_expression.h"
|
|
||||||
#include "src/ast/constructor_expression.h"
|
#include "src/ast/constructor_expression.h"
|
||||||
#include "src/ast/decorated_variable.h"
|
#include "src/ast/decorated_variable.h"
|
||||||
#include "src/ast/else_statement.h"
|
#include "src/ast/else_statement.h"
|
||||||
|
@ -465,9 +464,6 @@ uint32_t Builder::GenerateExpression(ast::Expression* expr) {
|
||||||
if (expr->IsCall()) {
|
if (expr->IsCall()) {
|
||||||
return GenerateCallExpression(expr->AsCall());
|
return GenerateCallExpression(expr->AsCall());
|
||||||
}
|
}
|
||||||
if (expr->IsCast()) {
|
|
||||||
return GenerateCastExpression(expr->AsCast());
|
|
||||||
}
|
|
||||||
if (expr->IsConstructor()) {
|
if (expr->IsConstructor()) {
|
||||||
return GenerateConstructorExpression(expr->AsConstructor(), false);
|
return GenerateConstructorExpression(expr->AsConstructor(), false);
|
||||||
}
|
}
|
||||||
|
@ -1054,32 +1050,20 @@ uint32_t Builder::GenerateConstructorExpression(
|
||||||
uint32_t Builder::GenerateTypeConstructorExpression(
|
uint32_t Builder::GenerateTypeConstructorExpression(
|
||||||
ast::TypeConstructorExpression* init,
|
ast::TypeConstructorExpression* init,
|
||||||
bool is_global_init) {
|
bool is_global_init) {
|
||||||
auto type_id = GenerateTypeIfNeeded(init->type());
|
auto& values = init->values();
|
||||||
if (type_id == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate the zero initializer if there are no values provided.
|
// Generate the zero initializer if there are no values provided.
|
||||||
if (init->values().empty()) {
|
if (values.empty()) {
|
||||||
ast::NullLiteral nl(init->type()->UnwrapPtrIfNeeded());
|
ast::NullLiteral nl(init->type()->UnwrapPtrIfNeeded());
|
||||||
return GenerateLiteralIfNeeded(&nl);
|
return GenerateLiteralIfNeeded(&nl);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* result_type = init->type()->UnwrapPtrIfNeeded();
|
|
||||||
if (result_type->IsVector()) {
|
|
||||||
result_type = result_type->AsVector()->type();
|
|
||||||
} else if (result_type->IsArray()) {
|
|
||||||
result_type = result_type->AsArray()->type();
|
|
||||||
} else if (result_type->IsMatrix()) {
|
|
||||||
result_type = result_type->AsMatrix()->type();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ostringstream out;
|
std::ostringstream out;
|
||||||
out << "__const";
|
out << "__const";
|
||||||
|
|
||||||
OperandList ops;
|
OperandList ops;
|
||||||
bool constructor_is_const = true;
|
bool constructor_is_const = true;
|
||||||
for (const auto& e : init->values()) {
|
for (const auto& e : values) {
|
||||||
if (!e->IsConstructor()) {
|
if (!e->IsConstructor()) {
|
||||||
if (is_global_init) {
|
if (is_global_init) {
|
||||||
error_ = "constructor must be a constant expression";
|
error_ = "constructor must be a constant expression";
|
||||||
|
@ -1089,9 +1073,37 @@ uint32_t Builder::GenerateTypeConstructorExpression(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto* result_type = init->type()->UnwrapAliasPtrAlias();
|
||||||
|
|
||||||
|
bool can_cast_or_copy = result_type->is_scalar();
|
||||||
|
if (result_type->IsVector() && result_type->AsVector()->type()->is_scalar()) {
|
||||||
|
auto* value_type = values[0]->result_type()->UnwrapAliasPtrAlias();
|
||||||
|
can_cast_or_copy =
|
||||||
|
(value_type->IsVector() &&
|
||||||
|
value_type->AsVector()->type()->is_scalar() &&
|
||||||
|
result_type->AsVector()->size() == value_type->AsVector()->size());
|
||||||
|
}
|
||||||
|
if (can_cast_or_copy) {
|
||||||
|
return GenerateCastOrCopy(result_type, values[0].get());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto type_id = GenerateTypeIfNeeded(init->type());
|
||||||
|
if (type_id == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool result_is_constant_composite = constructor_is_const;
|
bool result_is_constant_composite = constructor_is_const;
|
||||||
bool result_is_spec_composite = false;
|
bool result_is_spec_composite = false;
|
||||||
for (const auto& e : init->values()) {
|
|
||||||
|
if (result_type->IsVector()) {
|
||||||
|
result_type = result_type->AsVector()->type();
|
||||||
|
} else if (result_type->IsArray()) {
|
||||||
|
result_type = result_type->AsArray()->type();
|
||||||
|
} else if (result_type->IsMatrix()) {
|
||||||
|
result_type = result_type->AsMatrix()->type();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& e : values) {
|
||||||
uint32_t id = 0;
|
uint32_t id = 0;
|
||||||
if (constructor_is_const) {
|
if (constructor_is_const) {
|
||||||
id = GenerateConstructorExpression(e->AsConstructor(), is_global_init);
|
id = GenerateConstructorExpression(e->AsConstructor(), is_global_init);
|
||||||
|
@ -1104,54 +1116,54 @@ uint32_t Builder::GenerateTypeConstructorExpression(
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* value_type = e->result_type()->UnwrapPtrIfNeeded();
|
auto* value_type = e->result_type()->UnwrapPtrIfNeeded();
|
||||||
|
if (result_type == value_type) {
|
||||||
|
out << "_" << id;
|
||||||
|
ops.push_back(Operand::Int(id));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Both scalars, but not the same type so we need to generate a conversion
|
||||||
|
// of the value.
|
||||||
|
if (value_type->is_scalar() && result_type->is_scalar()) {
|
||||||
|
id = GenerateCastOrCopy(result_type, values[0].get());
|
||||||
|
out << "_" << id;
|
||||||
|
ops.push_back(Operand::Int(id));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// When handling vectors as the values there a few cases to take into
|
// When handling vectors as the values there a few cases to take into
|
||||||
// consideration:
|
// consideration:
|
||||||
// 1. Module scoped vec3<f32>(vec2<f32>(1, 2), 3) -> OpSpecConstantOp
|
// 1. Module scoped vec3<f32>(vec2<f32>(1, 2), 3) -> OpSpecConstantOp
|
||||||
// 2. Function scoped vec3<f32>(vec2<f32>(1, 2), 3) -> OpCompositeExtract
|
// 2. Function scoped vec3<f32>(vec2<f32>(1, 2), 3) -> OpCompositeExtract
|
||||||
// 3. Either array<vec3<f32>, 1>(vec3<f32>(1, 2, 3)) -> use the ID.
|
// 3. Either array<vec3<f32>, 1>(vec3<f32>(1, 2, 3)) -> use the ID.
|
||||||
|
// -> handled above
|
||||||
|
//
|
||||||
|
// For cases 1 and 2, if the type is different we also may need to insert
|
||||||
|
// a type cast.
|
||||||
if (value_type->IsVector()) {
|
if (value_type->IsVector()) {
|
||||||
auto* vec = value_type->AsVector();
|
auto* vec = value_type->AsVector();
|
||||||
auto* vec_type = vec->type();
|
auto* vec_type = vec->type();
|
||||||
|
|
||||||
// If the value we want is the same as what we have, use it directly.
|
auto value_type_id = GenerateTypeIfNeeded(vec_type);
|
||||||
// This maps to case 3.
|
if (value_type_id == 0) {
|
||||||
if (result_type == value_type) {
|
return 0;
|
||||||
out << "_" << id;
|
}
|
||||||
ops.push_back(Operand::Int(id));
|
|
||||||
} else if (!is_global_init) {
|
|
||||||
// A non-global initializer. Case 2.
|
|
||||||
auto value_type_id = GenerateTypeIfNeeded(vec_type);
|
|
||||||
if (value_type_id == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < vec->size(); ++i) {
|
for (uint32_t i = 0; i < vec->size(); ++i) {
|
||||||
auto extract = result_op();
|
auto extract = result_op();
|
||||||
auto extract_id = extract.to_i();
|
auto extract_id = extract.to_i();
|
||||||
|
|
||||||
|
if (!is_global_init) {
|
||||||
|
// A non-global initializer. Case 2.
|
||||||
push_function_inst(spv::Op::OpCompositeExtract,
|
push_function_inst(spv::Op::OpCompositeExtract,
|
||||||
{Operand::Int(value_type_id), extract,
|
{Operand::Int(value_type_id), extract,
|
||||||
Operand::Int(id), Operand::Int(i)});
|
Operand::Int(id), Operand::Int(i)});
|
||||||
|
|
||||||
out << "_" << extract_id;
|
|
||||||
ops.push_back(Operand::Int(extract_id));
|
|
||||||
|
|
||||||
// We no longer have a constant composite, but have to do a
|
// We no longer have a constant composite, but have to do a
|
||||||
// composite construction as these calls are inside a function.
|
// composite construction as these calls are inside a function.
|
||||||
result_is_constant_composite = false;
|
result_is_constant_composite = false;
|
||||||
}
|
} else {
|
||||||
} else {
|
// A global initializer, must use OpSpecConstantOp. Case 1.
|
||||||
// A global initializer, must use OpSpecConstantOp. Case 1.
|
|
||||||
auto value_type_id = GenerateTypeIfNeeded(vec_type);
|
|
||||||
if (value_type_id == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < vec->size(); ++i) {
|
|
||||||
auto extract = result_op();
|
|
||||||
auto extract_id = extract.to_i();
|
|
||||||
|
|
||||||
auto idx_id = GenerateU32Literal(i);
|
auto idx_id = GenerateU32Literal(i);
|
||||||
if (idx_id == 0) {
|
if (idx_id == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1161,15 +1173,15 @@ uint32_t Builder::GenerateTypeConstructorExpression(
|
||||||
Operand::Int(SpvOpCompositeExtract), Operand::Int(id),
|
Operand::Int(SpvOpCompositeExtract), Operand::Int(id),
|
||||||
Operand::Int(idx_id)});
|
Operand::Int(idx_id)});
|
||||||
|
|
||||||
out << "_" << extract_id;
|
|
||||||
ops.push_back(Operand::Int(extract_id));
|
|
||||||
|
|
||||||
result_is_spec_composite = true;
|
result_is_spec_composite = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out << "_" << extract_id;
|
||||||
|
ops.push_back(Operand::Int(extract_id));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
out << "_" << id;
|
error_ = "Unhandled type cast value type";
|
||||||
ops.push_back(Operand::Int(id));
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1192,9 +1204,69 @@ uint32_t Builder::GenerateTypeConstructorExpression(
|
||||||
} else {
|
} else {
|
||||||
push_function_inst(spv::Op::OpCompositeConstruct, ops);
|
push_function_inst(spv::Op::OpCompositeConstruct, ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result.to_i();
|
return result.to_i();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t Builder::GenerateCastOrCopy(ast::type::Type* to_type,
|
||||||
|
ast::Expression* from_expr) {
|
||||||
|
auto result = result_op();
|
||||||
|
auto result_id = result.to_i();
|
||||||
|
|
||||||
|
auto result_type_id = GenerateTypeIfNeeded(to_type);
|
||||||
|
if (result_type_id == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto val_id = GenerateExpression(from_expr);
|
||||||
|
if (val_id == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
val_id = GenerateLoadIfNeeded(from_expr->result_type(), val_id);
|
||||||
|
|
||||||
|
auto* from_type = from_expr->result_type()->UnwrapPtrIfNeeded();
|
||||||
|
|
||||||
|
spv::Op op = spv::Op::OpNop;
|
||||||
|
if ((from_type->IsI32() && to_type->IsF32()) ||
|
||||||
|
(from_type->is_signed_integer_vector() && to_type->is_float_vector())) {
|
||||||
|
op = spv::Op::OpConvertSToF;
|
||||||
|
} else if ((from_type->IsU32() && to_type->IsF32()) ||
|
||||||
|
(from_type->is_unsigned_integer_vector() &&
|
||||||
|
to_type->is_float_vector())) {
|
||||||
|
op = spv::Op::OpConvertUToF;
|
||||||
|
} else if ((from_type->IsF32() && to_type->IsI32()) ||
|
||||||
|
(from_type->is_float_vector() &&
|
||||||
|
to_type->is_signed_integer_vector())) {
|
||||||
|
op = spv::Op::OpConvertFToS;
|
||||||
|
} else if ((from_type->IsF32() && to_type->IsU32()) ||
|
||||||
|
(from_type->is_float_vector() &&
|
||||||
|
to_type->is_unsigned_integer_vector())) {
|
||||||
|
op = spv::Op::OpConvertFToU;
|
||||||
|
} else if ((from_type->IsBool() && to_type->IsBool()) ||
|
||||||
|
(from_type->IsU32() && to_type->IsU32()) ||
|
||||||
|
(from_type->IsI32() && to_type->IsI32()) ||
|
||||||
|
(from_type->IsF32() && to_type->IsF32())) {
|
||||||
|
op = spv::Op::OpCopyObject;
|
||||||
|
} else if ((from_type->IsI32() && to_type->IsU32()) ||
|
||||||
|
(from_type->IsU32() && to_type->IsI32()) ||
|
||||||
|
(from_type->is_signed_integer_vector() &&
|
||||||
|
to_type->is_unsigned_integer_vector()) ||
|
||||||
|
(from_type->is_unsigned_integer_vector() &&
|
||||||
|
to_type->is_integer_scalar_or_vector())) {
|
||||||
|
op = spv::Op::OpBitcast;
|
||||||
|
}
|
||||||
|
if (op == spv::Op::OpNop) {
|
||||||
|
error_ = "unable to determine conversion type for cast, from: " +
|
||||||
|
from_type->type_name() + " to: " + to_type->type_name();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
push_function_inst(
|
||||||
|
op, {Operand::Int(result_type_id), result, Operand::Int(val_id)});
|
||||||
|
|
||||||
|
return result_id;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t Builder::GenerateLiteralIfNeeded(ast::Literal* lit) {
|
uint32_t Builder::GenerateLiteralIfNeeded(ast::Literal* lit) {
|
||||||
auto type_id = GenerateTypeIfNeeded(lit->type());
|
auto type_id = GenerateTypeIfNeeded(lit->type());
|
||||||
if (type_id == 0) {
|
if (type_id == 0) {
|
||||||
|
@ -1726,70 +1798,6 @@ uint32_t Builder::GenerateBitcastExpression(ast::BitcastExpression* expr) {
|
||||||
return result_id;
|
return result_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Builder::GenerateCastExpression(ast::CastExpression* cast) {
|
|
||||||
auto result = result_op();
|
|
||||||
auto result_id = result.to_i();
|
|
||||||
|
|
||||||
auto result_type_id = GenerateTypeIfNeeded(cast->result_type());
|
|
||||||
if (result_type_id == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto val_id = GenerateExpression(cast->expr());
|
|
||||||
if (val_id == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
val_id = GenerateLoadIfNeeded(cast->expr()->result_type(), val_id);
|
|
||||||
|
|
||||||
auto* to_type = cast->result_type()->UnwrapPtrIfNeeded();
|
|
||||||
auto* from_type = cast->expr()->result_type()->UnwrapPtrIfNeeded();
|
|
||||||
|
|
||||||
spv::Op op = spv::Op::OpNop;
|
|
||||||
if ((from_type->IsI32() && to_type->IsF32()) ||
|
|
||||||
(from_type->is_signed_integer_vector() && to_type->is_float_vector())) {
|
|
||||||
op = spv::Op::OpConvertSToF;
|
|
||||||
} else if ((from_type->IsU32() && to_type->IsF32()) ||
|
|
||||||
(from_type->is_unsigned_integer_vector() &&
|
|
||||||
to_type->is_float_vector())) {
|
|
||||||
op = spv::Op::OpConvertUToF;
|
|
||||||
} else if ((from_type->IsF32() && to_type->IsI32()) ||
|
|
||||||
(from_type->is_float_vector() &&
|
|
||||||
to_type->is_signed_integer_vector())) {
|
|
||||||
op = spv::Op::OpConvertFToS;
|
|
||||||
} else if ((from_type->IsF32() && to_type->IsU32()) ||
|
|
||||||
(from_type->is_float_vector() &&
|
|
||||||
to_type->is_unsigned_integer_vector())) {
|
|
||||||
op = spv::Op::OpConvertFToU;
|
|
||||||
} else if ((from_type->IsU32() && to_type->IsU32()) ||
|
|
||||||
(from_type->IsI32() && to_type->IsI32()) ||
|
|
||||||
(from_type->IsF32() && to_type->IsF32()) ||
|
|
||||||
(from_type->is_unsigned_integer_vector() &&
|
|
||||||
to_type->is_unsigned_integer_vector()) ||
|
|
||||||
(from_type->is_signed_integer_vector() &&
|
|
||||||
to_type->is_signed_integer_vector()) ||
|
|
||||||
(from_type->is_float_vector() && to_type->is_float_vector())) {
|
|
||||||
op = spv::Op::OpCopyObject;
|
|
||||||
} else if ((from_type->IsI32() && to_type->IsU32()) ||
|
|
||||||
(from_type->IsU32() && to_type->IsI32()) ||
|
|
||||||
(from_type->is_signed_integer_vector() &&
|
|
||||||
to_type->is_unsigned_integer_vector()) ||
|
|
||||||
(from_type->is_unsigned_integer_vector() &&
|
|
||||||
to_type->is_integer_scalar_or_vector())) {
|
|
||||||
op = spv::Op::OpBitcast;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (op == spv::Op::OpNop) {
|
|
||||||
error_ = "unable to determine conversion type for cast, from: " +
|
|
||||||
from_type->type_name() + " to: " + to_type->type_name();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
push_function_inst(
|
|
||||||
op, {Operand::Int(result_type_id), result, Operand::Int(val_id)});
|
|
||||||
|
|
||||||
return result_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Builder::GenerateConditionalBlock(
|
bool Builder::GenerateConditionalBlock(
|
||||||
ast::Expression* cond,
|
ast::Expression* cond,
|
||||||
const ast::BlockStatement* true_body,
|
const ast::BlockStatement* true_body,
|
||||||
|
|
|
@ -306,10 +306,12 @@ class Builder {
|
||||||
uint32_t GenerateSampledImage(ast::type::Type* texture_type,
|
uint32_t GenerateSampledImage(ast::type::Type* texture_type,
|
||||||
Operand texture_operand,
|
Operand texture_operand,
|
||||||
Operand sampler_operand);
|
Operand sampler_operand);
|
||||||
/// Generates a cast expression
|
/// Generates a cast or object copy for the expression result
|
||||||
/// @param expr the expression to generate
|
/// @param to_type the type we're casting too
|
||||||
|
/// @param from_expr the expression to cast
|
||||||
/// @returns the expression ID on success or 0 otherwise
|
/// @returns the expression ID on success or 0 otherwise
|
||||||
uint32_t GenerateCastExpression(ast::CastExpression* expr);
|
uint32_t GenerateCastOrCopy(ast::type::Type* to_type,
|
||||||
|
ast::Expression* from_expr);
|
||||||
/// Generates a loop statement
|
/// Generates a loop statement
|
||||||
/// @param stmt the statement to generate
|
/// @param stmt the statement to generate
|
||||||
/// @returns true on successful generation
|
/// @returns true on successful generation
|
||||||
|
|
|
@ -1,554 +0,0 @@
|
||||||
// Copyright 2020 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 "gtest/gtest.h"
|
|
||||||
#include "src/ast/cast_expression.h"
|
|
||||||
#include "src/ast/float_literal.h"
|
|
||||||
#include "src/ast/identifier_expression.h"
|
|
||||||
#include "src/ast/module.h"
|
|
||||||
#include "src/ast/scalar_constructor_expression.h"
|
|
||||||
#include "src/ast/sint_literal.h"
|
|
||||||
#include "src/ast/type/f32_type.h"
|
|
||||||
#include "src/ast/type/i32_type.h"
|
|
||||||
#include "src/ast/type/u32_type.h"
|
|
||||||
#include "src/ast/type/vector_type.h"
|
|
||||||
#include "src/ast/uint_literal.h"
|
|
||||||
#include "src/context.h"
|
|
||||||
#include "src/type_determiner.h"
|
|
||||||
#include "src/writer/spirv/builder.h"
|
|
||||||
#include "src/writer/spirv/spv_dump.h"
|
|
||||||
|
|
||||||
namespace tint {
|
|
||||||
namespace writer {
|
|
||||||
namespace spirv {
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
using BuilderTest = testing::Test;
|
|
||||||
|
|
||||||
TEST_F(BuilderTest, Cast_FloatToU32) {
|
|
||||||
ast::type::U32Type u32;
|
|
||||||
ast::type::F32Type f32;
|
|
||||||
|
|
||||||
ast::CastExpression cast(&u32,
|
|
||||||
std::make_unique<ast::ScalarConstructorExpression>(
|
|
||||||
std::make_unique<ast::FloatLiteral>(&f32, 2.4)));
|
|
||||||
|
|
||||||
Context ctx;
|
|
||||||
ast::Module mod;
|
|
||||||
TypeDeterminer td(&ctx, &mod);
|
|
||||||
ASSERT_TRUE(td.DetermineResultType(&cast)) << td.error();
|
|
||||||
|
|
||||||
Builder b(&mod);
|
|
||||||
b.push_function(Function{});
|
|
||||||
EXPECT_EQ(b.GenerateCastExpression(&cast), 1u);
|
|
||||||
|
|
||||||
EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeInt 32 0
|
|
||||||
%3 = OpTypeFloat 32
|
|
||||||
%4 = OpConstant %3 2.4000001
|
|
||||||
)");
|
|
||||||
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
|
|
||||||
R"(%1 = OpConvertFToU %2 %4
|
|
||||||
)");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(BuilderTest, Cast_FloatToI32) {
|
|
||||||
ast::type::I32Type i32;
|
|
||||||
ast::type::F32Type f32;
|
|
||||||
|
|
||||||
ast::CastExpression cast(&i32,
|
|
||||||
std::make_unique<ast::ScalarConstructorExpression>(
|
|
||||||
std::make_unique<ast::FloatLiteral>(&f32, 2.4)));
|
|
||||||
|
|
||||||
Context ctx;
|
|
||||||
ast::Module mod;
|
|
||||||
TypeDeterminer td(&ctx, &mod);
|
|
||||||
ASSERT_TRUE(td.DetermineResultType(&cast)) << td.error();
|
|
||||||
|
|
||||||
Builder b(&mod);
|
|
||||||
b.push_function(Function{});
|
|
||||||
EXPECT_EQ(b.GenerateCastExpression(&cast), 1u);
|
|
||||||
|
|
||||||
EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeInt 32 1
|
|
||||||
%3 = OpTypeFloat 32
|
|
||||||
%4 = OpConstant %3 2.4000001
|
|
||||||
)");
|
|
||||||
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
|
|
||||||
R"(%1 = OpConvertFToS %2 %4
|
|
||||||
)");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(BuilderTest, Cast_I32ToFloat) {
|
|
||||||
ast::type::I32Type i32;
|
|
||||||
ast::type::F32Type f32;
|
|
||||||
|
|
||||||
ast::CastExpression cast(&f32,
|
|
||||||
std::make_unique<ast::ScalarConstructorExpression>(
|
|
||||||
std::make_unique<ast::SintLiteral>(&i32, 2)));
|
|
||||||
|
|
||||||
Context ctx;
|
|
||||||
ast::Module mod;
|
|
||||||
TypeDeterminer td(&ctx, &mod);
|
|
||||||
ASSERT_TRUE(td.DetermineResultType(&cast)) << td.error();
|
|
||||||
|
|
||||||
Builder b(&mod);
|
|
||||||
b.push_function(Function{});
|
|
||||||
EXPECT_EQ(b.GenerateCastExpression(&cast), 1u);
|
|
||||||
|
|
||||||
EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
|
|
||||||
%3 = OpTypeInt 32 1
|
|
||||||
%4 = OpConstant %3 2
|
|
||||||
)");
|
|
||||||
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
|
|
||||||
R"(%1 = OpConvertSToF %2 %4
|
|
||||||
)");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(BuilderTest, Cast_U32ToFloat) {
|
|
||||||
ast::type::U32Type u32;
|
|
||||||
ast::type::F32Type f32;
|
|
||||||
|
|
||||||
ast::CastExpression cast(&f32,
|
|
||||||
std::make_unique<ast::ScalarConstructorExpression>(
|
|
||||||
std::make_unique<ast::UintLiteral>(&u32, 2)));
|
|
||||||
|
|
||||||
Context ctx;
|
|
||||||
ast::Module mod;
|
|
||||||
TypeDeterminer td(&ctx, &mod);
|
|
||||||
ASSERT_TRUE(td.DetermineResultType(&cast)) << td.error();
|
|
||||||
|
|
||||||
Builder b(&mod);
|
|
||||||
b.push_function(Function{});
|
|
||||||
EXPECT_EQ(b.GenerateCastExpression(&cast), 1u);
|
|
||||||
|
|
||||||
EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
|
|
||||||
%3 = OpTypeInt 32 0
|
|
||||||
%4 = OpConstant %3 2
|
|
||||||
)");
|
|
||||||
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
|
|
||||||
R"(%1 = OpConvertUToF %2 %4
|
|
||||||
)");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(BuilderTest, Cast_WithLoad) {
|
|
||||||
ast::type::F32Type f32;
|
|
||||||
ast::type::I32Type i32;
|
|
||||||
|
|
||||||
// var i : i32 = 1;
|
|
||||||
// cast<f32>(i);
|
|
||||||
auto var =
|
|
||||||
std::make_unique<ast::Variable>("i", ast::StorageClass::kPrivate, &i32);
|
|
||||||
|
|
||||||
ast::CastExpression cast(&f32,
|
|
||||||
std::make_unique<ast::IdentifierExpression>("i"));
|
|
||||||
|
|
||||||
Context ctx;
|
|
||||||
ast::Module mod;
|
|
||||||
TypeDeterminer td(&ctx, &mod);
|
|
||||||
td.RegisterVariableForTesting(var.get());
|
|
||||||
ASSERT_TRUE(td.DetermineResultType(&cast)) << td.error();
|
|
||||||
|
|
||||||
Builder b(&mod);
|
|
||||||
b.push_function(Function{});
|
|
||||||
ASSERT_TRUE(b.GenerateGlobalVariable(var.get())) << b.error();
|
|
||||||
EXPECT_EQ(b.GenerateCastExpression(&cast), 5u) << b.error();
|
|
||||||
|
|
||||||
EXPECT_EQ(DumpInstructions(b.types()), R"(%3 = OpTypeInt 32 1
|
|
||||||
%2 = OpTypePointer Private %3
|
|
||||||
%4 = OpConstantNull %3
|
|
||||||
%1 = OpVariable %2 Private %4
|
|
||||||
%6 = OpTypeFloat 32
|
|
||||||
)");
|
|
||||||
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
|
|
||||||
R"(%7 = OpLoad %3 %1
|
|
||||||
%5 = OpConvertSToF %6 %7
|
|
||||||
)");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(BuilderTest, Cast_WithAlias) {
|
|
||||||
ast::type::I32Type i32;
|
|
||||||
ast::type::F32Type f32;
|
|
||||||
|
|
||||||
// type Int = i32
|
|
||||||
// cast<Int>(1.f)
|
|
||||||
|
|
||||||
ast::type::AliasType alias("Int", &i32);
|
|
||||||
|
|
||||||
ast::CastExpression cast(&alias,
|
|
||||||
std::make_unique<ast::ScalarConstructorExpression>(
|
|
||||||
std::make_unique<ast::FloatLiteral>(&f32, 2.3)));
|
|
||||||
|
|
||||||
Context ctx;
|
|
||||||
ast::Module mod;
|
|
||||||
TypeDeterminer td(&ctx, &mod);
|
|
||||||
ASSERT_TRUE(td.DetermineResultType(&cast)) << td.error();
|
|
||||||
|
|
||||||
Builder b(&mod);
|
|
||||||
b.push_function(Function{});
|
|
||||||
EXPECT_EQ(b.GenerateCastExpression(&cast), 1u);
|
|
||||||
|
|
||||||
EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeInt 32 1
|
|
||||||
%3 = OpTypeFloat 32
|
|
||||||
%4 = OpConstant %3 2.29999995
|
|
||||||
)");
|
|
||||||
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
|
|
||||||
R"(%1 = OpConvertFToS %2 %4
|
|
||||||
)");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(BuilderTest, Cast_I32ToU32) {
|
|
||||||
ast::type::U32Type u32;
|
|
||||||
ast::type::I32Type i32;
|
|
||||||
|
|
||||||
ast::CastExpression cast(&u32,
|
|
||||||
std::make_unique<ast::ScalarConstructorExpression>(
|
|
||||||
std::make_unique<ast::SintLiteral>(&i32, 2)));
|
|
||||||
|
|
||||||
Context ctx;
|
|
||||||
ast::Module mod;
|
|
||||||
TypeDeterminer td(&ctx, &mod);
|
|
||||||
ASSERT_TRUE(td.DetermineResultType(&cast)) << td.error();
|
|
||||||
|
|
||||||
Builder b(&mod);
|
|
||||||
b.push_function(Function{});
|
|
||||||
EXPECT_EQ(b.GenerateCastExpression(&cast), 1u);
|
|
||||||
|
|
||||||
EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeInt 32 0
|
|
||||||
%3 = OpTypeInt 32 1
|
|
||||||
%4 = OpConstant %3 2
|
|
||||||
)");
|
|
||||||
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
|
|
||||||
R"(%1 = OpBitcast %2 %4
|
|
||||||
)");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(BuilderTest, Cast_U32ToI32) {
|
|
||||||
ast::type::U32Type u32;
|
|
||||||
ast::type::I32Type i32;
|
|
||||||
|
|
||||||
ast::CastExpression cast(&i32,
|
|
||||||
std::make_unique<ast::ScalarConstructorExpression>(
|
|
||||||
std::make_unique<ast::UintLiteral>(&u32, 2)));
|
|
||||||
|
|
||||||
Context ctx;
|
|
||||||
ast::Module mod;
|
|
||||||
TypeDeterminer td(&ctx, &mod);
|
|
||||||
ASSERT_TRUE(td.DetermineResultType(&cast)) << td.error();
|
|
||||||
|
|
||||||
Builder b(&mod);
|
|
||||||
b.push_function(Function{});
|
|
||||||
EXPECT_EQ(b.GenerateCastExpression(&cast), 1u);
|
|
||||||
|
|
||||||
EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeInt 32 1
|
|
||||||
%3 = OpTypeInt 32 0
|
|
||||||
%4 = OpConstant %3 2
|
|
||||||
)");
|
|
||||||
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
|
|
||||||
R"(%1 = OpBitcast %2 %4
|
|
||||||
)");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(BuilderTest, Cast_I32ToI32) {
|
|
||||||
ast::type::I32Type i32;
|
|
||||||
|
|
||||||
ast::CastExpression cast(&i32,
|
|
||||||
std::make_unique<ast::ScalarConstructorExpression>(
|
|
||||||
std::make_unique<ast::SintLiteral>(&i32, 2)));
|
|
||||||
|
|
||||||
Context ctx;
|
|
||||||
ast::Module mod;
|
|
||||||
TypeDeterminer td(&ctx, &mod);
|
|
||||||
ASSERT_TRUE(td.DetermineResultType(&cast)) << td.error();
|
|
||||||
|
|
||||||
Builder b(&mod);
|
|
||||||
b.push_function(Function{});
|
|
||||||
EXPECT_EQ(b.GenerateCastExpression(&cast), 1u);
|
|
||||||
|
|
||||||
EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeInt 32 1
|
|
||||||
%3 = OpConstant %2 2
|
|
||||||
)");
|
|
||||||
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
|
|
||||||
R"(%1 = OpCopyObject %2 %3
|
|
||||||
)");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(BuilderTest, Cast_U32ToU32) {
|
|
||||||
ast::type::U32Type u32;
|
|
||||||
|
|
||||||
ast::CastExpression cast(&u32,
|
|
||||||
std::make_unique<ast::ScalarConstructorExpression>(
|
|
||||||
std::make_unique<ast::UintLiteral>(&u32, 2)));
|
|
||||||
|
|
||||||
Context ctx;
|
|
||||||
ast::Module mod;
|
|
||||||
TypeDeterminer td(&ctx, &mod);
|
|
||||||
ASSERT_TRUE(td.DetermineResultType(&cast)) << td.error();
|
|
||||||
|
|
||||||
Builder b(&mod);
|
|
||||||
b.push_function(Function{});
|
|
||||||
EXPECT_EQ(b.GenerateCastExpression(&cast), 1u);
|
|
||||||
|
|
||||||
EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeInt 32 0
|
|
||||||
%3 = OpConstant %2 2
|
|
||||||
)");
|
|
||||||
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
|
|
||||||
R"(%1 = OpCopyObject %2 %3
|
|
||||||
)");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(BuilderTest, Cast_F32ToF32) {
|
|
||||||
ast::type::F32Type f32;
|
|
||||||
|
|
||||||
ast::CastExpression cast(&f32,
|
|
||||||
std::make_unique<ast::ScalarConstructorExpression>(
|
|
||||||
std::make_unique<ast::FloatLiteral>(&f32, 2.0)));
|
|
||||||
|
|
||||||
Context ctx;
|
|
||||||
ast::Module mod;
|
|
||||||
TypeDeterminer td(&ctx, &mod);
|
|
||||||
ASSERT_TRUE(td.DetermineResultType(&cast)) << td.error();
|
|
||||||
|
|
||||||
Builder b(&mod);
|
|
||||||
b.push_function(Function{});
|
|
||||||
EXPECT_EQ(b.GenerateCastExpression(&cast), 1u);
|
|
||||||
|
|
||||||
EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
|
|
||||||
%3 = OpConstant %2 2
|
|
||||||
)");
|
|
||||||
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
|
|
||||||
R"(%1 = OpCopyObject %2 %3
|
|
||||||
)");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(BuilderTest, Cast_Vectors_I32_to_F32) {
|
|
||||||
ast::type::I32Type i32;
|
|
||||||
ast::type::VectorType ivec3(&i32, 3);
|
|
||||||
ast::type::F32Type f32;
|
|
||||||
ast::type::VectorType fvec3(&f32, 3);
|
|
||||||
|
|
||||||
auto var =
|
|
||||||
std::make_unique<ast::Variable>("i", ast::StorageClass::kPrivate, &ivec3);
|
|
||||||
|
|
||||||
ast::CastExpression cast(&fvec3,
|
|
||||||
std::make_unique<ast::IdentifierExpression>("i"));
|
|
||||||
|
|
||||||
Context ctx;
|
|
||||||
ast::Module mod;
|
|
||||||
TypeDeterminer td(&ctx, &mod);
|
|
||||||
td.RegisterVariableForTesting(var.get());
|
|
||||||
ASSERT_TRUE(td.DetermineResultType(&cast)) << td.error();
|
|
||||||
|
|
||||||
Builder b(&mod);
|
|
||||||
b.push_function(Function{});
|
|
||||||
ASSERT_TRUE(b.GenerateGlobalVariable(var.get())) << b.error();
|
|
||||||
EXPECT_EQ(b.GenerateCastExpression(&cast), 6u) << b.error();
|
|
||||||
|
|
||||||
EXPECT_EQ(DumpInstructions(b.types()), R"(%4 = OpTypeInt 32 1
|
|
||||||
%3 = OpTypeVector %4 3
|
|
||||||
%2 = OpTypePointer Private %3
|
|
||||||
%5 = OpConstantNull %3
|
|
||||||
%1 = OpVariable %2 Private %5
|
|
||||||
%8 = OpTypeFloat 32
|
|
||||||
%7 = OpTypeVector %8 3
|
|
||||||
)");
|
|
||||||
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
|
|
||||||
R"(%9 = OpLoad %3 %1
|
|
||||||
%6 = OpConvertSToF %7 %9
|
|
||||||
)");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(BuilderTest, Cast_Vectors_U32_to_F32) {
|
|
||||||
ast::type::U32Type u32;
|
|
||||||
ast::type::VectorType uvec3(&u32, 3);
|
|
||||||
ast::type::F32Type f32;
|
|
||||||
ast::type::VectorType fvec3(&f32, 3);
|
|
||||||
|
|
||||||
auto var =
|
|
||||||
std::make_unique<ast::Variable>("i", ast::StorageClass::kPrivate, &uvec3);
|
|
||||||
|
|
||||||
ast::CastExpression cast(&fvec3,
|
|
||||||
std::make_unique<ast::IdentifierExpression>("i"));
|
|
||||||
|
|
||||||
Context ctx;
|
|
||||||
ast::Module mod;
|
|
||||||
TypeDeterminer td(&ctx, &mod);
|
|
||||||
td.RegisterVariableForTesting(var.get());
|
|
||||||
ASSERT_TRUE(td.DetermineResultType(&cast)) << td.error();
|
|
||||||
|
|
||||||
Builder b(&mod);
|
|
||||||
b.push_function(Function{});
|
|
||||||
ASSERT_TRUE(b.GenerateGlobalVariable(var.get())) << b.error();
|
|
||||||
EXPECT_EQ(b.GenerateCastExpression(&cast), 6u) << b.error();
|
|
||||||
|
|
||||||
EXPECT_EQ(DumpInstructions(b.types()), R"(%4 = OpTypeInt 32 0
|
|
||||||
%3 = OpTypeVector %4 3
|
|
||||||
%2 = OpTypePointer Private %3
|
|
||||||
%5 = OpConstantNull %3
|
|
||||||
%1 = OpVariable %2 Private %5
|
|
||||||
%8 = OpTypeFloat 32
|
|
||||||
%7 = OpTypeVector %8 3
|
|
||||||
)");
|
|
||||||
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
|
|
||||||
R"(%9 = OpLoad %3 %1
|
|
||||||
%6 = OpConvertUToF %7 %9
|
|
||||||
)");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(BuilderTest, Cast_Vectors_F32_to_I32) {
|
|
||||||
ast::type::I32Type i32;
|
|
||||||
ast::type::VectorType ivec3(&i32, 3);
|
|
||||||
ast::type::F32Type f32;
|
|
||||||
ast::type::VectorType fvec3(&f32, 3);
|
|
||||||
|
|
||||||
auto var =
|
|
||||||
std::make_unique<ast::Variable>("i", ast::StorageClass::kPrivate, &fvec3);
|
|
||||||
|
|
||||||
ast::CastExpression cast(&ivec3,
|
|
||||||
std::make_unique<ast::IdentifierExpression>("i"));
|
|
||||||
|
|
||||||
Context ctx;
|
|
||||||
ast::Module mod;
|
|
||||||
TypeDeterminer td(&ctx, &mod);
|
|
||||||
td.RegisterVariableForTesting(var.get());
|
|
||||||
ASSERT_TRUE(td.DetermineResultType(&cast)) << td.error();
|
|
||||||
|
|
||||||
Builder b(&mod);
|
|
||||||
b.push_function(Function{});
|
|
||||||
ASSERT_TRUE(b.GenerateGlobalVariable(var.get())) << b.error();
|
|
||||||
EXPECT_EQ(b.GenerateCastExpression(&cast), 6u) << b.error();
|
|
||||||
|
|
||||||
EXPECT_EQ(DumpInstructions(b.types()), R"(%4 = OpTypeFloat 32
|
|
||||||
%3 = OpTypeVector %4 3
|
|
||||||
%2 = OpTypePointer Private %3
|
|
||||||
%5 = OpConstantNull %3
|
|
||||||
%1 = OpVariable %2 Private %5
|
|
||||||
%8 = OpTypeInt 32 1
|
|
||||||
%7 = OpTypeVector %8 3
|
|
||||||
)");
|
|
||||||
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
|
|
||||||
R"(%9 = OpLoad %3 %1
|
|
||||||
%6 = OpConvertFToS %7 %9
|
|
||||||
)");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(BuilderTest, Cast_Vectors_F32_to_U32) {
|
|
||||||
ast::type::U32Type u32;
|
|
||||||
ast::type::VectorType uvec3(&u32, 3);
|
|
||||||
ast::type::F32Type f32;
|
|
||||||
ast::type::VectorType fvec3(&f32, 3);
|
|
||||||
|
|
||||||
auto var =
|
|
||||||
std::make_unique<ast::Variable>("i", ast::StorageClass::kPrivate, &fvec3);
|
|
||||||
|
|
||||||
ast::CastExpression cast(&uvec3,
|
|
||||||
std::make_unique<ast::IdentifierExpression>("i"));
|
|
||||||
|
|
||||||
Context ctx;
|
|
||||||
ast::Module mod;
|
|
||||||
TypeDeterminer td(&ctx, &mod);
|
|
||||||
td.RegisterVariableForTesting(var.get());
|
|
||||||
ASSERT_TRUE(td.DetermineResultType(&cast)) << td.error();
|
|
||||||
|
|
||||||
Builder b(&mod);
|
|
||||||
b.push_function(Function{});
|
|
||||||
ASSERT_TRUE(b.GenerateGlobalVariable(var.get())) << b.error();
|
|
||||||
EXPECT_EQ(b.GenerateCastExpression(&cast), 6u) << b.error();
|
|
||||||
|
|
||||||
EXPECT_EQ(DumpInstructions(b.types()), R"(%4 = OpTypeFloat 32
|
|
||||||
%3 = OpTypeVector %4 3
|
|
||||||
%2 = OpTypePointer Private %3
|
|
||||||
%5 = OpConstantNull %3
|
|
||||||
%1 = OpVariable %2 Private %5
|
|
||||||
%8 = OpTypeInt 32 0
|
|
||||||
%7 = OpTypeVector %8 3
|
|
||||||
)");
|
|
||||||
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
|
|
||||||
R"(%9 = OpLoad %3 %1
|
|
||||||
%6 = OpConvertFToU %7 %9
|
|
||||||
)");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(BuilderTest, Cast_Vectors_U32_to_U32) {
|
|
||||||
ast::type::U32Type u32;
|
|
||||||
ast::type::VectorType uvec3(&u32, 3);
|
|
||||||
|
|
||||||
auto var =
|
|
||||||
std::make_unique<ast::Variable>("i", ast::StorageClass::kPrivate, &uvec3);
|
|
||||||
|
|
||||||
ast::CastExpression cast(&uvec3,
|
|
||||||
std::make_unique<ast::IdentifierExpression>("i"));
|
|
||||||
|
|
||||||
Context ctx;
|
|
||||||
ast::Module mod;
|
|
||||||
TypeDeterminer td(&ctx, &mod);
|
|
||||||
td.RegisterVariableForTesting(var.get());
|
|
||||||
ASSERT_TRUE(td.DetermineResultType(&cast)) << td.error();
|
|
||||||
|
|
||||||
Builder b(&mod);
|
|
||||||
b.push_function(Function{});
|
|
||||||
ASSERT_TRUE(b.GenerateGlobalVariable(var.get())) << b.error();
|
|
||||||
EXPECT_EQ(b.GenerateCastExpression(&cast), 6u) << b.error();
|
|
||||||
|
|
||||||
EXPECT_EQ(DumpInstructions(b.types()), R"(%4 = OpTypeInt 32 0
|
|
||||||
%3 = OpTypeVector %4 3
|
|
||||||
%2 = OpTypePointer Private %3
|
|
||||||
%5 = OpConstantNull %3
|
|
||||||
%1 = OpVariable %2 Private %5
|
|
||||||
)");
|
|
||||||
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
|
|
||||||
R"(%7 = OpLoad %3 %1
|
|
||||||
%6 = OpCopyObject %3 %7
|
|
||||||
)");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(BuilderTest, Cast_Vectors_I32_to_U32) {
|
|
||||||
ast::type::U32Type u32;
|
|
||||||
ast::type::VectorType uvec3(&u32, 3);
|
|
||||||
ast::type::I32Type i32;
|
|
||||||
ast::type::VectorType ivec3(&i32, 3);
|
|
||||||
|
|
||||||
auto var =
|
|
||||||
std::make_unique<ast::Variable>("i", ast::StorageClass::kPrivate, &ivec3);
|
|
||||||
|
|
||||||
ast::CastExpression cast(&uvec3,
|
|
||||||
std::make_unique<ast::IdentifierExpression>("i"));
|
|
||||||
|
|
||||||
Context ctx;
|
|
||||||
ast::Module mod;
|
|
||||||
TypeDeterminer td(&ctx, &mod);
|
|
||||||
td.RegisterVariableForTesting(var.get());
|
|
||||||
ASSERT_TRUE(td.DetermineResultType(&cast)) << td.error();
|
|
||||||
|
|
||||||
Builder b(&mod);
|
|
||||||
b.push_function(Function{});
|
|
||||||
ASSERT_TRUE(b.GenerateGlobalVariable(var.get())) << b.error();
|
|
||||||
EXPECT_EQ(b.GenerateCastExpression(&cast), 6u) << b.error();
|
|
||||||
|
|
||||||
EXPECT_EQ(DumpInstructions(b.types()), R"(%4 = OpTypeInt 32 1
|
|
||||||
%3 = OpTypeVector %4 3
|
|
||||||
%2 = OpTypePointer Private %3
|
|
||||||
%5 = OpConstantNull %3
|
|
||||||
%1 = OpVariable %2 Private %5
|
|
||||||
%8 = OpTypeInt 32 0
|
|
||||||
%7 = OpTypeVector %8 3
|
|
||||||
)");
|
|
||||||
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
|
|
||||||
R"(%9 = OpLoad %3 %1
|
|
||||||
%6 = OpBitcast %7 %9
|
|
||||||
)");
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
} // namespace spirv
|
|
||||||
} // namespace writer
|
|
||||||
} // namespace tint
|
|
File diff suppressed because it is too large
Load Diff
|
@ -29,7 +29,6 @@
|
||||||
#include "src/ast/call_expression.h"
|
#include "src/ast/call_expression.h"
|
||||||
#include "src/ast/call_statement.h"
|
#include "src/ast/call_statement.h"
|
||||||
#include "src/ast/case_statement.h"
|
#include "src/ast/case_statement.h"
|
||||||
#include "src/ast/cast_expression.h"
|
|
||||||
#include "src/ast/constructor_expression.h"
|
#include "src/ast/constructor_expression.h"
|
||||||
#include "src/ast/continue_statement.h"
|
#include "src/ast/continue_statement.h"
|
||||||
#include "src/ast/decorated_variable.h"
|
#include "src/ast/decorated_variable.h"
|
||||||
|
@ -186,9 +185,6 @@ bool GeneratorImpl::EmitExpression(ast::Expression* expr) {
|
||||||
if (expr->IsCall()) {
|
if (expr->IsCall()) {
|
||||||
return EmitCall(expr->AsCall());
|
return EmitCall(expr->AsCall());
|
||||||
}
|
}
|
||||||
if (expr->IsCast()) {
|
|
||||||
return EmitCast(expr->AsCast());
|
|
||||||
}
|
|
||||||
if (expr->IsIdentifier()) {
|
if (expr->IsIdentifier()) {
|
||||||
return EmitIdentifier(expr->AsIdentifier());
|
return EmitIdentifier(expr->AsIdentifier());
|
||||||
}
|
}
|
||||||
|
@ -269,21 +265,6 @@ bool GeneratorImpl::EmitCall(ast::CallExpression* expr) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GeneratorImpl::EmitCast(ast::CastExpression* expr) {
|
|
||||||
out_ << "cast<";
|
|
||||||
if (!EmitType(expr->type())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
out_ << ">(";
|
|
||||||
if (!EmitExpression(expr->expr())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
out_ << ")";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GeneratorImpl::EmitConstructor(ast::ConstructorExpression* expr) {
|
bool GeneratorImpl::EmitConstructor(ast::ConstructorExpression* expr) {
|
||||||
if (expr->IsScalarConstructor()) {
|
if (expr->IsScalarConstructor()) {
|
||||||
return EmitScalarConstructor(expr->AsScalarConstructor());
|
return EmitScalarConstructor(expr->AsScalarConstructor());
|
||||||
|
|
|
@ -98,10 +98,6 @@ class GeneratorImpl : public TextGenerator {
|
||||||
/// @param stmt the statement
|
/// @param stmt the statement
|
||||||
/// @returns true if the statment was emitted successfully
|
/// @returns true if the statment was emitted successfully
|
||||||
bool EmitCase(ast::CaseStatement* stmt);
|
bool EmitCase(ast::CaseStatement* stmt);
|
||||||
/// Handles generating a cast expression
|
|
||||||
/// @param expr the cast expression
|
|
||||||
/// @returns true if the cast was emitted
|
|
||||||
bool EmitCast(ast::CastExpression* expr);
|
|
||||||
/// Handles generating a scalar constructor
|
/// Handles generating a scalar constructor
|
||||||
/// @param expr the scalar constructor expression
|
/// @param expr the scalar constructor expression
|
||||||
/// @returns true if the scalar constructor is emitted
|
/// @returns true if the scalar constructor is emitted
|
||||||
|
|
|
@ -15,9 +15,9 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
#include "src/ast/cast_expression.h"
|
|
||||||
#include "src/ast/identifier_expression.h"
|
#include "src/ast/identifier_expression.h"
|
||||||
#include "src/ast/type/f32_type.h"
|
#include "src/ast/type/f32_type.h"
|
||||||
|
#include "src/ast/type_constructor_expression.h"
|
||||||
#include "src/writer/wgsl/generator_impl.h"
|
#include "src/writer/wgsl/generator_impl.h"
|
||||||
|
|
||||||
namespace tint {
|
namespace tint {
|
||||||
|
@ -29,12 +29,15 @@ using WgslGeneratorImplTest = testing::Test;
|
||||||
|
|
||||||
TEST_F(WgslGeneratorImplTest, EmitExpression_Cast) {
|
TEST_F(WgslGeneratorImplTest, EmitExpression_Cast) {
|
||||||
ast::type::F32Type f32;
|
ast::type::F32Type f32;
|
||||||
auto id = std::make_unique<ast::IdentifierExpression>("id");
|
|
||||||
ast::CastExpression cast(&f32, std::move(id));
|
ast::ExpressionList params;
|
||||||
|
params.push_back(std::make_unique<ast::IdentifierExpression>("id"));
|
||||||
|
|
||||||
|
ast::TypeConstructorExpression cast(&f32, std::move(params));
|
||||||
|
|
||||||
GeneratorImpl g;
|
GeneratorImpl g;
|
||||||
ASSERT_TRUE(g.EmitExpression(&cast)) << g.error();
|
ASSERT_TRUE(g.EmitExpression(&cast)) << g.error();
|
||||||
EXPECT_EQ(g.result(), "cast<f32>(id)");
|
EXPECT_EQ(g.result(), "f32(id)");
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
Loading…
Reference in New Issue