tint: Merge [S|U]intLiteralExpression

Merge SintLiteralExpression and UintLiteralExpression with
IntLiteralExpression. IntLiteralExpression has a new Suffix field which
indicates whether the literal is either a:
• 'i' suffixed integer literal
• 'u' suffixed integer literal
• no-suffix integer literal

Have the SPIR-V reader produce no-suffixed literals for i32 types, to
keep this change small. In future changes the SPIR-V reader will
produce 'i' suffixed types for these.

Have all consumers of IntLiteralExpression treat unsuffixed integers the
same as 'i'-suffixed literals. Unsuffixed will be treated as abstract in
future changes.

Removed SemHelper::TypeOf(const ast::LiteralExpression* lit).

Fixed: tint:1510
Bug: tint:1504
Change-Id: I443f41984e637ddd948182ee756af1010c5f8226
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/88842
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
Commit-Queue: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
Ben Clayton 2022-05-04 22:18:49 +00:00 committed by Dawn LUCI CQ
parent 5afd422e44
commit 8822e2966a
48 changed files with 553 additions and 598 deletions

View File

@ -288,8 +288,6 @@ libtint_source_set("libtint_core_all_src") {
"ast/sampled_texture.h",
"ast/sampler.cc",
"ast/sampler.h",
"ast/sint_literal_expression.cc",
"ast/sint_literal_expression.h",
"ast/stage_attribute.cc",
"ast/stage_attribute.h",
"ast/statement.cc",
@ -322,8 +320,6 @@ libtint_source_set("libtint_core_all_src") {
"ast/type_name.h",
"ast/u32.cc",
"ast/u32.h",
"ast/uint_literal_expression.cc",
"ast/uint_literal_expression.h",
"ast/unary_op.cc",
"ast/unary_op.h",
"ast/unary_op_expression.cc",

View File

@ -174,8 +174,6 @@ set(TINT_LIB_SRCS
ast/sampled_texture.h
ast/sampler.cc
ast/sampler.h
ast/sint_literal_expression.cc
ast/sint_literal_expression.h
ast/stage_attribute.cc
ast/stage_attribute.h
ast/statement.cc
@ -211,8 +209,6 @@ set(TINT_LIB_SRCS
ast/type_name.h
ast/u32.cc
ast/u32.h
ast/uint_literal_expression.cc
ast/uint_literal_expression.h
ast/unary_op_expression.cc
ast/unary_op_expression.h
ast/unary_op.cc
@ -711,7 +707,6 @@ if(TINT_BUILD_TESTS)
ast/return_statement_test.cc
ast/sampled_texture_test.cc
ast/sampler_test.cc
ast/sint_literal_expression_test.cc
ast/stage_attribute_test.cc
ast/storage_texture_test.cc
ast/stride_attribute_test.cc
@ -725,7 +720,6 @@ if(TINT_BUILD_TESTS)
ast/texture_test.cc
ast/traverse_expressions_test.cc
ast/u32_test.cc
ast/uint_literal_expression_test.cc
ast/unary_op_expression_test.cc
ast/variable_decl_statement_test.cc
ast/variable_test.cc

View File

@ -29,7 +29,7 @@ std::string SizeExprToString(const Expression* size, const SymbolTable& symbols)
return symbols.NameFor(ident->symbol);
}
if (auto* literal = size->As<IntLiteralExpression>()) {
return std::to_string(literal->ValueAsU32());
return std::to_string(literal->value);
}
// This will never be exposed to the user as the Resolver will reject this
// expression for array size.

View File

@ -26,7 +26,7 @@ using CaseStatementTest = TestHelper;
TEST_F(CaseStatementTest, Creation_i32) {
CaseSelectorList b;
auto* selector = create<SintLiteralExpression>(2);
auto* selector = Expr(2);
b.push_back(selector);
auto* discard = create<DiscardStatement>();
@ -41,7 +41,7 @@ TEST_F(CaseStatementTest, Creation_i32) {
TEST_F(CaseStatementTest, Creation_u32) {
CaseSelectorList b;
auto* selector = create<UintLiteralExpression>(2u);
auto* selector = Expr(2u);
b.push_back(selector);
auto* discard = create<DiscardStatement>();
@ -56,7 +56,7 @@ TEST_F(CaseStatementTest, Creation_u32) {
TEST_F(CaseStatementTest, Creation_WithSource) {
CaseSelectorList b;
b.push_back(create<SintLiteralExpression>(2));
b.push_back(Expr(2));
auto* body = create<BlockStatement>(StatementList{
create<DiscardStatement>(),
@ -77,7 +77,7 @@ TEST_F(CaseStatementTest, IsDefault_WithoutSelectors) {
TEST_F(CaseStatementTest, IsDefault_WithSelectors) {
CaseSelectorList b;
b.push_back(create<SintLiteralExpression>(2));
b.push_back(Expr(2));
auto* c = create<CaseStatement>(b, create<BlockStatement>(StatementList{}));
EXPECT_FALSE(c->IsDefault());
@ -123,7 +123,7 @@ TEST_F(CaseStatementTest, Assert_DifferentProgramID_Selector) {
{
ProgramBuilder b1;
ProgramBuilder b2;
b1.create<CaseStatement>(CaseSelectorList{b2.create<SintLiteralExpression>(2)},
b1.create<CaseStatement>(CaseSelectorList{b2.Expr(2)},
b1.create<BlockStatement>(StatementList{}));
},
"internal compiler error");

View File

@ -14,12 +14,35 @@
#include "src/tint/ast/int_literal_expression.h"
#include "src/tint/program_builder.h"
TINT_INSTANTIATE_TYPEINFO(tint::ast::IntLiteralExpression);
namespace tint::ast {
IntLiteralExpression::IntLiteralExpression(ProgramID pid, const Source& src) : Base(pid, src) {}
IntLiteralExpression::IntLiteralExpression(ProgramID pid,
const Source& src,
int64_t val,
Suffix suf)
: Base(pid, src), value(val), suffix(suf) {}
IntLiteralExpression::~IntLiteralExpression() = default;
const IntLiteralExpression* IntLiteralExpression::Clone(CloneContext* ctx) const {
// Clone arguments outside of create() call to have deterministic ordering
auto src = ctx->Clone(source);
return ctx->dst->create<IntLiteralExpression>(src, value, suffix);
}
std::ostream& operator<<(std::ostream& out, IntLiteralExpression::Suffix suffix) {
switch (suffix) {
default:
return out;
case IntLiteralExpression::Suffix::kI:
return out << "i";
case IntLiteralExpression::Suffix::kU:
return out << "u";
}
}
} // namespace tint::ast

View File

@ -19,23 +19,46 @@
namespace tint::ast {
/// An integer literal. This could be either signed or unsigned.
/// An integer literal. The literal may have an 'i', 'u' or no suffix.
class IntLiteralExpression : public Castable<IntLiteralExpression, LiteralExpression> {
public:
~IntLiteralExpression() override;
/// Literal suffix
enum class Suffix {
/// No suffix
kNone,
/// 'i' suffix (i32)
kI,
/// 'u' suffix (u32)
kU,
};
/// @returns the literal value as a u32
virtual uint32_t ValueAsU32() const = 0;
/// @returns the literal value as an i32
int32_t ValueAsI32() const { return static_cast<int32_t>(ValueAsU32()); }
protected:
/// Constructor
/// @param pid the identifier of the program that owns this node
/// @param src the source of this node
IntLiteralExpression(ProgramID pid, const Source& src);
}; // namespace ast
/// @param val the literal value
/// @param suf the literal suffix
IntLiteralExpression(ProgramID pid, const Source& src, int64_t val, Suffix suf);
~IntLiteralExpression() override;
/// Clones this node and all transitive child nodes using the `CloneContext`
/// `ctx`.
/// @param ctx the clone context
/// @return the newly cloned node
const IntLiteralExpression* Clone(CloneContext* ctx) const override;
/// The literal value
const int64_t value;
/// The literal suffix
const Suffix suffix;
};
/// Writes the integer literal suffix to the std::ostream.
/// @param out the std::ostream to write to
/// @param suffix the suffix to write
/// @returns out so calls can be chained
std::ostream& operator<<(std::ostream& out, IntLiteralExpression::Suffix suffix);
} // namespace tint::ast

View File

@ -19,14 +19,25 @@ namespace {
using IntLiteralExpressionTest = TestHelper;
TEST_F(IntLiteralExpressionTest, Sint_IsInt) {
auto* i = create<SintLiteralExpression>(47);
TEST_F(IntLiteralExpressionTest, SuffixNone) {
auto* i = create<IntLiteralExpression>(42, IntLiteralExpression::Suffix::kNone);
ASSERT_TRUE(i->Is<IntLiteralExpression>());
EXPECT_EQ(i->value, 42);
EXPECT_EQ(i->suffix, IntLiteralExpression::Suffix::kNone);
}
TEST_F(IntLiteralExpressionTest, Uint_IsInt) {
auto* i = create<UintLiteralExpression>(42);
EXPECT_TRUE(i->Is<IntLiteralExpression>());
TEST_F(IntLiteralExpressionTest, SuffixI) {
auto* i = create<IntLiteralExpression>(42, IntLiteralExpression::Suffix::kI);
ASSERT_TRUE(i->Is<IntLiteralExpression>());
EXPECT_EQ(i->value, 42);
EXPECT_EQ(i->suffix, IntLiteralExpression::Suffix::kI);
}
TEST_F(IntLiteralExpressionTest, SuffixU) {
auto* i = create<IntLiteralExpression>(42, IntLiteralExpression::Suffix::kU);
ASSERT_TRUE(i->Is<IntLiteralExpression>());
EXPECT_EQ(i->value, 42);
EXPECT_EQ(i->suffix, IntLiteralExpression::Suffix::kU);
}
} // namespace

View File

@ -1,38 +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/tint/ast/sint_literal_expression.h"
#include "src/tint/program_builder.h"
TINT_INSTANTIATE_TYPEINFO(tint::ast::SintLiteralExpression);
namespace tint::ast {
SintLiteralExpression::SintLiteralExpression(ProgramID pid, const Source& src, int32_t val)
: Base(pid, src), value(val) {}
SintLiteralExpression::~SintLiteralExpression() = default;
uint32_t SintLiteralExpression::ValueAsU32() const {
return static_cast<uint32_t>(value);
}
const SintLiteralExpression* SintLiteralExpression::Clone(CloneContext* ctx) const {
// Clone arguments outside of create() call to have deterministic ordering
auto src = ctx->Clone(source);
return ctx->dst->create<SintLiteralExpression>(src, value);
}
} // namespace tint::ast

View File

@ -1,49 +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_TINT_AST_SINT_LITERAL_EXPRESSION_H_
#define SRC_TINT_AST_SINT_LITERAL_EXPRESSION_H_
#include <string>
#include "src/tint/ast/int_literal_expression.h"
namespace tint::ast {
/// A signed int literal
class SintLiteralExpression final : public Castable<SintLiteralExpression, IntLiteralExpression> {
public:
/// Constructor
/// @param pid the identifier of the program that owns this node
/// @param src the source of this node
/// @param value the signed int literals value
SintLiteralExpression(ProgramID pid, const Source& src, int32_t value);
~SintLiteralExpression() override;
/// @returns the literal value as a u32
uint32_t ValueAsU32() const override;
/// Clones this node and all transitive child nodes using the `CloneContext`
/// `ctx`.
/// @param ctx the clone context
/// @return the newly cloned node
const SintLiteralExpression* Clone(CloneContext* ctx) const override;
/// The int literal value
const int32_t value;
};
} // namespace tint::ast
#endif // SRC_TINT_AST_SINT_LITERAL_EXPRESSION_H_

View File

@ -1,29 +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/tint/ast/test_helper.h"
namespace tint::ast {
namespace {
using SintLiteralExpressionTest = TestHelper;
TEST_F(SintLiteralExpressionTest, Value) {
auto* i = create<SintLiteralExpression>(47);
ASSERT_TRUE(i->Is<SintLiteralExpression>());
EXPECT_EQ(i->value, 47);
}
} // namespace
} // namespace tint::ast

View File

@ -24,7 +24,7 @@ using SwitchStatementTest = TestHelper;
TEST_F(SwitchStatementTest, Creation) {
CaseSelectorList lit;
lit.push_back(create<SintLiteralExpression>(1));
lit.push_back(Expr(1));
auto* ident = Expr("ident");
CaseStatementList body;
@ -49,7 +49,7 @@ TEST_F(SwitchStatementTest, Creation_WithSource) {
TEST_F(SwitchStatementTest, IsSwitch) {
CaseSelectorList lit;
lit.push_back(create<SintLiteralExpression>(2));
lit.push_back(Expr(2));
auto* ident = Expr("ident");
CaseStatementList body;

View File

@ -1,38 +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/tint/ast/uint_literal_expression.h"
#include "src/tint/program_builder.h"
TINT_INSTANTIATE_TYPEINFO(tint::ast::UintLiteralExpression);
namespace tint::ast {
UintLiteralExpression::UintLiteralExpression(ProgramID pid, const Source& src, uint32_t val)
: Base(pid, src), value(val) {}
UintLiteralExpression::~UintLiteralExpression() = default;
uint32_t UintLiteralExpression::ValueAsU32() const {
return value;
}
const UintLiteralExpression* UintLiteralExpression::Clone(CloneContext* ctx) const {
// Clone arguments outside of create() call to have deterministic ordering
auto src = ctx->Clone(source);
return ctx->dst->create<UintLiteralExpression>(src, value);
}
} // namespace tint::ast

View File

@ -1,49 +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_TINT_AST_UINT_LITERAL_EXPRESSION_H_
#define SRC_TINT_AST_UINT_LITERAL_EXPRESSION_H_
#include <string>
#include "src/tint/ast/int_literal_expression.h"
namespace tint::ast {
/// A uint literal
class UintLiteralExpression final : public Castable<UintLiteralExpression, IntLiteralExpression> {
public:
/// Constructor
/// @param pid the identifier of the program that owns this node
/// @param src the source of this node
/// @param value the uint literals value
UintLiteralExpression(ProgramID pid, const Source& src, uint32_t value);
~UintLiteralExpression() override;
/// @returns the literal value as a u32
uint32_t ValueAsU32() const override;
/// Clones this node and all transitive child nodes using the `CloneContext`
/// `ctx`.
/// @param ctx the clone context
/// @return the newly cloned node
const UintLiteralExpression* Clone(CloneContext* ctx) const override;
/// The int literal value
const uint32_t value;
};
} // namespace tint::ast
#endif // SRC_TINT_AST_UINT_LITERAL_EXPRESSION_H_

View File

@ -1,29 +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/tint/ast/test_helper.h"
namespace tint::ast {
namespace {
using UintLiteralExpressionTest = TestHelper;
TEST_F(UintLiteralExpressionTest, Value) {
auto* u = create<UintLiteralExpression>(47);
ASSERT_TRUE(u->Is<UintLiteralExpression>());
EXPECT_EQ(u->value, 47u);
}
} // namespace
} // namespace tint::ast

View File

@ -27,7 +27,7 @@ TEST_F(WorkgroupAttributeTest, Creation_1param) {
auto values = d->Values();
ASSERT_TRUE(values[0]->Is<ast::IntLiteralExpression>());
EXPECT_EQ(values[0]->As<ast::IntLiteralExpression>()->ValueAsU32(), 2u);
EXPECT_EQ(values[0]->As<ast::IntLiteralExpression>()->value, 2);
EXPECT_EQ(values[1], nullptr);
EXPECT_EQ(values[2], nullptr);
@ -37,10 +37,10 @@ TEST_F(WorkgroupAttributeTest, Creation_2param) {
auto values = d->Values();
ASSERT_TRUE(values[0]->Is<ast::IntLiteralExpression>());
EXPECT_EQ(values[0]->As<ast::IntLiteralExpression>()->ValueAsU32(), 2u);
EXPECT_EQ(values[0]->As<ast::IntLiteralExpression>()->value, 2);
ASSERT_TRUE(values[1]->Is<ast::IntLiteralExpression>());
EXPECT_EQ(values[1]->As<ast::IntLiteralExpression>()->ValueAsU32(), 4u);
EXPECT_EQ(values[1]->As<ast::IntLiteralExpression>()->value, 4);
EXPECT_EQ(values[2], nullptr);
}
@ -50,13 +50,13 @@ TEST_F(WorkgroupAttributeTest, Creation_3param) {
auto values = d->Values();
ASSERT_TRUE(values[0]->Is<ast::IntLiteralExpression>());
EXPECT_EQ(values[0]->As<ast::IntLiteralExpression>()->ValueAsU32(), 2u);
EXPECT_EQ(values[0]->As<ast::IntLiteralExpression>()->value, 2);
ASSERT_TRUE(values[1]->Is<ast::IntLiteralExpression>());
EXPECT_EQ(values[1]->As<ast::IntLiteralExpression>()->ValueAsU32(), 4u);
EXPECT_EQ(values[1]->As<ast::IntLiteralExpression>()->value, 4);
ASSERT_TRUE(values[2]->Is<ast::IntLiteralExpression>());
EXPECT_EQ(values[2]->As<ast::IntLiteralExpression>()->ValueAsU32(), 6u);
EXPECT_EQ(values[2]->As<ast::IntLiteralExpression>()->value, 6);
}
TEST_F(WorkgroupAttributeTest, Creation_WithIdentifier) {
@ -64,10 +64,10 @@ TEST_F(WorkgroupAttributeTest, Creation_WithIdentifier) {
auto values = d->Values();
ASSERT_TRUE(values[0]->Is<ast::IntLiteralExpression>());
EXPECT_EQ(values[0]->As<ast::IntLiteralExpression>()->ValueAsU32(), 2u);
EXPECT_EQ(values[0]->As<ast::IntLiteralExpression>()->value, 2);
ASSERT_TRUE(values[1]->Is<ast::IntLiteralExpression>());
EXPECT_EQ(values[1]->As<ast::IntLiteralExpression>()->ValueAsU32(), 4u);
EXPECT_EQ(values[1]->As<ast::IntLiteralExpression>()->value, 4);
auto* z_ident = As<ast::IdentifierExpression>(values[2]);
ASSERT_TRUE(z_ident);

View File

@ -24,8 +24,6 @@
#include "src/tint/ast/interpolate_attribute.h"
#include "src/tint/ast/location_attribute.h"
#include "src/tint/ast/module.h"
#include "src/tint/ast/sint_literal_expression.h"
#include "src/tint/ast/uint_literal_expression.h"
#include "src/tint/sem/array.h"
#include "src/tint/sem/call.h"
#include "src/tint/sem/depth_multisampled_texture.h"
@ -248,14 +246,16 @@ std::map<uint32_t, Scalar> Inspector::GetConstantIDs() {
continue;
}
if (auto* l = literal->As<ast::UintLiteralExpression>()) {
result[constant_id] = Scalar(l->value);
continue;
}
if (auto* l = literal->As<ast::SintLiteralExpression>()) {
result[constant_id] = Scalar(l->value);
continue;
if (auto* l = literal->As<ast::IntLiteralExpression>()) {
switch (l->suffix) {
case ast::IntLiteralExpression::Suffix::kNone:
case ast::IntLiteralExpression::Suffix::kI:
result[constant_id] = Scalar(static_cast<int32_t>(l->value));
continue;
case ast::IntLiteralExpression::Suffix::kU:
result[constant_id] = Scalar(static_cast<uint32_t>(l->value));
continue;
}
}
if (auto* l = literal->As<ast::FloatLiteralExpression>()) {

View File

@ -61,7 +61,6 @@
#include "src/tint/ast/return_statement.h"
#include "src/tint/ast/sampled_texture.h"
#include "src/tint/ast/sampler.h"
#include "src/tint/ast/sint_literal_expression.h"
#include "src/tint/ast/stage_attribute.h"
#include "src/tint/ast/storage_texture.h"
#include "src/tint/ast/stride_attribute.h"
@ -71,7 +70,6 @@
#include "src/tint/ast/switch_statement.h"
#include "src/tint/ast/type_name.h"
#include "src/tint/ast/u32.h"
#include "src/tint/ast/uint_literal_expression.h"
#include "src/tint/ast/unary_op_expression.h"
#include "src/tint/ast/variable_decl_statement.h"
#include "src/tint/ast/vector.h"
@ -1018,27 +1016,29 @@ class ProgramBuilder {
/// @param source the source information
/// @param value the integer value
/// @return a Scalar constructor for the given value
const ast::SintLiteralExpression* Expr(const Source& source, i32 value) {
return create<ast::SintLiteralExpression>(source, value);
const ast::IntLiteralExpression* Expr(const Source& source, i32 value) {
return create<ast::IntLiteralExpression>(source, value,
ast::IntLiteralExpression::Suffix::kNone);
}
/// @param value the integer value
/// @return a Scalar constructor for the given value
const ast::SintLiteralExpression* Expr(i32 value) {
return create<ast::SintLiteralExpression>(value);
const ast::IntLiteralExpression* Expr(i32 value) {
return create<ast::IntLiteralExpression>(value, ast::IntLiteralExpression::Suffix::kNone);
}
/// @param source the source information
/// @param value the unsigned int value
/// @return a Scalar constructor for the given value
const ast::UintLiteralExpression* Expr(const Source& source, u32 value) {
return create<ast::UintLiteralExpression>(source, value);
const ast::IntLiteralExpression* Expr(const Source& source, u32 value) {
return create<ast::IntLiteralExpression>(source, value,
ast::IntLiteralExpression::Suffix::kU);
}
/// @param value the unsigned int value
/// @return a Scalar constructor for the given value
const ast::UintLiteralExpression* Expr(u32 value) {
return create<ast::UintLiteralExpression>(value);
const ast::IntLiteralExpression* Expr(u32 value) {
return create<ast::IntLiteralExpression>(value, ast::IntLiteralExpression::Suffix::kU);
}
/// Converts `arg` to an `ast::Expression` using `Expr()`, then appends it to

View File

@ -2986,9 +2986,12 @@ bool FunctionEmitter::EmitSwitchStart(const BlockInfo& block_info) {
// The Tint AST handles 32-bit values.
const uint32_t value32 = uint32_t(value & 0xFFFFFFFF);
if (selector.type->IsUnsignedScalarOrVector()) {
selectors.emplace_back(create<ast::UintLiteralExpression>(Source{}, value32));
selectors.emplace_back(create<ast::IntLiteralExpression>(
Source{}, value32, ast::IntLiteralExpression::Suffix::kU));
} else {
selectors.emplace_back(create<ast::SintLiteralExpression>(Source{}, value32));
selectors.emplace_back(create<ast::IntLiteralExpression>(
Source{}, static_cast<int32_t>(value32),
ast::IntLiteralExpression::Suffix::kNone));
}
}
}
@ -4298,7 +4301,8 @@ TypedExpression FunctionEmitter::MakeCompositeValueDecomposition(
auto current_type_id = composite_type_id;
auto make_index = [this](uint32_t literal) {
return create<ast::UintLiteralExpression>(Source{}, literal);
return create<ast::IntLiteralExpression>(Source{}, literal,
ast::IntLiteralExpression::Suffix::kU);
};
// Build up a nested expression for the decomposition by walking down the type

View File

@ -1327,18 +1327,25 @@ bool ParserImpl::EmitScalarSpecConstants() {
case SpvOpSpecConstant: {
ast_type = ConvertType(inst.type_id());
const uint32_t literal_value = inst.GetSingleWordInOperand(0);
if (ast_type->Is<I32>()) {
ast_expr = create<ast::SintLiteralExpression>(
Source{}, static_cast<int32_t>(literal_value));
} else if (ast_type->Is<U32>()) {
ast_expr = create<ast::UintLiteralExpression>(
Source{}, static_cast<uint32_t>(literal_value));
} else if (ast_type->Is<F32>()) {
float float_value;
// Copy the bits so we can read them as a float.
std::memcpy(&float_value, &literal_value, sizeof(float_value));
ast_expr = create<ast::FloatLiteralExpression>(Source{}, float_value);
} else {
ast_expr = Switch(
ast_type, //
[&](const I32*) {
return create<ast::IntLiteralExpression>(
Source{}, static_cast<int64_t>(literal_value),
ast::IntLiteralExpression::Suffix::kNone);
},
[&](const U32*) {
return create<ast::IntLiteralExpression>(
Source{}, static_cast<uint64_t>(literal_value),
ast::IntLiteralExpression::Suffix::kU);
},
[&](const F32*) {
float float_value;
// Copy the bits so we can read them as a float.
std::memcpy(&float_value, &literal_value, sizeof(float_value));
return create<ast::FloatLiteralExpression>(Source{}, float_value);
});
if (ast_expr == nullptr) {
return Fail() << " invalid result type for OpSpecConstant "
<< inst.PrettyPrint();
}
@ -1895,22 +1902,31 @@ TypedExpression ParserImpl::MakeConstantExpressionForScalarSpirvConstant(
// So canonicalization should map that way too.
// Currently "null<type>" is missing from the WGSL parser.
// See https://bugs.chromium.org/p/tint/issues/detail?id=34
if (ast_type->Is<U32>()) {
return {ty_.U32(), create<ast::UintLiteralExpression>(source, spirv_const->GetU32())};
}
if (ast_type->Is<I32>()) {
return {ty_.I32(), create<ast::SintLiteralExpression>(source, spirv_const->GetS32())};
}
if (ast_type->Is<F32>()) {
return {ty_.F32(), create<ast::FloatLiteralExpression>(source, spirv_const->GetFloat())};
}
if (ast_type->Is<Bool>()) {
const bool value =
spirv_const->AsNullConstant() ? false : spirv_const->AsBoolConstant()->value();
return {ty_.Bool(), create<ast::BoolLiteralExpression>(source, value)};
}
Fail() << "expected scalar constant";
return {};
return Switch(
ast_type,
[&](const I32*) {
return TypedExpression{ty_.I32(), create<ast::IntLiteralExpression>(
source, spirv_const->GetS32(),
ast::IntLiteralExpression::Suffix::kNone)};
},
[&](const U32*) {
return TypedExpression{ty_.U32(), create<ast::IntLiteralExpression>(
source, spirv_const->GetU32(),
ast::IntLiteralExpression::Suffix::kU)};
},
[&](const F32*) {
return TypedExpression{
ty_.F32(), create<ast::FloatLiteralExpression>(source, spirv_const->GetFloat())};
},
[&](const Bool*) {
const bool value =
spirv_const->AsNullConstant() ? false : spirv_const->AsBoolConstant()->value();
return TypedExpression{ty_.Bool(), create<ast::BoolLiteralExpression>(source, value)};
},
[&](Default) {
Fail() << "expected scalar constant";
return TypedExpression{};
});
}
const ast::Expression* ParserImpl::MakeNullValue(const Type* type) {
@ -1927,31 +1943,33 @@ const ast::Expression* ParserImpl::MakeNullValue(const Type* type) {
auto* original_type = type;
type = type->UnwrapAlias();
if (type->Is<Bool>()) {
return create<ast::BoolLiteralExpression>(Source{}, false);
}
if (type->Is<U32>()) {
return create<ast::UintLiteralExpression>(Source{}, 0u);
}
if (type->Is<I32>()) {
return create<ast::SintLiteralExpression>(Source{}, 0);
}
if (type->Is<F32>()) {
return create<ast::FloatLiteralExpression>(Source{}, 0.0f);
}
if (type->IsAnyOf<Vector, Matrix, Array>()) {
return builder_.Construct(Source{}, type->Build(builder_));
}
if (auto* struct_ty = type->As<Struct>()) {
ast::ExpressionList ast_components;
for (auto* member : struct_ty->members) {
ast_components.emplace_back(MakeNullValue(member));
}
return builder_.Construct(Source{}, original_type->Build(builder_),
std::move(ast_components));
}
Fail() << "can't make null value for type: " << type->TypeInfo().name;
return nullptr;
return Switch(
type, //
[&](const I32*) {
return create<ast::IntLiteralExpression>(Source{}, 0,
ast::IntLiteralExpression::Suffix::kNone);
},
[&](const U32*) {
return create<ast::IntLiteralExpression>(Source{}, 0,
ast::IntLiteralExpression::Suffix::kU);
},
[&](const F32*) { return create<ast::FloatLiteralExpression>(Source{}, 0.0f); },
[&](const Vector*) { return builder_.Construct(Source{}, type->Build(builder_)); },
[&](const Matrix*) { return builder_.Construct(Source{}, type->Build(builder_)); },
[&](const Array*) { return builder_.Construct(Source{}, type->Build(builder_)); },
[&](const Bool*) { return create<ast::BoolLiteralExpression>(Source{}, false); },
[&](const Struct* struct_ty) {
ast::ExpressionList ast_components;
for (auto* member : struct_ty->members) {
ast_components.emplace_back(MakeNullValue(member));
}
return builder_.Construct(Source{}, original_type->Build(builder_),
std::move(ast_components));
},
[&](Default) {
Fail() << "can't make null value for type: " << type->TypeInfo().name;
return nullptr;
});
}
TypedExpression ParserImpl::MakeNullExpression(const Type* type) {

View File

@ -2772,20 +2772,22 @@ Maybe<const ast::Statement*> ParserImpl::assignment_stmt() {
// const_literal
// : INT_LITERAL
// | UINT_LITERAL
// | FLOAT_LITERAL
// | TRUE
// | FALSE
Maybe<const ast::LiteralExpression*> ParserImpl::const_literal() {
auto t = peek();
if (match(Token::Type::kIntLiteral)) {
return create<ast::SintLiteralExpression>(t.source(), static_cast<int32_t>(t.to_i64()));
return create<ast::IntLiteralExpression>(t.source(), t.to_i64(),
ast::IntLiteralExpression::Suffix::kNone);
}
if (match(Token::Type::kIntILiteral)) {
return create<ast::SintLiteralExpression>(t.source(), static_cast<int32_t>(t.to_i64()));
return create<ast::IntLiteralExpression>(t.source(), t.to_i64(),
ast::IntLiteralExpression::Suffix::kI);
}
if (match(Token::Type::kIntULiteral)) {
return create<ast::UintLiteralExpression>(t.source(), static_cast<uint32_t>(t.to_i64()));
return create<ast::IntLiteralExpression>(t.source(), t.to_i64(),
ast::IntLiteralExpression::Suffix::kU);
}
if (match(Token::Type::kFloatLiteral)) {
return create<ast::FloatLiteralExpression>(t.source(), t.to_f32());

View File

@ -34,8 +34,10 @@ TEST_F(ParserImplTest, AssignmentStmt_Parses_ToVariable) {
auto* ident = a->lhs->As<ast::IdentifierExpression>();
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
ASSERT_TRUE(a->rhs->Is<ast::SintLiteralExpression>());
EXPECT_EQ(a->rhs->As<ast::SintLiteralExpression>()->value, 123);
ASSERT_TRUE(a->rhs->Is<ast::IntLiteralExpression>());
EXPECT_EQ(a->rhs->As<ast::IntLiteralExpression>()->value, 123);
EXPECT_EQ(a->rhs->As<ast::IntLiteralExpression>()->suffix,
ast::IntLiteralExpression::Suffix::kNone);
}
TEST_F(ParserImplTest, AssignmentStmt_Parses_ToMember) {
@ -51,8 +53,10 @@ TEST_F(ParserImplTest, AssignmentStmt_Parses_ToMember) {
ASSERT_NE(a->lhs, nullptr);
ASSERT_NE(a->rhs, nullptr);
ASSERT_TRUE(a->rhs->Is<ast::SintLiteralExpression>());
EXPECT_EQ(a->rhs->As<ast::SintLiteralExpression>()->value, 123);
ASSERT_TRUE(a->rhs->Is<ast::IntLiteralExpression>());
EXPECT_EQ(a->rhs->As<ast::IntLiteralExpression>()->value, 123);
EXPECT_EQ(a->rhs->As<ast::IntLiteralExpression>()->suffix,
ast::IntLiteralExpression::Suffix::kNone);
ASSERT_TRUE(a->lhs->Is<ast::MemberAccessorExpression>());
auto* mem = a->lhs->As<ast::MemberAccessorExpression>();
@ -65,8 +69,8 @@ TEST_F(ParserImplTest, AssignmentStmt_Parses_ToMember) {
auto* idx = mem->structure->As<ast::IndexAccessorExpression>();
ASSERT_NE(idx->index, nullptr);
ASSERT_TRUE(idx->index->Is<ast::SintLiteralExpression>());
EXPECT_EQ(idx->index->As<ast::SintLiteralExpression>()->value, 2);
ASSERT_TRUE(idx->index->Is<ast::IntLiteralExpression>());
EXPECT_EQ(idx->index->As<ast::IntLiteralExpression>()->value, 2);
ASSERT_TRUE(idx->object->Is<ast::MemberAccessorExpression>());
mem = idx->object->As<ast::MemberAccessorExpression>();
@ -87,7 +91,7 @@ TEST_F(ParserImplTest, AssignmentStmt_Parses_ToMember) {
}
TEST_F(ParserImplTest, AssignmentStmt_Parses_ToPhony) {
auto p = parser("_ = 123");
auto p = parser("_ = 123i");
auto e = p->assignment_stmt();
EXPECT_TRUE(e.matched);
EXPECT_FALSE(e.errored);
@ -99,14 +103,16 @@ TEST_F(ParserImplTest, AssignmentStmt_Parses_ToPhony) {
ASSERT_NE(a->lhs, nullptr);
ASSERT_NE(a->rhs, nullptr);
ASSERT_TRUE(a->rhs->Is<ast::SintLiteralExpression>());
EXPECT_EQ(a->rhs->As<ast::SintLiteralExpression>()->value, 123);
ASSERT_TRUE(a->rhs->Is<ast::IntLiteralExpression>());
EXPECT_EQ(a->rhs->As<ast::IntLiteralExpression>()->value, 123);
EXPECT_EQ(a->rhs->As<ast::IntLiteralExpression>()->suffix,
ast::IntLiteralExpression::Suffix::kI);
ASSERT_TRUE(a->lhs->Is<ast::PhonyExpression>());
}
TEST_F(ParserImplTest, AssignmentStmt_Parses_CompoundOp) {
auto p = parser("a += 123");
auto p = parser("a += 123u");
auto e = p->assignment_stmt();
EXPECT_TRUE(e.matched);
EXPECT_FALSE(e.errored);
@ -123,8 +129,10 @@ TEST_F(ParserImplTest, AssignmentStmt_Parses_CompoundOp) {
auto* ident = a->lhs->As<ast::IdentifierExpression>();
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
ASSERT_TRUE(a->rhs->Is<ast::SintLiteralExpression>());
EXPECT_EQ(a->rhs->As<ast::SintLiteralExpression>()->value, 123);
ASSERT_TRUE(a->rhs->Is<ast::IntLiteralExpression>());
EXPECT_EQ(a->rhs->As<ast::IntLiteralExpression>()->value, 123);
EXPECT_EQ(a->rhs->As<ast::IntLiteralExpression>()->suffix,
ast::IntLiteralExpression::Suffix::kU);
}
TEST_F(ParserImplTest, AssignmentStmt_MissingEqual) {

View File

@ -49,8 +49,10 @@ TEST_F(ParserImplTest, ConstLiteral_Int) {
EXPECT_FALSE(c.errored);
EXPECT_FALSE(p->has_error()) << p->error();
ASSERT_NE(c.value, nullptr);
ASSERT_TRUE(c->Is<ast::SintLiteralExpression>());
EXPECT_EQ(c->As<ast::SintLiteralExpression>()->value, 234);
ASSERT_TRUE(c->Is<ast::IntLiteralExpression>());
EXPECT_EQ(c->As<ast::IntLiteralExpression>()->value, 234);
EXPECT_EQ(c->As<ast::IntLiteralExpression>()->suffix,
ast::IntLiteralExpression::Suffix::kNone);
EXPECT_EQ(c->source.range, (Source::Range{{1u, 1u}, {1u, 4u}}));
}
{
@ -60,8 +62,10 @@ TEST_F(ParserImplTest, ConstLiteral_Int) {
EXPECT_FALSE(c.errored);
EXPECT_FALSE(p->has_error()) << p->error();
ASSERT_NE(c.value, nullptr);
ASSERT_TRUE(c->Is<ast::SintLiteralExpression>());
EXPECT_EQ(c->As<ast::SintLiteralExpression>()->value, 234);
ASSERT_TRUE(c->Is<ast::IntLiteralExpression>());
EXPECT_EQ(c->As<ast::IntLiteralExpression>()->value, 234);
EXPECT_EQ(c->As<ast::IntLiteralExpression>()->suffix,
ast::IntLiteralExpression::Suffix::kI);
EXPECT_EQ(c->source.range, (Source::Range{{1u, 1u}, {1u, 5u}}));
}
{
@ -71,8 +75,10 @@ TEST_F(ParserImplTest, ConstLiteral_Int) {
EXPECT_FALSE(c.errored);
EXPECT_FALSE(p->has_error()) << p->error();
ASSERT_NE(c.value, nullptr);
ASSERT_TRUE(c->Is<ast::SintLiteralExpression>());
EXPECT_EQ(c->As<ast::SintLiteralExpression>()->value, -234);
ASSERT_TRUE(c->Is<ast::IntLiteralExpression>());
EXPECT_EQ(c->As<ast::IntLiteralExpression>()->value, -234);
EXPECT_EQ(c->As<ast::IntLiteralExpression>()->suffix,
ast::IntLiteralExpression::Suffix::kNone);
EXPECT_EQ(c->source.range, (Source::Range{{1u, 1u}, {1u, 5u}}));
}
{
@ -82,8 +88,10 @@ TEST_F(ParserImplTest, ConstLiteral_Int) {
EXPECT_FALSE(c.errored);
EXPECT_FALSE(p->has_error()) << p->error();
ASSERT_NE(c.value, nullptr);
ASSERT_TRUE(c->Is<ast::SintLiteralExpression>());
EXPECT_EQ(c->As<ast::SintLiteralExpression>()->value, -234);
ASSERT_TRUE(c->Is<ast::IntLiteralExpression>());
EXPECT_EQ(c->As<ast::IntLiteralExpression>()->value, -234);
EXPECT_EQ(c->As<ast::IntLiteralExpression>()->suffix,
ast::IntLiteralExpression::Suffix::kI);
EXPECT_EQ(c->source.range, (Source::Range{{1u, 1u}, {1u, 6u}}));
}
}
@ -95,8 +103,9 @@ TEST_F(ParserImplTest, ConstLiteral_Uint) {
EXPECT_FALSE(c.errored);
EXPECT_FALSE(p->has_error()) << p->error();
ASSERT_NE(c.value, nullptr);
ASSERT_TRUE(c->Is<ast::UintLiteralExpression>());
EXPECT_EQ(c->As<ast::UintLiteralExpression>()->value, 234u);
ASSERT_TRUE(c->Is<ast::IntLiteralExpression>());
EXPECT_EQ(c->As<ast::IntLiteralExpression>()->value, 234);
EXPECT_EQ(c->As<ast::IntLiteralExpression>()->suffix, ast::IntLiteralExpression::Suffix::kU);
EXPECT_EQ(c->source.range, (Source::Range{{1u, 1u}, {1u, 5u}}));
}

View File

@ -37,8 +37,9 @@ TEST_F(ParserImplTest, AttributeList_Parses) {
auto* x_literal = x->As<ast::LiteralExpression>();
ASSERT_NE(x_literal, nullptr);
ASSERT_TRUE(x_literal->Is<ast::IntLiteralExpression>());
EXPECT_EQ(x_literal->As<ast::IntLiteralExpression>()->ValueAsU32(), 2u);
EXPECT_EQ(x_literal->As<ast::IntLiteralExpression>()->value, 2);
EXPECT_EQ(x_literal->As<ast::IntLiteralExpression>()->suffix,
ast::IntLiteralExpression::Suffix::kNone);
ASSERT_TRUE(attr_1->Is<ast::StageAttribute>());
EXPECT_EQ(attr_1->As<ast::StageAttribute>()->stage, ast::PipelineStage::kCompute);
}

View File

@ -33,7 +33,9 @@ TEST_F(ParserImplTest, Attribute_Workgroup) {
auto values = func_attr->As<ast::WorkgroupAttribute>()->Values();
ASSERT_TRUE(values[0]->Is<ast::IntLiteralExpression>());
EXPECT_EQ(values[0]->As<ast::IntLiteralExpression>()->ValueAsU32(), 4u);
EXPECT_EQ(values[0]->As<ast::IntLiteralExpression>()->value, 4);
EXPECT_EQ(values[0]->As<ast::IntLiteralExpression>()->suffix,
ast::IntLiteralExpression::Suffix::kNone);
EXPECT_EQ(values[1], nullptr);
EXPECT_EQ(values[2], nullptr);
@ -53,10 +55,14 @@ TEST_F(ParserImplTest, Attribute_Workgroup_2Param) {
auto values = func_attr->As<ast::WorkgroupAttribute>()->Values();
ASSERT_TRUE(values[0]->Is<ast::IntLiteralExpression>());
EXPECT_EQ(values[0]->As<ast::IntLiteralExpression>()->ValueAsU32(), 4u);
EXPECT_EQ(values[0]->As<ast::IntLiteralExpression>()->value, 4);
EXPECT_EQ(values[0]->As<ast::IntLiteralExpression>()->suffix,
ast::IntLiteralExpression::Suffix::kNone);
ASSERT_TRUE(values[1]->Is<ast::IntLiteralExpression>());
EXPECT_EQ(values[1]->As<ast::IntLiteralExpression>()->ValueAsU32(), 5u);
EXPECT_EQ(values[1]->As<ast::IntLiteralExpression>()->value, 5);
EXPECT_EQ(values[1]->As<ast::IntLiteralExpression>()->suffix,
ast::IntLiteralExpression::Suffix::kNone);
EXPECT_EQ(values[2], nullptr);
}
@ -75,13 +81,19 @@ TEST_F(ParserImplTest, Attribute_Workgroup_3Param) {
auto values = func_attr->As<ast::WorkgroupAttribute>()->Values();
ASSERT_TRUE(values[0]->Is<ast::IntLiteralExpression>());
EXPECT_EQ(values[0]->As<ast::IntLiteralExpression>()->ValueAsU32(), 4u);
EXPECT_EQ(values[0]->As<ast::IntLiteralExpression>()->value, 4);
EXPECT_EQ(values[0]->As<ast::IntLiteralExpression>()->suffix,
ast::IntLiteralExpression::Suffix::kNone);
ASSERT_TRUE(values[1]->Is<ast::IntLiteralExpression>());
EXPECT_EQ(values[1]->As<ast::IntLiteralExpression>()->ValueAsU32(), 5u);
EXPECT_EQ(values[1]->As<ast::IntLiteralExpression>()->value, 5);
EXPECT_EQ(values[1]->As<ast::IntLiteralExpression>()->suffix,
ast::IntLiteralExpression::Suffix::kNone);
ASSERT_TRUE(values[2]->Is<ast::IntLiteralExpression>());
EXPECT_EQ(values[2]->As<ast::IntLiteralExpression>()->ValueAsU32(), 6u);
EXPECT_EQ(values[2]->As<ast::IntLiteralExpression>()->value, 6);
EXPECT_EQ(values[2]->As<ast::IntLiteralExpression>()->suffix,
ast::IntLiteralExpression::Suffix::kNone);
}
TEST_F(ParserImplTest, Attribute_Workgroup_WithIdent) {
@ -98,7 +110,9 @@ TEST_F(ParserImplTest, Attribute_Workgroup_WithIdent) {
auto values = func_attr->As<ast::WorkgroupAttribute>()->Values();
ASSERT_TRUE(values[0]->Is<ast::IntLiteralExpression>());
EXPECT_EQ(values[0]->As<ast::IntLiteralExpression>()->ValueAsU32(), 4u);
EXPECT_EQ(values[0]->As<ast::IntLiteralExpression>()->value, 4);
EXPECT_EQ(values[0]->As<ast::IntLiteralExpression>()->suffix,
ast::IntLiteralExpression::Suffix::kNone);
ASSERT_NE(values[1], nullptr);
auto* y_ident = values[1]->As<ast::IdentifierExpression>();

View File

@ -116,13 +116,19 @@ TEST_F(ParserImplTest, FunctionDecl_AttributeList) {
auto values = attributes[0]->As<ast::WorkgroupAttribute>()->Values();
ASSERT_TRUE(values[0]->Is<ast::IntLiteralExpression>());
EXPECT_EQ(values[0]->As<ast::IntLiteralExpression>()->ValueAsU32(), 2u);
EXPECT_EQ(values[0]->As<ast::IntLiteralExpression>()->value, 2);
EXPECT_EQ(values[0]->As<ast::IntLiteralExpression>()->suffix,
ast::IntLiteralExpression::Suffix::kNone);
ASSERT_TRUE(values[1]->Is<ast::IntLiteralExpression>());
EXPECT_EQ(values[1]->As<ast::IntLiteralExpression>()->ValueAsU32(), 3u);
EXPECT_EQ(values[1]->As<ast::IntLiteralExpression>()->value, 3);
EXPECT_EQ(values[1]->As<ast::IntLiteralExpression>()->suffix,
ast::IntLiteralExpression::Suffix::kNone);
ASSERT_TRUE(values[2]->Is<ast::IntLiteralExpression>());
EXPECT_EQ(values[2]->As<ast::IntLiteralExpression>()->ValueAsU32(), 4u);
EXPECT_EQ(values[2]->As<ast::IntLiteralExpression>()->value, 4);
EXPECT_EQ(values[2]->As<ast::IntLiteralExpression>()->suffix,
ast::IntLiteralExpression::Suffix::kNone);
auto* body = f->body;
ASSERT_EQ(body->statements.size(), 1u);
@ -155,13 +161,19 @@ fn main() { return; })");
auto values = attributes[0]->As<ast::WorkgroupAttribute>()->Values();
ASSERT_TRUE(values[0]->Is<ast::IntLiteralExpression>());
EXPECT_EQ(values[0]->As<ast::IntLiteralExpression>()->ValueAsU32(), 2u);
EXPECT_EQ(values[0]->As<ast::IntLiteralExpression>()->value, 2);
EXPECT_EQ(values[0]->As<ast::IntLiteralExpression>()->suffix,
ast::IntLiteralExpression::Suffix::kNone);
ASSERT_TRUE(values[1]->Is<ast::IntLiteralExpression>());
EXPECT_EQ(values[1]->As<ast::IntLiteralExpression>()->ValueAsU32(), 3u);
EXPECT_EQ(values[1]->As<ast::IntLiteralExpression>()->value, 3);
EXPECT_EQ(values[1]->As<ast::IntLiteralExpression>()->suffix,
ast::IntLiteralExpression::Suffix::kNone);
ASSERT_TRUE(values[2]->Is<ast::IntLiteralExpression>());
EXPECT_EQ(values[2]->As<ast::IntLiteralExpression>()->ValueAsU32(), 4u);
EXPECT_EQ(values[2]->As<ast::IntLiteralExpression>()->value, 4);
EXPECT_EQ(values[2]->As<ast::IntLiteralExpression>()->suffix,
ast::IntLiteralExpression::Suffix::kNone);
ASSERT_TRUE(attributes[1]->Is<ast::StageAttribute>());
EXPECT_EQ(attributes[1]->As<ast::StageAttribute>()->stage, ast::PipelineStage::kCompute);
@ -198,13 +210,19 @@ fn main() { return; })");
auto values = attrs[0]->As<ast::WorkgroupAttribute>()->Values();
ASSERT_TRUE(values[0]->Is<ast::IntLiteralExpression>());
EXPECT_EQ(values[0]->As<ast::IntLiteralExpression>()->ValueAsU32(), 2u);
EXPECT_EQ(values[0]->As<ast::IntLiteralExpression>()->value, 2);
EXPECT_EQ(values[0]->As<ast::IntLiteralExpression>()->suffix,
ast::IntLiteralExpression::Suffix::kNone);
ASSERT_TRUE(values[1]->Is<ast::IntLiteralExpression>());
EXPECT_EQ(values[1]->As<ast::IntLiteralExpression>()->ValueAsU32(), 3u);
EXPECT_EQ(values[1]->As<ast::IntLiteralExpression>()->value, 3);
EXPECT_EQ(values[1]->As<ast::IntLiteralExpression>()->suffix,
ast::IntLiteralExpression::Suffix::kNone);
ASSERT_TRUE(values[2]->Is<ast::IntLiteralExpression>());
EXPECT_EQ(values[2]->As<ast::IntLiteralExpression>()->ValueAsU32(), 4u);
EXPECT_EQ(values[2]->As<ast::IntLiteralExpression>()->value, 4);
EXPECT_EQ(values[2]->As<ast::IntLiteralExpression>()->suffix,
ast::IntLiteralExpression::Suffix::kNone);
ASSERT_TRUE(attrs[1]->Is<ast::StageAttribute>());
EXPECT_EQ(attrs[1]->As<ast::StageAttribute>()->stage, ast::PipelineStage::kCompute);

View File

@ -98,8 +98,8 @@ TEST_F(ParserImplTest, IncrementDecrementStmt_ToMember) {
auto* idx = mem->structure->As<ast::IndexAccessorExpression>();
ASSERT_NE(idx->index, nullptr);
ASSERT_TRUE(idx->index->Is<ast::SintLiteralExpression>());
EXPECT_EQ(idx->index->As<ast::SintLiteralExpression>()->value, 2);
ASSERT_TRUE(idx->index->Is<ast::IntLiteralExpression>());
EXPECT_EQ(idx->index->As<ast::IntLiteralExpression>()->value, 2);
ASSERT_TRUE(idx->object->Is<ast::MemberAccessorExpression>());
mem = idx->object->As<ast::MemberAccessorExpression>();

View File

@ -44,17 +44,25 @@ TEST_F(ParserImplTest, PrimaryExpression_TypeDecl) {
ASSERT_EQ(call->args.size(), 4u);
const auto& val = call->args;
ASSERT_TRUE(val[0]->Is<ast::SintLiteralExpression>());
EXPECT_EQ(val[0]->As<ast::SintLiteralExpression>()->value, 1);
ASSERT_TRUE(val[0]->Is<ast::IntLiteralExpression>());
EXPECT_EQ(val[0]->As<ast::IntLiteralExpression>()->value, 1);
EXPECT_EQ(val[0]->As<ast::IntLiteralExpression>()->suffix,
ast::IntLiteralExpression::Suffix::kNone);
ASSERT_TRUE(val[1]->Is<ast::SintLiteralExpression>());
EXPECT_EQ(val[1]->As<ast::SintLiteralExpression>()->value, 2);
ASSERT_TRUE(val[1]->Is<ast::IntLiteralExpression>());
EXPECT_EQ(val[1]->As<ast::IntLiteralExpression>()->value, 2);
EXPECT_EQ(val[1]->As<ast::IntLiteralExpression>()->suffix,
ast::IntLiteralExpression::Suffix::kNone);
ASSERT_TRUE(val[2]->Is<ast::SintLiteralExpression>());
EXPECT_EQ(val[2]->As<ast::SintLiteralExpression>()->value, 3);
ASSERT_TRUE(val[2]->Is<ast::IntLiteralExpression>());
EXPECT_EQ(val[2]->As<ast::IntLiteralExpression>()->value, 3);
EXPECT_EQ(val[2]->As<ast::IntLiteralExpression>()->suffix,
ast::IntLiteralExpression::Suffix::kNone);
ASSERT_TRUE(val[3]->Is<ast::SintLiteralExpression>());
EXPECT_EQ(val[3]->As<ast::SintLiteralExpression>()->value, 4);
ASSERT_TRUE(val[3]->Is<ast::IntLiteralExpression>());
EXPECT_EQ(val[3]->As<ast::IntLiteralExpression>()->value, 4);
EXPECT_EQ(val[3]->As<ast::IntLiteralExpression>()->suffix,
ast::IntLiteralExpression::Suffix::kNone);
}
TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_ZeroConstructor) {
@ -158,8 +166,10 @@ TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_StructConstructor_NotEmpty) {
ASSERT_EQ(call->args.size(), 2u);
ASSERT_TRUE(call->args[0]->Is<ast::UintLiteralExpression>());
EXPECT_EQ(call->args[0]->As<ast::UintLiteralExpression>()->value, 1u);
ASSERT_TRUE(call->args[0]->Is<ast::IntLiteralExpression>());
EXPECT_EQ(call->args[0]->As<ast::IntLiteralExpression>()->value, 1u);
EXPECT_EQ(call->args[0]->As<ast::IntLiteralExpression>()->suffix,
ast::IntLiteralExpression::Suffix::kU);
ASSERT_TRUE(call->args[1]->Is<ast::FloatLiteralExpression>());
EXPECT_EQ(call->args[1]->As<ast::FloatLiteralExpression>()->value, 2.f);

View File

@ -32,8 +32,10 @@ TEST_F(ParserImplTest, SingularExpression_Array_ConstantIndex) {
auto* ident = idx->object->As<ast::IdentifierExpression>();
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
ASSERT_TRUE(idx->index->Is<ast::SintLiteralExpression>());
EXPECT_EQ(idx->index->As<ast::SintLiteralExpression>()->value, 1);
ASSERT_TRUE(idx->index->Is<ast::IntLiteralExpression>());
EXPECT_EQ(idx->index->As<ast::IntLiteralExpression>()->value, 1);
EXPECT_EQ(idx->index->As<ast::IntLiteralExpression>()->suffix,
ast::IntLiteralExpression::Suffix::kNone);
}
TEST_F(ParserImplTest, SingularExpression_Array_ExpressionIndex) {

View File

@ -28,7 +28,8 @@ TEST_F(ParserImplTest, SwitchBody_Case) {
EXPECT_FALSE(e->IsDefault());
auto* stmt = e->As<ast::CaseStatement>();
ASSERT_EQ(stmt->selectors.size(), 1u);
EXPECT_EQ(stmt->selectors[0]->ValueAsU32(), 1u);
EXPECT_EQ(stmt->selectors[0]->value, 1);
EXPECT_EQ(stmt->selectors[0]->suffix, ast::IntLiteralExpression::Suffix::kNone);
ASSERT_EQ(e->body->statements.size(), 1u);
EXPECT_TRUE(e->body->statements[0]->Is<ast::AssignmentStatement>());
}
@ -44,7 +45,8 @@ TEST_F(ParserImplTest, SwitchBody_Case_WithColon) {
EXPECT_FALSE(e->IsDefault());
auto* stmt = e->As<ast::CaseStatement>();
ASSERT_EQ(stmt->selectors.size(), 1u);
EXPECT_EQ(stmt->selectors[0]->ValueAsU32(), 1u);
EXPECT_EQ(stmt->selectors[0]->value, 1);
EXPECT_EQ(stmt->selectors[0]->suffix, ast::IntLiteralExpression::Suffix::kNone);
ASSERT_EQ(e->body->statements.size(), 1u);
EXPECT_TRUE(e->body->statements[0]->Is<ast::AssignmentStatement>());
}
@ -60,8 +62,9 @@ TEST_F(ParserImplTest, SwitchBody_Case_TrailingComma) {
EXPECT_FALSE(e->IsDefault());
auto* stmt = e->As<ast::CaseStatement>();
ASSERT_EQ(stmt->selectors.size(), 2u);
EXPECT_EQ(stmt->selectors[0]->ValueAsU32(), 1u);
EXPECT_EQ(stmt->selectors[1]->ValueAsU32(), 2u);
EXPECT_EQ(stmt->selectors[0]->value, 1);
EXPECT_EQ(stmt->selectors[0]->suffix, ast::IntLiteralExpression::Suffix::kNone);
EXPECT_EQ(stmt->selectors[1]->value, 2);
}
TEST_F(ParserImplTest, SwitchBody_Case_TrailingComma_WithColon) {
@ -75,8 +78,9 @@ TEST_F(ParserImplTest, SwitchBody_Case_TrailingComma_WithColon) {
EXPECT_FALSE(e->IsDefault());
auto* stmt = e->As<ast::CaseStatement>();
ASSERT_EQ(stmt->selectors.size(), 2u);
EXPECT_EQ(stmt->selectors[0]->ValueAsU32(), 1u);
EXPECT_EQ(stmt->selectors[1]->ValueAsU32(), 2u);
EXPECT_EQ(stmt->selectors[0]->value, 1);
EXPECT_EQ(stmt->selectors[0]->suffix, ast::IntLiteralExpression::Suffix::kNone);
EXPECT_EQ(stmt->selectors[1]->value, 2);
}
TEST_F(ParserImplTest, SwitchBody_Case_InvalidConstLiteral) {
@ -160,8 +164,10 @@ TEST_F(ParserImplTest, SwitchBody_Case_MultipleSelectors) {
EXPECT_FALSE(e->IsDefault());
ASSERT_EQ(e->body->statements.size(), 0u);
ASSERT_EQ(e->selectors.size(), 2u);
ASSERT_EQ(e->selectors[0]->ValueAsI32(), 1);
ASSERT_EQ(e->selectors[1]->ValueAsI32(), 2);
ASSERT_EQ(e->selectors[0]->value, 1);
EXPECT_EQ(e->selectors[0]->suffix, ast::IntLiteralExpression::Suffix::kNone);
ASSERT_EQ(e->selectors[1]->value, 2);
EXPECT_EQ(e->selectors[1]->suffix, ast::IntLiteralExpression::Suffix::kNone);
}
TEST_F(ParserImplTest, SwitchBody_Case_MultipleSelectors_WithColon) {
@ -175,8 +181,10 @@ TEST_F(ParserImplTest, SwitchBody_Case_MultipleSelectors_WithColon) {
EXPECT_FALSE(e->IsDefault());
ASSERT_EQ(e->body->statements.size(), 0u);
ASSERT_EQ(e->selectors.size(), 2u);
ASSERT_EQ(e->selectors[0]->ValueAsI32(), 1);
ASSERT_EQ(e->selectors[1]->ValueAsI32(), 2);
ASSERT_EQ(e->selectors[0]->value, 1);
EXPECT_EQ(e->selectors[0]->suffix, ast::IntLiteralExpression::Suffix::kNone);
ASSERT_EQ(e->selectors[1]->value, 2);
EXPECT_EQ(e->selectors[1]->suffix, ast::IntLiteralExpression::Suffix::kNone);
}
TEST_F(ParserImplTest, SwitchBody_Case_MultipleSelectorsMissingComma) {

View File

@ -376,7 +376,7 @@ TEST_F(ParserImplTest, TypeDecl_Atomic_MissingType) {
ASSERT_EQ(p->error(), "1:8: invalid type for atomic declaration");
}
TEST_F(ParserImplTest, TypeDecl_Array_SintLiteralSize) {
TEST_F(ParserImplTest, TypeDecl_Array_AbstractIntLiteralSize) {
auto p = parser("array<f32, 5>");
auto t = p->type_decl();
EXPECT_TRUE(t.matched);
@ -391,9 +391,31 @@ TEST_F(ParserImplTest, TypeDecl_Array_SintLiteralSize) {
EXPECT_EQ(a->attributes.size(), 0u);
EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 14u}}));
auto* size = a->count->As<ast::SintLiteralExpression>();
auto* size = a->count->As<ast::IntLiteralExpression>();
ASSERT_NE(size, nullptr);
EXPECT_EQ(size->ValueAsI32(), 5);
EXPECT_EQ(size->value, 5);
EXPECT_EQ(size->suffix, ast::IntLiteralExpression::Suffix::kNone);
}
TEST_F(ParserImplTest, TypeDecl_Array_SintLiteralSize) {
auto p = parser("array<f32, 5i>");
auto t = p->type_decl();
EXPECT_TRUE(t.matched);
EXPECT_FALSE(t.errored);
ASSERT_NE(t.value, nullptr) << p->error();
ASSERT_FALSE(p->has_error());
ASSERT_TRUE(t.value->Is<ast::Array>());
auto* a = t.value->As<ast::Array>();
ASSERT_FALSE(a->IsRuntimeArray());
ASSERT_TRUE(a->type->Is<ast::F32>());
EXPECT_EQ(a->attributes.size(), 0u);
EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 15u}}));
auto* size = a->count->As<ast::IntLiteralExpression>();
ASSERT_NE(size, nullptr);
EXPECT_EQ(size->value, 5);
EXPECT_EQ(size->suffix, ast::IntLiteralExpression::Suffix::kI);
}
TEST_F(ParserImplTest, TypeDecl_Array_UintLiteralSize) {
@ -411,9 +433,9 @@ TEST_F(ParserImplTest, TypeDecl_Array_UintLiteralSize) {
EXPECT_EQ(a->attributes.size(), 0u);
EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 15u}}));
auto* size = a->count->As<ast::UintLiteralExpression>();
auto* size = a->count->As<ast::IntLiteralExpression>();
ASSERT_NE(size, nullptr);
EXPECT_EQ(size->ValueAsU32(), 5u);
EXPECT_EQ(size->suffix, ast::IntLiteralExpression::Suffix::kU);
}
TEST_F(ParserImplTest, TypeDecl_Array_ConstantSize) {

View File

@ -32,8 +32,10 @@ TEST_F(ParserImplTest, UnaryExpression_Postix) {
auto* ident = idx->object->As<ast::IdentifierExpression>();
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
ASSERT_TRUE(idx->index->Is<ast::SintLiteralExpression>());
ASSERT_EQ(idx->index->As<ast::SintLiteralExpression>()->value, 2);
ASSERT_TRUE(idx->index->Is<ast::IntLiteralExpression>());
ASSERT_EQ(idx->index->As<ast::IntLiteralExpression>()->value, 2);
ASSERT_EQ(idx->index->As<ast::IntLiteralExpression>()->suffix,
ast::IntLiteralExpression::Suffix::kNone);
}
TEST_F(ParserImplTest, UnaryExpression_Minus) {
@ -48,8 +50,10 @@ TEST_F(ParserImplTest, UnaryExpression_Minus) {
auto* u = e->As<ast::UnaryOpExpression>();
ASSERT_EQ(u->op, ast::UnaryOp::kNegation);
ASSERT_TRUE(u->expr->Is<ast::SintLiteralExpression>());
EXPECT_EQ(u->expr->As<ast::SintLiteralExpression>()->value, 1);
ASSERT_TRUE(u->expr->Is<ast::IntLiteralExpression>());
EXPECT_EQ(u->expr->As<ast::IntLiteralExpression>()->value, 1);
ASSERT_EQ(u->expr->As<ast::IntLiteralExpression>()->suffix,
ast::IntLiteralExpression::Suffix::kNone);
}
TEST_F(ParserImplTest, UnaryExpression_AddressOf) {
@ -130,8 +134,10 @@ TEST_F(ParserImplTest, UnaryExpression_Bang) {
auto* u = e->As<ast::UnaryOpExpression>();
ASSERT_EQ(u->op, ast::UnaryOp::kNot);
ASSERT_TRUE(u->expr->Is<ast::SintLiteralExpression>());
EXPECT_EQ(u->expr->As<ast::SintLiteralExpression>()->value, 1);
ASSERT_TRUE(u->expr->Is<ast::IntLiteralExpression>());
EXPECT_EQ(u->expr->As<ast::IntLiteralExpression>()->value, 1);
ASSERT_EQ(u->expr->As<ast::IntLiteralExpression>()->suffix,
ast::IntLiteralExpression::Suffix::kNone);
}
TEST_F(ParserImplTest, UnaryExpression_Bang_InvalidRHS) {
@ -156,8 +162,10 @@ TEST_F(ParserImplTest, UnaryExpression_Tilde) {
auto* u = e->As<ast::UnaryOpExpression>();
ASSERT_EQ(u->op, ast::UnaryOp::kComplement);
ASSERT_TRUE(u->expr->Is<ast::SintLiteralExpression>());
EXPECT_EQ(u->expr->As<ast::SintLiteralExpression>()->value, 1);
ASSERT_TRUE(u->expr->Is<ast::IntLiteralExpression>());
EXPECT_EQ(u->expr->As<ast::IntLiteralExpression>()->value, 1);
ASSERT_EQ(u->expr->As<ast::IntLiteralExpression>()->suffix,
ast::IntLiteralExpression::Suffix::kNone);
}
TEST_F(ParserImplTest, UnaryExpression_PrefixPlusPlus) {

View File

@ -1147,9 +1147,9 @@ TEST_P(ResolverDependencyShadowTest, Test) {
helper.Add(inner_kind, symbol, Source{{56, 78}});
auto* inner_var = helper.nested_statements.size()
? helper.nested_statements[0]->As<ast::VariableDeclStatement>()->variable
: helper.statements.size()
? helper.statements[0]->As<ast::VariableDeclStatement>()->variable
: helper.parameters[0];
: helper.statements.size()
? helper.statements[0]->As<ast::VariableDeclStatement>()->variable
: helper.parameters[0];
helper.Build();
EXPECT_EQ(Build().shadows[inner_var], outer);

View File

@ -859,7 +859,9 @@ sem::CaseStatement* Resolver::CaseStatement(const ast::CaseStatement* stmt) {
builder_->create<sem::CaseStatement>(stmt, current_compound_statement_, current_function_);
return StatementScope(stmt, sem, [&] {
for (auto* sel : stmt->selectors) {
Mark(sel);
if (!Expression(sel)) {
return false;
}
}
Mark(stmt->body);
auto* body = BlockStatement(stmt->body);
@ -1525,8 +1527,27 @@ sem::Call* Resolver::TypeConstructor(const ast::CallExpression* expr,
}
sem::Expression* Resolver::Literal(const ast::LiteralExpression* literal) {
auto* ty = sem_.TypeOf(literal);
if (!ty) {
auto* ty = Switch(
literal,
[&](const ast::IntLiteralExpression* i) -> sem::Type* {
switch (i->suffix) {
case ast::IntLiteralExpression::Suffix::kNone:
// TODO(crbug.com/tint/1504): This will need to become abstract-int.
// For now, treat as 'i32'.
case ast::IntLiteralExpression::Suffix::kI:
return builder_->create<sem::I32>();
case ast::IntLiteralExpression::Suffix::kU:
return builder_->create<sem::U32>();
}
return nullptr;
},
[&](const ast::FloatLiteralExpression*) { return builder_->create<sem::F32>(); },
[&](const ast::BoolLiteralExpression*) { return builder_->create<sem::Bool>(); },
[&](Default) { return nullptr; });
if (ty == nullptr) {
TINT_UNREACHABLE(Resolver, builder_->Diagnostics())
<< "Unhandled literal type: " << literal->TypeInfo().name;
return nullptr;
}

View File

@ -39,20 +39,20 @@ sem::Constant Resolver::EvaluateConstantValue(const ast::Expression* expr, const
sem::Constant Resolver::EvaluateConstantValue(const ast::LiteralExpression* literal,
const sem::Type* type) {
if (auto* lit = literal->As<ast::SintLiteralExpression>()) {
return {type, {lit->ValueAsI32()}};
}
if (auto* lit = literal->As<ast::UintLiteralExpression>()) {
return {type, {lit->ValueAsU32()}};
}
if (auto* lit = literal->As<ast::FloatLiteralExpression>()) {
return {type, {lit->value}};
}
if (auto* lit = literal->As<ast::BoolLiteralExpression>()) {
return {type, {lit->value}};
}
TINT_UNREACHABLE(Resolver, builder_->Diagnostics());
return {};
return Switch(
literal,
[&](const ast::IntLiteralExpression* lit) {
if (lit->suffix == ast::IntLiteralExpression::Suffix::kU) {
return sem::Constant{type, {static_cast<uint32_t>(lit->value)}};
}
return sem::Constant{type, {static_cast<int32_t>(lit->value)}};
},
[&](const ast::FloatLiteralExpression* lit) {
return sem::Constant{type, {lit->value}};
},
[&](const ast::BoolLiteralExpression* lit) {
return sem::Constant{type, {lit->value}};
});
}
sem::Constant Resolver::EvaluateConstantValue(const ast::CallExpression* call,

View File

@ -113,7 +113,7 @@ TEST_F(ResolverTest, Stmt_Case) {
auto* assign = Assign(lhs, rhs);
auto* block = Block(assign);
ast::CaseSelectorList lit;
lit.push_back(create<ast::SintLiteralExpression>(3));
lit.push_back(Expr(3));
auto* cse = create<ast::CaseStatement>(lit, block);
auto* cond_var = Var("c", ty.i32());
auto* sw = Switch(cond_var, cse, DefaultCase());
@ -1922,8 +1922,8 @@ TEST_F(ResolverTest, ASTNodeNotReached) {
b.Expr("expr");
Resolver(&b).Resolve();
},
"internal compiler error: AST node 'tint::ast::IdentifierExpression' was "
"not reached by the resolver");
"internal compiler error: AST node 'tint::ast::IdentifierExpression' was not reached by "
"the resolver");
}
TEST_F(ResolverTest, ASTNodeReachedTwice) {
@ -1935,8 +1935,8 @@ TEST_F(ResolverTest, ASTNodeReachedTwice) {
b.Global("b", b.ty.i32(), ast::StorageClass::kPrivate, expr);
Resolver(&b).Resolve();
},
"internal compiler error: AST node 'tint::ast::SintLiteralExpression' "
"was encountered twice in the same AST of a Program");
"internal compiler error: AST node 'tint::ast::IntLiteralExpression' was encountered twice "
"in the same AST of a Program");
}
TEST_F(ResolverTest, UnaryOp_Not) {

View File

@ -36,17 +36,4 @@ sem::Type* SemHelper::TypeOf(const ast::Expression* expr) const {
return sem ? const_cast<sem::Type*>(sem->Type()) : nullptr;
}
sem::Type* SemHelper::TypeOf(const ast::LiteralExpression* lit) {
return Switch(
lit, [&](const ast::SintLiteralExpression*) { return builder_->create<sem::I32>(); },
[&](const ast::UintLiteralExpression*) { return builder_->create<sem::U32>(); },
[&](const ast::FloatLiteralExpression*) { return builder_->create<sem::F32>(); },
[&](const ast::BoolLiteralExpression*) { return builder_->create<sem::Bool>(); },
[&](Default) {
TINT_UNREACHABLE(Resolver, builder_->Diagnostics())
<< "Unhandled literal type: " << lit->TypeInfo().name;
return nullptr;
});
}
} // namespace tint::resolver

View File

@ -62,10 +62,6 @@ class SemHelper {
/// @param expr the expression
sem::Type* TypeOf(const ast::Expression* expr) const;
/// @returns the semantic type of the AST literal `lit`
/// @param lit the literal
sem::Type* TypeOf(const ast::LiteralExpression* lit);
/// @returns the type name of the given semantic type, unwrapping
/// references.
/// @param ty the type to look up

View File

@ -2178,7 +2178,7 @@ bool Validator::SwitchStatement(const ast::SwitchStatement* s) {
}
bool has_default = false;
std::unordered_map<uint32_t, Source> selectors;
std::unordered_map<int64_t, Source> selectors;
for (auto* case_stmt : s->body) {
if (case_stmt->IsDefault()) {
@ -2200,17 +2200,14 @@ bool Validator::SwitchStatement(const ast::SwitchStatement* s) {
return false;
}
auto v = selector->ValueAsU32();
auto it = selectors.find(v);
auto it = selectors.find(selector->value);
if (it != selectors.end()) {
auto val = selector->Is<ast::IntLiteralExpression>()
? std::to_string(selector->ValueAsI32())
: std::to_string(selector->ValueAsU32());
auto val = std::to_string(selector->value);
AddError("duplicate switch case '" + val + "'", selector->source);
AddNote("previous case declared here", it->second);
return false;
}
selectors.emplace(v, selector->source);
selectors.emplace(selector->value, selector->source);
}
}

View File

@ -320,11 +320,9 @@ struct DecomposeMemoryAccess::State {
/// @param expr the expression to convert to an Offset
/// @returns an Offset for the given ast::Expression
const Offset* ToOffset(const ast::Expression* expr) {
if (auto* u32 = expr->As<ast::UintLiteralExpression>()) {
return offsets_.Create<OffsetLiteral>(u32->value);
} else if (auto* i32 = expr->As<ast::SintLiteralExpression>()) {
if (i32->value > 0) {
return offsets_.Create<OffsetLiteral>(i32->value);
if (auto* lit = expr->As<ast::IntLiteralExpression>()) {
if (lit->value > 0) {
return offsets_.Create<OffsetLiteral>(static_cast<uint32_t>(lit->value));
}
}
return offsets_.Create<OffsetExpr>(expr);

View File

@ -73,7 +73,7 @@ TEST_F(CreateASTTypeForTest, ArrayImplicitStride) {
auto* size = arr->As<ast::Array>()->count->As<ast::IntLiteralExpression>();
ASSERT_NE(size, nullptr);
EXPECT_EQ(size->ValueAsI32(), 2);
EXPECT_EQ(size->value, 2);
}
TEST_F(CreateASTTypeForTest, ArrayNonImplicitStride) {
@ -88,7 +88,7 @@ TEST_F(CreateASTTypeForTest, ArrayNonImplicitStride) {
auto* size = arr->As<ast::Array>()->count->As<ast::IntLiteralExpression>();
ASSERT_NE(size, nullptr);
EXPECT_EQ(size->ValueAsI32(), 2);
EXPECT_EQ(size->value, 2);
}
TEST_F(CreateASTTypeForTest, Struct) {

View File

@ -453,7 +453,7 @@ TEST_F(AppendVectorTest, ZeroVec3i32_i32) {
ASSERT_NE(vec_0004, nullptr);
ASSERT_EQ(vec_0004->args.size(), 4u);
for (size_t i = 0; i < 3; i++) {
auto* literal = As<ast::SintLiteralExpression>(vec_0004->args[i]);
auto* literal = As<ast::IntLiteralExpression>(vec_0004->args[i]);
ASSERT_NE(literal, nullptr);
EXPECT_EQ(literal->value, 0);
}

View File

@ -2164,26 +2164,34 @@ bool GeneratorImpl::EmitEntryPointFunction(const ast::Function* func) {
}
bool GeneratorImpl::EmitLiteral(std::ostream& out, const ast::LiteralExpression* lit) {
if (auto* l = lit->As<ast::BoolLiteralExpression>()) {
out << (l->value ? "true" : "false");
} else if (auto* fl = lit->As<ast::FloatLiteralExpression>()) {
if (std::isinf(fl->value)) {
out << (fl->value >= 0 ? "uintBitsToFloat(0x7f800000u)"
: "uintBitsToFloat(0xff800000u)");
} else if (std::isnan(fl->value)) {
out << "uintBitsToFloat(0x7fc00000u)";
} else {
out << FloatToString(fl->value) << "f";
}
} else if (auto* sl = lit->As<ast::SintLiteralExpression>()) {
out << sl->value;
} else if (auto* ul = lit->As<ast::UintLiteralExpression>()) {
out << ul->value << "u";
} else {
diagnostics_.add_error(diag::System::Writer, "unknown literal type");
return false;
}
return true;
return Switch(
lit,
[&](const ast::BoolLiteralExpression* l) {
out << (l->value ? "true" : "false");
return true;
},
[&](const ast::FloatLiteralExpression* l) {
if (std::isinf(l->value)) {
out << (l->value >= 0 ? "uintBitsToFloat(0x7f800000u)"
: "uintBitsToFloat(0xff800000u)");
} else if (std::isnan(l->value)) {
out << "uintBitsToFloat(0x7fc00000u)";
} else {
out << FloatToString(l->value) << "f";
}
return true;
},
[&](const ast::IntLiteralExpression* l) {
out << l->value;
if (l->suffix == ast::IntLiteralExpression::Suffix::kU) {
out << "u";
}
return true;
},
[&](Default) {
diagnostics_.add_error(diag::System::Writer, "unknown literal type");
return false;
});
}
bool GeneratorImpl::EmitZeroValue(std::ostream& out, const sem::Type* type) {

View File

@ -3042,13 +3042,18 @@ bool GeneratorImpl::EmitLiteral(std::ostream& out, const ast::LiteralExpression*
}
return true;
},
[&](const ast::SintLiteralExpression* sl) {
out << sl->value;
return true;
},
[&](const ast::UintLiteralExpression* ul) {
out << ul->value << "u";
return true;
[&](const ast::IntLiteralExpression* i) {
out << i->value;
switch (i->suffix) {
case ast::IntLiteralExpression::Suffix::kNone:
case ast::IntLiteralExpression::Suffix::kI:
return true;
case ast::IntLiteralExpression::Suffix::kU:
out << "u";
return true;
}
diagnostics_.add_error(diag::System::Writer, "unknown integer literal suffix type");
return false;
},
[&](Default) {
diagnostics_.add_error(diag::System::Writer, "unknown literal type");

View File

@ -30,8 +30,6 @@
#include "src/tint/ast/id_attribute.h"
#include "src/tint/ast/interpolate_attribute.h"
#include "src/tint/ast/module.h"
#include "src/tint/ast/sint_literal_expression.h"
#include "src/tint/ast/uint_literal_expression.h"
#include "src/tint/ast/variable_decl_statement.h"
#include "src/tint/ast/void.h"
#include "src/tint/sem/array.h"
@ -1523,24 +1521,31 @@ bool GeneratorImpl::EmitLiteral(std::ostream& out, const ast::LiteralExpression*
}
return true;
},
[&](const ast::SintLiteralExpression* l) {
// MSL (and C++) parse `-2147483648` as a `long` because it parses
// unary minus and `2147483648` as separate tokens, and the latter
// doesn't fit into an (32-bit) `int`. WGSL, OTOH, parses this as an
// `i32`. To avoid issues with `long` to `int` casts, emit
// `(2147483647 - 1)` instead, which ensures the expression type is
// `int`.
const auto int_min = std::numeric_limits<int32_t>::min();
if (l->ValueAsI32() == int_min) {
out << "(" << int_min + 1 << " - 1)";
} else {
out << l->value;
[&](const ast::IntLiteralExpression* i) {
switch (i->suffix) {
case ast::IntLiteralExpression::Suffix::kNone:
case ast::IntLiteralExpression::Suffix::kI: {
// MSL (and C++) parse `-2147483648` as a `long` because it parses
// unary minus and `2147483648` as separate tokens, and the latter
// doesn't fit into an (32-bit) `int`. WGSL, OTOH, parses this as an
// `i32`. To avoid issues with `long` to `int` casts, emit
// `(2147483647 - 1)` instead, which ensures the expression type is
// `int`.
const auto int_min = std::numeric_limits<int32_t>::min();
if (i->value == int_min) {
out << "(" << int_min + 1 << " - 1)";
} else {
out << i->value;
}
return true;
}
case ast::IntLiteralExpression::Suffix::kU: {
out << i->value << "u";
return true;
}
}
return true;
},
[&](const ast::UintLiteralExpression* l) {
out << l->value << "u";
return true;
diagnostics_.add_error(diag::System::Writer, "unknown integer literal suffix type");
return false;
},
[&](Default) {
diagnostics_.add_error(diag::System::Writer, "unknown literal type");

View File

@ -743,22 +743,30 @@ bool Builder::GenerateGlobalVariable(const ast::Variable* var) {
}
// SPIR-V requires specialization constants to have initializers.
if (type->Is<sem::F32>()) {
ast::FloatLiteralExpression l(ProgramID(), Source{}, 0.0f);
init_id = GenerateLiteralIfNeeded(var, &l);
} else if (type->Is<sem::U32>()) {
ast::UintLiteralExpression l(ProgramID(), Source{}, 0);
init_id = GenerateLiteralIfNeeded(var, &l);
} else if (type->Is<sem::I32>()) {
ast::SintLiteralExpression l(ProgramID(), Source{}, 0);
init_id = GenerateLiteralIfNeeded(var, &l);
} else if (type->Is<sem::Bool>()) {
ast::BoolLiteralExpression l(ProgramID(), Source{}, false);
init_id = GenerateLiteralIfNeeded(var, &l);
} else {
error_ = "invalid type for pipeline constant ID, must be scalar";
return false;
}
init_id = Switch(
type, //
[&](const sem::F32*) {
ast::FloatLiteralExpression l(ProgramID{}, Source{}, 0.0f);
return GenerateLiteralIfNeeded(var, &l);
},
[&](const sem::U32*) {
ast::IntLiteralExpression l(ProgramID{}, Source{}, 0,
ast::IntLiteralExpression::Suffix::kU);
return GenerateLiteralIfNeeded(var, &l);
},
[&](const sem::I32*) {
ast::IntLiteralExpression l(ProgramID{}, Source{}, 0,
ast::IntLiteralExpression::Suffix::kI);
return GenerateLiteralIfNeeded(var, &l);
},
[&](const sem::Bool*) {
ast::BoolLiteralExpression l(ProgramID{}, Source{}, false);
return GenerateLiteralIfNeeded(var, &l);
},
[&](Default) {
error_ = "invalid type for pipeline constant ID, must be scalar";
return 0;
});
if (init_id == 0) {
return 0;
}
@ -1537,28 +1545,22 @@ uint32_t Builder::GenerateCastOrCopyOrPassthrough(const sem::Type* to_type,
uint32_t one_id;
uint32_t zero_id;
if (to_elem_type->Is<sem::F32>()) {
ast::FloatLiteralExpression one(ProgramID(), Source{}, 1.0f);
ast::FloatLiteralExpression zero(ProgramID(), Source{}, 0.0f);
one_id = GenerateLiteralIfNeeded(nullptr, &one);
zero_id = GenerateLiteralIfNeeded(nullptr, &zero);
zero_id = GenerateConstantIfNeeded(ScalarConstant::F32(0));
one_id = GenerateConstantIfNeeded(ScalarConstant::F32(1));
} else if (to_elem_type->Is<sem::U32>()) {
ast::UintLiteralExpression one(ProgramID(), Source{}, 1);
ast::UintLiteralExpression zero(ProgramID(), Source{}, 0);
one_id = GenerateLiteralIfNeeded(nullptr, &one);
zero_id = GenerateLiteralIfNeeded(nullptr, &zero);
zero_id = GenerateConstantIfNeeded(ScalarConstant::U32(0));
one_id = GenerateConstantIfNeeded(ScalarConstant::U32(1));
} else if (to_elem_type->Is<sem::I32>()) {
ast::SintLiteralExpression one(ProgramID(), Source{}, 1);
ast::SintLiteralExpression zero(ProgramID(), Source{}, 0);
one_id = GenerateLiteralIfNeeded(nullptr, &one);
zero_id = GenerateLiteralIfNeeded(nullptr, &zero);
zero_id = GenerateConstantIfNeeded(ScalarConstant::I32(0));
one_id = GenerateConstantIfNeeded(ScalarConstant::I32(1));
} else {
error_ = "invalid destination type for bool conversion";
return false;
}
if (auto* to_vec = to_type->As<sem::Vector>()) {
// Splat the scalars into vectors.
one_id = GenerateConstantVectorSplatIfNeeded(to_vec, one_id);
zero_id = GenerateConstantVectorSplatIfNeeded(to_vec, zero_id);
one_id = GenerateConstantVectorSplatIfNeeded(to_vec, one_id);
}
if (!one_id || !zero_id) {
return false;
@ -1605,17 +1607,22 @@ uint32_t Builder::GenerateLiteralIfNeeded(const ast::Variable* var,
constant.kind = ScalarConstant::Kind::kBool;
constant.value.b = l->value;
},
[&](const ast::SintLiteralExpression* sl) {
constant.kind = ScalarConstant::Kind::kI32;
constant.value.i32 = sl->value;
[&](const ast::IntLiteralExpression* i) {
switch (i->suffix) {
case ast::IntLiteralExpression::Suffix::kNone:
case ast::IntLiteralExpression::Suffix::kI:
constant.kind = ScalarConstant::Kind::kI32;
constant.value.i32 = static_cast<int32_t>(i->value);
return;
case ast::IntLiteralExpression::Suffix::kU:
constant.kind = ScalarConstant::Kind::kU32;
constant.value.u32 = static_cast<uint32_t>(i->value);
return;
}
},
[&](const ast::UintLiteralExpression* ul) {
constant.kind = ScalarConstant::Kind::kU32;
constant.value.u32 = ul->value;
},
[&](const ast::FloatLiteralExpression* fl) {
[&](const ast::FloatLiteralExpression* f) {
constant.kind = ScalarConstant::Kind::kF32;
constant.value.f32 = fl->value;
constant.value.f32 = f->value;
},
[&](Default) { error_ = "unknown literal type"; });
@ -2699,9 +2706,9 @@ bool Builder::GenerateTextureBuiltin(const sem::Call* call,
op = spv::Op::OpImageQuerySizeLod;
spirv_params.emplace_back(gen(level));
} else {
ast::SintLiteralExpression i32_0(ProgramID(), Source{}, 0);
op = spv::Op::OpImageQuerySizeLod;
spirv_params.emplace_back(Operand(GenerateLiteralIfNeeded(nullptr, &i32_0)));
spirv_params.emplace_back(
Operand(GenerateConstantIfNeeded(ScalarConstant::I32(0))));
}
break;
}
@ -2729,9 +2736,9 @@ bool Builder::GenerateTextureBuiltin(const sem::Call* call,
texture_type->Is<sem::StorageTexture>()) {
op = spv::Op::OpImageQuerySize;
} else {
ast::SintLiteralExpression i32_0(ProgramID(), Source{}, 0);
op = spv::Op::OpImageQuerySizeLod;
spirv_params.emplace_back(Operand(GenerateLiteralIfNeeded(nullptr, &i32_0)));
spirv_params.emplace_back(
Operand(GenerateConstantIfNeeded(ScalarConstant::I32(0))));
}
break;
}
@ -3401,7 +3408,7 @@ bool Builder::GenerateSwitchStatement(const ast::SwitchStatement* stmt) {
return false;
}
params.push_back(Operand(int_literal->ValueAsU32()));
params.push_back(Operand(static_cast<uint32_t>(int_literal->value)));
params.push_back(Operand(block_id));
}
}

View File

@ -70,7 +70,7 @@ TEST_F(BuilderTest, Literal_Bool_Dedup) {
}
TEST_F(BuilderTest, Literal_I32) {
auto* i = create<ast::SintLiteralExpression>(-23);
auto* i = Expr(-23);
WrapInFunction(i);
spirv::Builder& b = Build();
@ -84,8 +84,8 @@ TEST_F(BuilderTest, Literal_I32) {
}
TEST_F(BuilderTest, Literal_I32_Dedup) {
auto* i1 = create<ast::SintLiteralExpression>(-23);
auto* i2 = create<ast::SintLiteralExpression>(-23);
auto* i1 = Expr(-23);
auto* i2 = Expr(-23);
WrapInFunction(i1, i2);
spirv::Builder& b = Build();
@ -100,7 +100,7 @@ TEST_F(BuilderTest, Literal_I32_Dedup) {
}
TEST_F(BuilderTest, Literal_U32) {
auto* i = create<ast::UintLiteralExpression>(23);
auto* i = Expr(23u);
WrapInFunction(i);
spirv::Builder& b = Build();
@ -115,8 +115,8 @@ TEST_F(BuilderTest, Literal_U32) {
}
TEST_F(BuilderTest, Literal_U32_Dedup) {
auto* i1 = create<ast::UintLiteralExpression>(23);
auto* i2 = create<ast::UintLiteralExpression>(23);
auto* i1 = Expr(23u);
auto* i2 = Expr(23u);
WrapInFunction(i1, i2);
spirv::Builder& b = Build();

View File

@ -37,7 +37,6 @@
#include "src/tint/ast/multisampled_texture.h"
#include "src/tint/ast/pointer.h"
#include "src/tint/ast/sampled_texture.h"
#include "src/tint/ast/sint_literal_expression.h"
#include "src/tint/ast/stage_attribute.h"
#include "src/tint/ast/storage_texture.h"
#include "src/tint/ast/stride_attribute.h"
@ -46,7 +45,6 @@
#include "src/tint/ast/struct_member_size_attribute.h"
#include "src/tint/ast/type_name.h"
#include "src/tint/ast/u32.h"
#include "src/tint/ast/uint_literal_expression.h"
#include "src/tint/ast/variable_decl_statement.h"
#include "src/tint/ast/vector.h"
#include "src/tint/ast/void.h"
@ -259,20 +257,16 @@ bool GeneratorImpl::EmitCall(std::ostream& out, const ast::CallExpression* expr)
bool GeneratorImpl::EmitLiteral(std::ostream& out, const ast::LiteralExpression* lit) {
return Switch(
lit,
[&](const ast::BoolLiteralExpression* bl) { //
out << (bl->value ? "true" : "false");
[&](const ast::BoolLiteralExpression* l) { //
out << (l->value ? "true" : "false");
return true;
},
[&](const ast::FloatLiteralExpression* fl) { //
out << FloatToBitPreservingString(fl->value);
[&](const ast::FloatLiteralExpression* l) { //
out << FloatToBitPreservingString(l->value);
return true;
},
[&](const ast::SintLiteralExpression* sl) { //
out << sl->value;
return true;
},
[&](const ast::UintLiteralExpression* ul) { //
out << ul->value << "u";
[&](const ast::IntLiteralExpression* l) { //
out << l->value << l->suffix;
return true;
},
[&](Default) { //

View File

@ -192,7 +192,6 @@ tint_unittests_source_set("tint_unittests_ast_src") {
"../../src/tint/ast/return_statement_test.cc",
"../../src/tint/ast/sampled_texture_test.cc",
"../../src/tint/ast/sampler_test.cc",
"../../src/tint/ast/sint_literal_expression_test.cc",
"../../src/tint/ast/stage_attribute_test.cc",
"../../src/tint/ast/storage_texture_test.cc",
"../../src/tint/ast/stride_attribute_test.cc",
@ -206,7 +205,6 @@ tint_unittests_source_set("tint_unittests_ast_src") {
"../../src/tint/ast/texture_test.cc",
"../../src/tint/ast/traverse_expressions_test.cc",
"../../src/tint/ast/u32_test.cc",
"../../src/tint/ast/uint_literal_expression_test.cc",
"../../src/tint/ast/unary_op_expression_test.cc",
"../../src/tint/ast/variable_decl_statement_test.cc",
"../../src/tint/ast/variable_test.cc",