ast: Remove types from ast::Literals
A literal has an implicit type, so there should be no type on the AST node. This highlighted that the resolver was nto canonicalizing TypeConstructorExpression types, which has been fixed. This required preservation of the declared type name in order for error messages to contain aliased names. Bug: tint:724 Change-Id: I21594a3e8a0fb1b73c6c5b46a14b8664b7f28512 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/49345 Reviewed-by: Antonio Maiorano <amaiorano@google.com> Commit-Queue: Ben Clayton <bclayton@chromium.org>
This commit is contained in:
parent
0bf0fb9b29
commit
109b18f504
|
@ -21,11 +21,8 @@ TINT_INSTANTIATE_TYPEINFO(tint::ast::BoolLiteral);
|
|||
namespace tint {
|
||||
namespace ast {
|
||||
|
||||
BoolLiteral::BoolLiteral(ProgramID program_id,
|
||||
const Source& source,
|
||||
typ::Type type,
|
||||
bool value)
|
||||
: Base(program_id, source, type), value_(value) {}
|
||||
BoolLiteral::BoolLiteral(ProgramID program_id, const Source& source, bool value)
|
||||
: Base(program_id, source), value_(value) {}
|
||||
|
||||
BoolLiteral::~BoolLiteral() = default;
|
||||
|
||||
|
@ -40,8 +37,7 @@ std::string BoolLiteral::name() const {
|
|||
BoolLiteral* BoolLiteral::Clone(CloneContext* ctx) const {
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source());
|
||||
auto ty = ctx->Clone(type());
|
||||
return ctx->dst->create<BoolLiteral>(src, ty, value_);
|
||||
return ctx->dst->create<BoolLiteral>(src, value_);
|
||||
}
|
||||
|
||||
} // namespace ast
|
||||
|
|
|
@ -28,12 +28,8 @@ class BoolLiteral : public Castable<BoolLiteral, Literal> {
|
|||
/// Constructor
|
||||
/// @param program_id the identifier of the program that owns this node
|
||||
/// @param source the input source
|
||||
/// @param type the type of the literal
|
||||
/// @param value the bool literals value
|
||||
BoolLiteral(ProgramID program_id,
|
||||
const Source& source,
|
||||
typ::Type type,
|
||||
bool value);
|
||||
BoolLiteral(ProgramID program_id, const Source& source, bool value);
|
||||
~BoolLiteral() override;
|
||||
|
||||
/// @returns true if the bool literal is true
|
||||
|
|
|
@ -21,21 +21,21 @@ namespace {
|
|||
using BoolLiteralTest = TestHelper;
|
||||
|
||||
TEST_F(BoolLiteralTest, True) {
|
||||
auto* b = create<BoolLiteral>(ty.bool_(), true);
|
||||
auto* b = create<BoolLiteral>(true);
|
||||
ASSERT_TRUE(b->Is<BoolLiteral>());
|
||||
ASSERT_TRUE(b->IsTrue());
|
||||
ASSERT_FALSE(b->IsFalse());
|
||||
}
|
||||
|
||||
TEST_F(BoolLiteralTest, False) {
|
||||
auto* b = create<BoolLiteral>(ty.bool_(), false);
|
||||
auto* b = create<BoolLiteral>(false);
|
||||
ASSERT_TRUE(b->Is<BoolLiteral>());
|
||||
ASSERT_FALSE(b->IsTrue());
|
||||
ASSERT_TRUE(b->IsFalse());
|
||||
}
|
||||
|
||||
TEST_F(BoolLiteralTest, Is) {
|
||||
ast::Literal* l = create<BoolLiteral>(ty.bool_(), false);
|
||||
ast::Literal* l = create<BoolLiteral>(false);
|
||||
EXPECT_TRUE(l->Is<BoolLiteral>());
|
||||
EXPECT_FALSE(l->Is<SintLiteral>());
|
||||
EXPECT_FALSE(l->Is<FloatLiteral>());
|
||||
|
@ -44,8 +44,8 @@ TEST_F(BoolLiteralTest, Is) {
|
|||
}
|
||||
|
||||
TEST_F(BoolLiteralTest, ToStr) {
|
||||
auto* t = create<BoolLiteral>(ty.bool_(), true);
|
||||
auto* f = create<BoolLiteral>(ty.bool_(), false);
|
||||
auto* t = create<BoolLiteral>(true);
|
||||
auto* f = create<BoolLiteral>(false);
|
||||
|
||||
EXPECT_EQ(str(t), "true");
|
||||
EXPECT_EQ(str(f), "false");
|
||||
|
|
|
@ -27,7 +27,7 @@ using CaseStatementTest = TestHelper;
|
|||
|
||||
TEST_F(CaseStatementTest, Creation_i32) {
|
||||
CaseSelectorList b;
|
||||
auto* selector = create<SintLiteral>(ty.i32(), 2);
|
||||
auto* selector = create<SintLiteral>(2);
|
||||
b.push_back(selector);
|
||||
|
||||
auto* discard = create<DiscardStatement>();
|
||||
|
@ -42,7 +42,7 @@ TEST_F(CaseStatementTest, Creation_i32) {
|
|||
|
||||
TEST_F(CaseStatementTest, Creation_u32) {
|
||||
CaseSelectorList b;
|
||||
auto* selector = create<SintLiteral>(ty.u32(), 2);
|
||||
auto* selector = create<UintLiteral>(2u);
|
||||
b.push_back(selector);
|
||||
|
||||
auto* discard = create<DiscardStatement>();
|
||||
|
@ -57,7 +57,7 @@ TEST_F(CaseStatementTest, Creation_u32) {
|
|||
|
||||
TEST_F(CaseStatementTest, Creation_WithSource) {
|
||||
CaseSelectorList b;
|
||||
b.push_back(create<SintLiteral>(ty.i32(), 2));
|
||||
b.push_back(create<SintLiteral>(2));
|
||||
|
||||
auto* body = create<BlockStatement>(StatementList{
|
||||
create<DiscardStatement>(),
|
||||
|
@ -78,7 +78,7 @@ TEST_F(CaseStatementTest, IsDefault_WithoutSelectors) {
|
|||
|
||||
TEST_F(CaseStatementTest, IsDefault_WithSelectors) {
|
||||
CaseSelectorList b;
|
||||
b.push_back(create<SintLiteral>(ty.i32(), 2));
|
||||
b.push_back(create<SintLiteral>(2));
|
||||
|
||||
auto* c = create<CaseStatement>(b, create<BlockStatement>(StatementList{}));
|
||||
EXPECT_FALSE(c->IsDefault());
|
||||
|
@ -125,8 +125,7 @@ TEST_F(CaseStatementTest, Assert_DifferentProgramID_Selector) {
|
|||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.create<CaseStatement>(
|
||||
CaseSelectorList{b2.create<SintLiteral>(b2.ty.i32(), 2)},
|
||||
b1.create<CaseStatement>(CaseSelectorList{b2.create<SintLiteral>(2)},
|
||||
b1.create<BlockStatement>(StatementList{}));
|
||||
},
|
||||
"internal compiler error");
|
||||
|
@ -134,7 +133,7 @@ TEST_F(CaseStatementTest, Assert_DifferentProgramID_Selector) {
|
|||
|
||||
TEST_F(CaseStatementTest, ToStr_WithSelectors_i32) {
|
||||
CaseSelectorList b;
|
||||
b.push_back(create<SintLiteral>(ty.i32(), -2));
|
||||
b.push_back(create<SintLiteral>(-2));
|
||||
|
||||
auto* body = create<BlockStatement>(StatementList{
|
||||
create<DiscardStatement>(),
|
||||
|
@ -149,7 +148,7 @@ TEST_F(CaseStatementTest, ToStr_WithSelectors_i32) {
|
|||
|
||||
TEST_F(CaseStatementTest, ToStr_WithSelectors_u32) {
|
||||
CaseSelectorList b;
|
||||
b.push_back(create<UintLiteral>(ty.u32(), 2));
|
||||
b.push_back(create<UintLiteral>(2));
|
||||
|
||||
auto* body = create<BlockStatement>(StatementList{
|
||||
create<DiscardStatement>(),
|
||||
|
@ -164,8 +163,8 @@ TEST_F(CaseStatementTest, ToStr_WithSelectors_u32) {
|
|||
|
||||
TEST_F(CaseStatementTest, ToStr_WithMultipleSelectors) {
|
||||
CaseSelectorList b;
|
||||
b.push_back(create<SintLiteral>(ty.i32(), 1));
|
||||
b.push_back(create<SintLiteral>(ty.i32(), 2));
|
||||
b.push_back(create<SintLiteral>(1));
|
||||
b.push_back(create<SintLiteral>(2));
|
||||
|
||||
auto* body = create<BlockStatement>(StatementList{
|
||||
create<DiscardStatement>(),
|
||||
|
|
|
@ -25,9 +25,8 @@ namespace ast {
|
|||
|
||||
FloatLiteral::FloatLiteral(ProgramID program_id,
|
||||
const Source& source,
|
||||
typ::Type type,
|
||||
float value)
|
||||
: Base(program_id, source, type), value_(value) {}
|
||||
: Base(program_id, source), value_(value) {}
|
||||
|
||||
FloatLiteral::~FloatLiteral() = default;
|
||||
|
||||
|
@ -46,8 +45,7 @@ std::string FloatLiteral::name() const {
|
|||
FloatLiteral* FloatLiteral::Clone(CloneContext* ctx) const {
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source());
|
||||
auto ty = ctx->Clone(type());
|
||||
return ctx->dst->create<FloatLiteral>(src, ty, value_);
|
||||
return ctx->dst->create<FloatLiteral>(src, value_);
|
||||
}
|
||||
|
||||
} // namespace ast
|
||||
|
|
|
@ -28,12 +28,8 @@ class FloatLiteral : public Castable<FloatLiteral, Literal> {
|
|||
/// Constructor
|
||||
/// @param program_id the identifier of the program that owns this node
|
||||
/// @param source the input source
|
||||
/// @param type the type of the literal
|
||||
/// @param value the float literals value
|
||||
FloatLiteral(ProgramID program_id,
|
||||
const Source& source,
|
||||
typ::Type type,
|
||||
float value);
|
||||
FloatLiteral(ProgramID program_id, const Source& source, float value);
|
||||
~FloatLiteral() override;
|
||||
|
||||
/// @returns the float literal value
|
||||
|
|
|
@ -21,13 +21,13 @@ namespace {
|
|||
using FloatLiteralTest = TestHelper;
|
||||
|
||||
TEST_F(FloatLiteralTest, Value) {
|
||||
auto* f = create<FloatLiteral>(ty.f32(), 47.2f);
|
||||
auto* f = create<FloatLiteral>(47.2f);
|
||||
ASSERT_TRUE(f->Is<FloatLiteral>());
|
||||
EXPECT_EQ(f->value(), 47.2f);
|
||||
}
|
||||
|
||||
TEST_F(FloatLiteralTest, Is) {
|
||||
ast::Literal* l = create<FloatLiteral>(ty.f32(), 42.f);
|
||||
ast::Literal* l = create<FloatLiteral>(42.f);
|
||||
EXPECT_FALSE(l->Is<BoolLiteral>());
|
||||
EXPECT_FALSE(l->Is<SintLiteral>());
|
||||
EXPECT_FALSE(l->Is<IntLiteral>());
|
||||
|
@ -36,12 +36,12 @@ TEST_F(FloatLiteralTest, Is) {
|
|||
}
|
||||
|
||||
TEST_F(FloatLiteralTest, ToStr) {
|
||||
auto* f = create<FloatLiteral>(ty.f32(), 42.1f);
|
||||
auto* f = create<FloatLiteral>(42.1f);
|
||||
EXPECT_EQ(str(f), "42.099998");
|
||||
}
|
||||
|
||||
TEST_F(FloatLiteralTest, ToName) {
|
||||
auto* f = create<FloatLiteral>(ty.f32(), 42.1f);
|
||||
auto* f = create<FloatLiteral>(42.1f);
|
||||
EXPECT_EQ(f->name(), "__float42.0999985");
|
||||
}
|
||||
|
||||
|
|
|
@ -21,9 +21,8 @@ namespace ast {
|
|||
|
||||
IntLiteral::IntLiteral(ProgramID program_id,
|
||||
const Source& source,
|
||||
typ::Type type,
|
||||
uint32_t value)
|
||||
: Base(program_id, source, type), value_(value) {}
|
||||
: Base(program_id, source), value_(value) {}
|
||||
|
||||
IntLiteral::~IntLiteral() = default;
|
||||
|
||||
|
|
|
@ -32,12 +32,8 @@ class IntLiteral : public Castable<IntLiteral, Literal> {
|
|||
/// Constructor
|
||||
/// @param program_id the identifier of the program that owns this node
|
||||
/// @param source the input source
|
||||
/// @param type the type of the literal
|
||||
/// @param value value of the literal
|
||||
IntLiteral(ProgramID program_id,
|
||||
const Source& source,
|
||||
typ::Type type,
|
||||
uint32_t value);
|
||||
IntLiteral(ProgramID program_id, const Source& source, uint32_t value);
|
||||
|
||||
private:
|
||||
uint32_t const value_;
|
||||
|
|
|
@ -21,12 +21,12 @@ namespace {
|
|||
using IntLiteralTest = TestHelper;
|
||||
|
||||
TEST_F(IntLiteralTest, Sint_IsInt) {
|
||||
auto* i = create<SintLiteral>(ty.i32(), 47);
|
||||
auto* i = create<SintLiteral>(47);
|
||||
ASSERT_TRUE(i->Is<IntLiteral>());
|
||||
}
|
||||
|
||||
TEST_F(IntLiteralTest, Uint_IsInt) {
|
||||
auto* i = create<UintLiteral>(ty.i32(), 42);
|
||||
auto* i = create<UintLiteral>(42);
|
||||
EXPECT_TRUE(i->Is<IntLiteral>());
|
||||
}
|
||||
|
||||
|
|
|
@ -19,8 +19,8 @@ TINT_INSTANTIATE_TYPEINFO(tint::ast::Literal);
|
|||
namespace tint {
|
||||
namespace ast {
|
||||
|
||||
Literal::Literal(ProgramID program_id, const Source& source, typ::Type type)
|
||||
: Base(program_id, source), type_(type) {}
|
||||
Literal::Literal(ProgramID program_id, const Source& source)
|
||||
: Base(program_id, source) {}
|
||||
|
||||
Literal::~Literal() = default;
|
||||
|
||||
|
|
|
@ -27,9 +27,6 @@ class Literal : public Castable<Literal, Node> {
|
|||
public:
|
||||
~Literal() override;
|
||||
|
||||
/// @returns the type of the literal
|
||||
typ::Type type() const { return type_; }
|
||||
|
||||
/// Writes a representation of the node to the output stream
|
||||
/// @param sem the semantic info for the program
|
||||
/// @param out the stream to write to
|
||||
|
@ -49,11 +46,7 @@ class Literal : public Castable<Literal, Node> {
|
|||
/// Constructor
|
||||
/// @param program_id the identifier of the program that owns this node
|
||||
/// @param source the input source
|
||||
/// @param type the type of the literal
|
||||
explicit Literal(ProgramID program_id, const Source& source, typ::Type type);
|
||||
|
||||
private:
|
||||
typ::Type const type_;
|
||||
Literal(ProgramID program_id, const Source& source);
|
||||
};
|
||||
|
||||
} // namespace ast
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace {
|
|||
using ScalarConstructorExpressionTest = TestHelper;
|
||||
|
||||
TEST_F(ScalarConstructorExpressionTest, Creation) {
|
||||
auto* b = create<BoolLiteral>(ty.bool_(), true);
|
||||
auto* b = create<BoolLiteral>(true);
|
||||
auto* c = create<ScalarConstructorExpression>(b);
|
||||
EXPECT_EQ(c->literal(), b);
|
||||
}
|
||||
|
@ -45,8 +45,7 @@ TEST_F(ScalarConstructorExpressionTest, Assert_DifferentProgramID_Literal) {
|
|||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.create<ScalarConstructorExpression>(
|
||||
b2.create<BoolLiteral>(b2.ty.bool_(), true));
|
||||
b1.create<ScalarConstructorExpression>(b2.create<BoolLiteral>(true));
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
|
|
@ -23,9 +23,8 @@ namespace ast {
|
|||
|
||||
SintLiteral::SintLiteral(ProgramID program_id,
|
||||
const Source& source,
|
||||
typ::Type type,
|
||||
int32_t value)
|
||||
: Base(program_id, source, type, static_cast<uint32_t>(value)) {}
|
||||
: Base(program_id, source, static_cast<uint32_t>(value)) {}
|
||||
|
||||
SintLiteral::~SintLiteral() = default;
|
||||
|
||||
|
@ -34,14 +33,13 @@ std::string SintLiteral::to_str(const sem::Info&) const {
|
|||
}
|
||||
|
||||
std::string SintLiteral::name() const {
|
||||
return "__sint" + type()->type_name() + "_" + std::to_string(value());
|
||||
return "__sint_" + std::to_string(value());
|
||||
}
|
||||
|
||||
SintLiteral* SintLiteral::Clone(CloneContext* ctx) const {
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source());
|
||||
auto ty = ctx->Clone(type());
|
||||
return ctx->dst->create<SintLiteral>(src, ty, value());
|
||||
return ctx->dst->create<SintLiteral>(src, value());
|
||||
}
|
||||
|
||||
} // namespace ast
|
||||
|
|
|
@ -28,12 +28,8 @@ class SintLiteral : public Castable<SintLiteral, IntLiteral> {
|
|||
/// Constructor
|
||||
/// @param program_id the identifier of the program that owns this node
|
||||
/// @param source the input source
|
||||
/// @param type the type
|
||||
/// @param value the signed int literals value
|
||||
SintLiteral(ProgramID program_id,
|
||||
const Source& source,
|
||||
typ::Type type,
|
||||
int32_t value);
|
||||
SintLiteral(ProgramID program_id, const Source& source, int32_t value);
|
||||
~SintLiteral() override;
|
||||
|
||||
/// @returns the int literal value
|
||||
|
|
|
@ -21,13 +21,13 @@ namespace {
|
|||
using SintLiteralTest = TestHelper;
|
||||
|
||||
TEST_F(SintLiteralTest, Value) {
|
||||
auto* i = create<SintLiteral>(ty.i32(), 47);
|
||||
auto* i = create<SintLiteral>(47);
|
||||
ASSERT_TRUE(i->Is<SintLiteral>());
|
||||
EXPECT_EQ(i->value(), 47);
|
||||
}
|
||||
|
||||
TEST_F(SintLiteralTest, Is) {
|
||||
ast::Literal* l = create<SintLiteral>(ty.i32(), 42);
|
||||
ast::Literal* l = create<SintLiteral>(42);
|
||||
EXPECT_FALSE(l->Is<BoolLiteral>());
|
||||
EXPECT_TRUE(l->Is<SintLiteral>());
|
||||
EXPECT_FALSE(l->Is<FloatLiteral>());
|
||||
|
@ -35,18 +35,13 @@ TEST_F(SintLiteralTest, Is) {
|
|||
}
|
||||
|
||||
TEST_F(SintLiteralTest, ToStr) {
|
||||
auto* i = create<SintLiteral>(ty.i32(), -42);
|
||||
auto* i = create<SintLiteral>(-42);
|
||||
EXPECT_EQ(str(i), "-42");
|
||||
}
|
||||
|
||||
TEST_F(SintLiteralTest, Name_I32) {
|
||||
auto* i = create<SintLiteral>(ty.i32(), 2);
|
||||
EXPECT_EQ("__sint__i32_2", i->name());
|
||||
}
|
||||
|
||||
TEST_F(SintLiteralTest, Name_U32) {
|
||||
auto* i = create<SintLiteral>(ty.u32(), 2);
|
||||
EXPECT_EQ("__sint__u32_2", i->name());
|
||||
auto* i = create<SintLiteral>(2);
|
||||
EXPECT_EQ("__sint_2", i->name());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -25,7 +25,7 @@ using SwitchStatementTest = TestHelper;
|
|||
|
||||
TEST_F(SwitchStatementTest, Creation) {
|
||||
CaseSelectorList lit;
|
||||
lit.push_back(create<SintLiteral>(ty.i32(), 1));
|
||||
lit.push_back(create<SintLiteral>(1));
|
||||
|
||||
auto* ident = Expr("ident");
|
||||
CaseStatementList body;
|
||||
|
@ -50,7 +50,7 @@ TEST_F(SwitchStatementTest, Creation_WithSource) {
|
|||
|
||||
TEST_F(SwitchStatementTest, IsSwitch) {
|
||||
CaseSelectorList lit;
|
||||
lit.push_back(create<SintLiteral>(ty.i32(), 2));
|
||||
lit.push_back(create<SintLiteral>(2));
|
||||
|
||||
auto* ident = Expr("ident");
|
||||
CaseStatementList body;
|
||||
|
@ -127,7 +127,7 @@ TEST_F(SwitchStatementTest, ToStr_Empty) {
|
|||
|
||||
TEST_F(SwitchStatementTest, ToStr) {
|
||||
CaseSelectorList lit;
|
||||
lit.push_back(create<SintLiteral>(ty.i32(), 2));
|
||||
lit.push_back(create<SintLiteral>(2));
|
||||
|
||||
auto* ident = Expr("ident");
|
||||
CaseStatementList body;
|
||||
|
|
|
@ -23,9 +23,8 @@ namespace ast {
|
|||
|
||||
UintLiteral::UintLiteral(ProgramID program_id,
|
||||
const Source& source,
|
||||
typ::Type type,
|
||||
uint32_t value)
|
||||
: Base(program_id, source, type, value) {}
|
||||
: Base(program_id, source, value) {}
|
||||
|
||||
UintLiteral::~UintLiteral() = default;
|
||||
|
||||
|
@ -40,8 +39,7 @@ std::string UintLiteral::name() const {
|
|||
UintLiteral* UintLiteral::Clone(CloneContext* ctx) const {
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source());
|
||||
auto ty = ctx->Clone(type());
|
||||
return ctx->dst->create<UintLiteral>(src, ty, value());
|
||||
return ctx->dst->create<UintLiteral>(src, value());
|
||||
}
|
||||
|
||||
} // namespace ast
|
||||
|
|
|
@ -28,12 +28,8 @@ class UintLiteral : public Castable<UintLiteral, IntLiteral> {
|
|||
/// Constructor
|
||||
/// @param program_id the identifier of the program that owns this node
|
||||
/// @param source the input source
|
||||
/// @param type the type of the literal
|
||||
/// @param value the uint literals value
|
||||
UintLiteral(ProgramID program_id,
|
||||
const Source& source,
|
||||
typ::Type type,
|
||||
uint32_t value);
|
||||
UintLiteral(ProgramID program_id, const Source& source, uint32_t value);
|
||||
~UintLiteral() override;
|
||||
|
||||
/// @returns the uint literal value
|
||||
|
|
|
@ -21,13 +21,13 @@ namespace {
|
|||
using UintLiteralTest = TestHelper;
|
||||
|
||||
TEST_F(UintLiteralTest, Value) {
|
||||
auto* u = create<UintLiteral>(ty.u32(), 47);
|
||||
auto* u = create<UintLiteral>(47);
|
||||
ASSERT_TRUE(u->Is<UintLiteral>());
|
||||
EXPECT_EQ(u->value(), 47u);
|
||||
}
|
||||
|
||||
TEST_F(UintLiteralTest, Is) {
|
||||
ast::Literal* l = create<UintLiteral>(ty.u32(), 42);
|
||||
ast::Literal* l = create<UintLiteral>(42);
|
||||
EXPECT_FALSE(l->Is<BoolLiteral>());
|
||||
EXPECT_FALSE(l->Is<SintLiteral>());
|
||||
EXPECT_FALSE(l->Is<FloatLiteral>());
|
||||
|
@ -35,7 +35,7 @@ TEST_F(UintLiteralTest, Is) {
|
|||
}
|
||||
|
||||
TEST_F(UintLiteralTest, ToStr) {
|
||||
auto* u = create<UintLiteral>(ty.u32(), 42u);
|
||||
auto* u = create<UintLiteral>(42u);
|
||||
EXPECT_EQ(str(u), "42u");
|
||||
}
|
||||
|
||||
|
|
|
@ -147,8 +147,7 @@ class InspectorHelper : public ProgramBuilder {
|
|||
void AddConstantID(std::string name, uint32_t id, typ::Type type, T* val) {
|
||||
ast::Expression* constructor = nullptr;
|
||||
if (val) {
|
||||
constructor =
|
||||
create<ast::ScalarConstructorExpression>(MakeLiteral(type, val));
|
||||
constructor = Expr(*val);
|
||||
}
|
||||
GlobalConst(name, type, constructor,
|
||||
ast::DecorationList{
|
||||
|
@ -156,34 +155,6 @@ class InspectorHelper : public ProgramBuilder {
|
|||
});
|
||||
}
|
||||
|
||||
/// @param type AST type of the literal, must resolve to BoolLiteral
|
||||
/// @param val scalar value for the literal to contain
|
||||
/// @returns a Literal of the expected type and value
|
||||
ast::Literal* MakeLiteral(typ::Type type, bool* val) {
|
||||
return create<ast::BoolLiteral>(type, *val);
|
||||
}
|
||||
|
||||
/// @param type AST type of the literal, must resolve to UIntLiteral
|
||||
/// @param val scalar value for the literal to contain
|
||||
/// @returns a Literal of the expected type and value
|
||||
ast::Literal* MakeLiteral(typ::Type type, uint32_t* val) {
|
||||
return create<ast::UintLiteral>(type, *val);
|
||||
}
|
||||
|
||||
/// @param type AST type of the literal, must resolve to IntLiteral
|
||||
/// @param val scalar value for the literal to contain
|
||||
/// @returns a Literal of the expected type and value
|
||||
ast::Literal* MakeLiteral(typ::Type type, int32_t* val) {
|
||||
return create<ast::SintLiteral>(type, *val);
|
||||
}
|
||||
|
||||
/// @param type AST type of the literal, must resolve to FloattLiteral
|
||||
/// @param val scalar value for the literal to contain
|
||||
/// @returns a Literal of the expected type and value
|
||||
ast::Literal* MakeLiteral(typ::Type type, float* val) {
|
||||
return create<ast::FloatLiteral>(type, *val);
|
||||
}
|
||||
|
||||
/// @param vec Vector of StageVariable to be searched
|
||||
/// @param name Name to be searching for
|
||||
/// @returns true if name is in vec, otherwise false
|
||||
|
|
|
@ -97,19 +97,19 @@ ast::ConstructorExpression* ProgramBuilder::ConstructValueFilledWith(
|
|||
auto* unwrapped_type = type->UnwrapAliasIfNeeded();
|
||||
if (unwrapped_type->Is<sem::Bool>()) {
|
||||
return create<ast::ScalarConstructorExpression>(
|
||||
create<ast::BoolLiteral>(type, elem_value == 0 ? false : true));
|
||||
create<ast::BoolLiteral>(elem_value == 0 ? false : true));
|
||||
}
|
||||
if (unwrapped_type->Is<sem::I32>()) {
|
||||
return create<ast::ScalarConstructorExpression>(create<ast::SintLiteral>(
|
||||
type, static_cast<ProgramBuilder::i32>(elem_value)));
|
||||
return create<ast::ScalarConstructorExpression>(
|
||||
create<ast::SintLiteral>(static_cast<i32>(elem_value)));
|
||||
}
|
||||
if (unwrapped_type->Is<sem::U32>()) {
|
||||
return create<ast::ScalarConstructorExpression>(create<ast::UintLiteral>(
|
||||
type, static_cast<ProgramBuilder::u32>(elem_value)));
|
||||
return create<ast::ScalarConstructorExpression>(
|
||||
create<ast::UintLiteral>(static_cast<u32>(elem_value)));
|
||||
}
|
||||
if (unwrapped_type->Is<sem::F32>()) {
|
||||
return create<ast::ScalarConstructorExpression>(create<ast::FloatLiteral>(
|
||||
type, static_cast<ProgramBuilder::f32>(elem_value)));
|
||||
return create<ast::ScalarConstructorExpression>(
|
||||
create<ast::FloatLiteral>(static_cast<f32>(elem_value)));
|
||||
}
|
||||
if (auto* v = unwrapped_type->As<sem::Vector>()) {
|
||||
ast::ExpressionList el(v->size());
|
||||
|
|
|
@ -992,27 +992,19 @@ class ProgramBuilder {
|
|||
|
||||
/// @param val the boolan value
|
||||
/// @return a boolean literal with the given value
|
||||
ast::BoolLiteral* Literal(bool val) {
|
||||
return create<ast::BoolLiteral>(ty.bool_(), val);
|
||||
}
|
||||
ast::BoolLiteral* Literal(bool val) { return create<ast::BoolLiteral>(val); }
|
||||
|
||||
/// @param val the float value
|
||||
/// @return a float literal with the given value
|
||||
ast::FloatLiteral* Literal(f32 val) {
|
||||
return create<ast::FloatLiteral>(ty.f32(), val);
|
||||
}
|
||||
ast::FloatLiteral* Literal(f32 val) { return create<ast::FloatLiteral>(val); }
|
||||
|
||||
/// @param val the unsigned int value
|
||||
/// @return a ast::UintLiteral with the given value
|
||||
ast::UintLiteral* Literal(u32 val) {
|
||||
return create<ast::UintLiteral>(ty.u32(), val);
|
||||
}
|
||||
ast::UintLiteral* Literal(u32 val) { return create<ast::UintLiteral>(val); }
|
||||
|
||||
/// @param val the integer value
|
||||
/// @return the ast::SintLiteral with the given value
|
||||
ast::SintLiteral* Literal(i32 val) {
|
||||
return create<ast::SintLiteral>(ty.i32(), val);
|
||||
}
|
||||
ast::SintLiteral* Literal(i32 val) { return create<ast::SintLiteral>(val); }
|
||||
|
||||
/// @param args the arguments for the type constructor
|
||||
/// @return an `ast::TypeConstructorExpression` of type `ty`, with the values
|
||||
|
|
|
@ -2032,10 +2032,9 @@ TypedExpression FunctionEmitter::MakeExpression(uint32_t id) {
|
|||
<< id;
|
||||
return {};
|
||||
case SkipReason::kPointSizeBuiltinValue: {
|
||||
auto* f32 = create<sem::F32>();
|
||||
return {f32,
|
||||
return {create<sem::F32>(),
|
||||
create<ast::ScalarConstructorExpression>(
|
||||
Source{}, create<ast::FloatLiteral>(Source{}, f32, 1.0f))};
|
||||
Source{}, create<ast::FloatLiteral>(Source{}, 1.0f))};
|
||||
}
|
||||
case SkipReason::kPointSizeBuiltinPointer:
|
||||
Fail() << "unhandled use of a pointer to the PointSize builtin, with ID: "
|
||||
|
@ -2545,11 +2544,9 @@ 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->is_unsigned_scalar_or_vector()) {
|
||||
selectors.emplace_back(
|
||||
create<ast::UintLiteral>(Source{}, selector.type, value32));
|
||||
selectors.emplace_back(create<ast::UintLiteral>(Source{}, value32));
|
||||
} else {
|
||||
selectors.emplace_back(
|
||||
create<ast::SintLiteral>(Source{}, selector.type, value32));
|
||||
selectors.emplace_back(create<ast::SintLiteral>(Source{}, value32));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3679,7 +3676,7 @@ TypedExpression FunctionEmitter::MakeCompositeValueDecomposition(
|
|||
|
||||
auto make_index = [this](uint32_t literal) {
|
||||
return create<ast::ScalarConstructorExpression>(
|
||||
Source{}, create<ast::UintLiteral>(Source{}, u32_, literal));
|
||||
Source{}, create<ast::UintLiteral>(Source{}, literal));
|
||||
};
|
||||
|
||||
// Build up a nested expression for the decomposition by walking down the type
|
||||
|
@ -3795,13 +3792,13 @@ TypedExpression FunctionEmitter::MakeCompositeValueDecomposition(
|
|||
|
||||
ast::Expression* FunctionEmitter::MakeTrue(const Source& source) const {
|
||||
return create<ast::ScalarConstructorExpression>(
|
||||
source, create<ast::BoolLiteral>(source, parser_impl_.Bool(), true));
|
||||
source, create<ast::BoolLiteral>(source, true));
|
||||
}
|
||||
|
||||
ast::Expression* FunctionEmitter::MakeFalse(const Source& source) const {
|
||||
sem::Bool bool_type;
|
||||
return create<ast::ScalarConstructorExpression>(
|
||||
source, create<ast::BoolLiteral>(source, parser_impl_.Bool(), false));
|
||||
source, create<ast::BoolLiteral>(source, false));
|
||||
}
|
||||
|
||||
TypedExpression FunctionEmitter::MakeVectorShuffle(
|
||||
|
|
|
@ -1066,9 +1066,8 @@ bool ParserImpl::EmitScalarSpecConstants() {
|
|||
case SpvOpSpecConstantFalse: {
|
||||
ast_type = ConvertType(inst.type_id());
|
||||
ast_expr = create<ast::ScalarConstructorExpression>(
|
||||
Source{},
|
||||
create<ast::BoolLiteral>(Source{}, ast_type,
|
||||
inst.opcode() == SpvOpSpecConstantTrue));
|
||||
Source{}, create<ast::BoolLiteral>(
|
||||
Source{}, inst.opcode() == SpvOpSpecConstantTrue));
|
||||
break;
|
||||
}
|
||||
case SpvOpSpecConstant: {
|
||||
|
@ -1076,21 +1075,18 @@ bool ParserImpl::EmitScalarSpecConstants() {
|
|||
const uint32_t literal_value = inst.GetSingleWordInOperand(0);
|
||||
if (ast_type->Is<sem::I32>()) {
|
||||
ast_expr = create<ast::ScalarConstructorExpression>(
|
||||
Source{},
|
||||
create<ast::SintLiteral>(Source{}, ast_type,
|
||||
static_cast<int32_t>(literal_value)));
|
||||
Source{}, create<ast::SintLiteral>(
|
||||
Source{}, static_cast<int32_t>(literal_value)));
|
||||
} else if (ast_type->Is<sem::U32>()) {
|
||||
ast_expr = create<ast::ScalarConstructorExpression>(
|
||||
Source{},
|
||||
create<ast::UintLiteral>(Source{}, ast_type,
|
||||
static_cast<uint32_t>(literal_value)));
|
||||
Source{}, create<ast::UintLiteral>(
|
||||
Source{}, static_cast<uint32_t>(literal_value)));
|
||||
} else if (ast_type->Is<sem::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::ScalarConstructorExpression>(
|
||||
Source{},
|
||||
create<ast::FloatLiteral>(Source{}, ast_type, float_value));
|
||||
Source{}, create<ast::FloatLiteral>(Source{}, float_value));
|
||||
} else {
|
||||
return Fail() << " invalid result type for OpSpecConstant "
|
||||
<< inst.PrettyPrint();
|
||||
|
@ -1421,30 +1417,26 @@ TypedExpression ParserImpl::MakeConstantExpression(uint32_t id) {
|
|||
// Currently "null<type>" is missing from the WGSL parser.
|
||||
// See https://bugs.chromium.org/p/tint/issues/detail?id=34
|
||||
if (ast_type->Is<sem::U32>()) {
|
||||
return {ast_type,
|
||||
create<ast::ScalarConstructorExpression>(
|
||||
Source{}, create<ast::UintLiteral>(source, ast_type,
|
||||
spirv_const->GetU32()))};
|
||||
return {ast_type, create<ast::ScalarConstructorExpression>(
|
||||
Source{}, create<ast::UintLiteral>(
|
||||
source, spirv_const->GetU32()))};
|
||||
}
|
||||
if (ast_type->Is<sem::I32>()) {
|
||||
return {ast_type,
|
||||
create<ast::ScalarConstructorExpression>(
|
||||
Source{}, create<ast::SintLiteral>(source, ast_type,
|
||||
spirv_const->GetS32()))};
|
||||
return {ast_type, create<ast::ScalarConstructorExpression>(
|
||||
Source{}, create<ast::SintLiteral>(
|
||||
source, spirv_const->GetS32()))};
|
||||
}
|
||||
if (ast_type->Is<sem::F32>()) {
|
||||
return {ast_type,
|
||||
create<ast::ScalarConstructorExpression>(
|
||||
Source{}, create<ast::FloatLiteral>(source, ast_type,
|
||||
spirv_const->GetFloat()))};
|
||||
return {ast_type, create<ast::ScalarConstructorExpression>(
|
||||
Source{}, create<ast::FloatLiteral>(
|
||||
source, spirv_const->GetFloat()))};
|
||||
}
|
||||
if (ast_type->Is<sem::Bool>()) {
|
||||
const bool value = spirv_const->AsNullConstant()
|
||||
? false
|
||||
: spirv_const->AsBoolConstant()->value();
|
||||
return {ast_type,
|
||||
create<ast::ScalarConstructorExpression>(
|
||||
Source{}, create<ast::BoolLiteral>(source, ast_type, value))};
|
||||
return {ast_type, create<ast::ScalarConstructorExpression>(
|
||||
Source{}, create<ast::BoolLiteral>(source, value))};
|
||||
}
|
||||
auto* spirv_composite_const = spirv_const->AsCompositeConstant();
|
||||
if (spirv_composite_const != nullptr) {
|
||||
|
@ -1498,19 +1490,19 @@ ast::Expression* ParserImpl::MakeNullValue(sem::Type* type) {
|
|||
|
||||
if (type->Is<sem::Bool>()) {
|
||||
return create<ast::ScalarConstructorExpression>(
|
||||
Source{}, create<ast::BoolLiteral>(Source{}, type, false));
|
||||
Source{}, create<ast::BoolLiteral>(Source{}, false));
|
||||
}
|
||||
if (type->Is<sem::U32>()) {
|
||||
return create<ast::ScalarConstructorExpression>(
|
||||
Source{}, create<ast::UintLiteral>(Source{}, type, 0u));
|
||||
Source{}, create<ast::UintLiteral>(Source{}, 0u));
|
||||
}
|
||||
if (type->Is<sem::I32>()) {
|
||||
return create<ast::ScalarConstructorExpression>(
|
||||
Source{}, create<ast::SintLiteral>(Source{}, type, 0));
|
||||
Source{}, create<ast::SintLiteral>(Source{}, 0));
|
||||
}
|
||||
if (type->Is<sem::F32>()) {
|
||||
return create<ast::ScalarConstructorExpression>(
|
||||
Source{}, create<ast::FloatLiteral>(Source{}, type, 0.0f));
|
||||
Source{}, create<ast::FloatLiteral>(Source{}, 0.0f));
|
||||
}
|
||||
if (const auto* vec_ty = type->As<sem::Vector>()) {
|
||||
ast::ExpressionList ast_components;
|
||||
|
|
|
@ -2840,20 +2840,16 @@ Maybe<ast::AssignmentStatement*> ParserImpl::assignment_stmt() {
|
|||
Maybe<ast::Literal*> ParserImpl::const_literal() {
|
||||
auto t = peek();
|
||||
if (match(Token::Type::kTrue)) {
|
||||
auto* type = builder_.create<sem::Bool>();
|
||||
return create<ast::BoolLiteral>(Source{}, type, true);
|
||||
return create<ast::BoolLiteral>(Source{}, true);
|
||||
}
|
||||
if (match(Token::Type::kFalse)) {
|
||||
auto* type = builder_.create<sem::Bool>();
|
||||
return create<ast::BoolLiteral>(Source{}, type, false);
|
||||
return create<ast::BoolLiteral>(Source{}, false);
|
||||
}
|
||||
if (match(Token::Type::kSintLiteral)) {
|
||||
auto* type = builder_.create<sem::I32>();
|
||||
return create<ast::SintLiteral>(Source{}, type, t.to_i32());
|
||||
return create<ast::SintLiteral>(Source{}, t.to_i32());
|
||||
}
|
||||
if (match(Token::Type::kUintLiteral)) {
|
||||
auto* type = builder_.create<sem::U32>();
|
||||
return create<ast::UintLiteral>(Source{}, type, t.to_u32());
|
||||
return create<ast::UintLiteral>(Source{}, t.to_u32());
|
||||
}
|
||||
if (match(Token::Type::kFloatLiteral)) {
|
||||
auto p = peek();
|
||||
|
@ -2861,8 +2857,7 @@ Maybe<ast::Literal*> ParserImpl::const_literal() {
|
|||
next(); // Consume 'f'
|
||||
add_error(p.source(), "float literals must not be suffixed with 'f'");
|
||||
}
|
||||
auto* type = builder_.create<sem::F32>();
|
||||
return create<ast::FloatLiteral>(Source{}, type, t.to_f32());
|
||||
return create<ast::FloatLiteral>(Source{}, t.to_f32());
|
||||
}
|
||||
return Failure::kNoMatch;
|
||||
}
|
||||
|
|
|
@ -119,7 +119,7 @@ TEST_F(ResolverControlBlockValidationTest,
|
|||
|
||||
ast::CaseStatementList switch_body;
|
||||
ast::CaseSelectorList csl;
|
||||
csl.push_back(create<ast::UintLiteral>(ty.u32(), 1));
|
||||
csl.push_back(create<ast::UintLiteral>(1u));
|
||||
switch_body.push_back(create<ast::CaseStatement>(
|
||||
Source{Source::Location{12, 34}}, csl, Block()));
|
||||
|
||||
|
@ -178,12 +178,12 @@ TEST_F(ResolverControlBlockValidationTest,
|
|||
|
||||
ast::CaseStatementList switch_body;
|
||||
ast::CaseSelectorList csl_1;
|
||||
csl_1.push_back(create<ast::UintLiteral>(ty.u32(), 0));
|
||||
csl_1.push_back(create<ast::UintLiteral>(0u));
|
||||
switch_body.push_back(create<ast::CaseStatement>(csl_1, Block()));
|
||||
|
||||
ast::CaseSelectorList csl_2;
|
||||
csl_2.push_back(create<ast::UintLiteral>(ty.u32(), 2));
|
||||
csl_2.push_back(create<ast::UintLiteral>(ty.u32(), 2));
|
||||
csl_2.push_back(create<ast::UintLiteral>(2u));
|
||||
csl_2.push_back(create<ast::UintLiteral>(2u));
|
||||
switch_body.push_back(create<ast::CaseStatement>(
|
||||
Source{Source::Location{12, 34}}, csl_2, Block()));
|
||||
|
||||
|
|
|
@ -350,8 +350,13 @@ Resolver::VariableInfo* Resolver::Variable(
|
|||
return it->second;
|
||||
}
|
||||
|
||||
auto* ctype = Canonical(type ? type : var->declared_type());
|
||||
auto* info = variable_infos_.Create(var, ctype);
|
||||
if (!type) {
|
||||
type = var->declared_type();
|
||||
}
|
||||
|
||||
auto type_name = type->FriendlyName(builder_->Symbols());
|
||||
auto* ctype = Canonical(type);
|
||||
auto* info = variable_infos_.Create(var, ctype, type_name);
|
||||
variable_to_info_.emplace(var, info);
|
||||
|
||||
// Resolve variable's type
|
||||
|
@ -1304,28 +1309,34 @@ bool Resolver::Constructor(ast::ConstructorExpression* expr) {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
SetType(expr, type_ctor->type());
|
||||
|
||||
// Now that the argument types have been determined, make sure that they
|
||||
// obey the constructor type rules laid out in
|
||||
// https://gpuweb.github.io/gpuweb/wgsl.html#type-constructor-expr.
|
||||
if (auto* vec_type = type_ctor->type()->As<sem::Vector>()) {
|
||||
return ValidateVectorConstructor(vec_type, type_ctor->values());
|
||||
return ValidateVectorConstructor(type_ctor, vec_type,
|
||||
type_ctor->values());
|
||||
}
|
||||
if (auto* mat_type = type_ctor->type()->As<sem::Matrix>()) {
|
||||
return ValidateMatrixConstructor(mat_type, type_ctor->values());
|
||||
auto mat_typename = TypeNameOf(type_ctor);
|
||||
return ValidateMatrixConstructor(type_ctor, mat_type,
|
||||
type_ctor->values());
|
||||
}
|
||||
// TODO(crbug.com/tint/634): Validate array constructor
|
||||
} else if (auto* scalar_ctor = expr->As<ast::ScalarConstructorExpression>()) {
|
||||
Mark(scalar_ctor->literal());
|
||||
SetType(expr, scalar_ctor->literal()->type());
|
||||
SetType(expr, TypeOf(scalar_ctor->literal()));
|
||||
} else {
|
||||
TINT_ICE(diagnostics_) << "unexpected constructor expression type";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Resolver::ValidateVectorConstructor(const sem::Vector* vec_type,
|
||||
bool Resolver::ValidateVectorConstructor(
|
||||
const ast::TypeConstructorExpression* ctor,
|
||||
const sem::Vector* vec_type,
|
||||
const ast::ExpressionList& values) {
|
||||
auto* elem_type = vec_type->type()->UnwrapAll();
|
||||
size_t value_cardinality_sum = 0;
|
||||
|
@ -1337,7 +1348,7 @@ bool Resolver::ValidateVectorConstructor(const sem::Vector* vec_type,
|
|||
"type in vector constructor does not match vector type: "
|
||||
"expected '" +
|
||||
elem_type->FriendlyName(builder_->Symbols()) + "', found '" +
|
||||
value_type->FriendlyName(builder_->Symbols()) + "'",
|
||||
TypeNameOf(value) + "'",
|
||||
value->source());
|
||||
return false;
|
||||
}
|
||||
|
@ -1384,8 +1395,7 @@ bool Resolver::ValidateVectorConstructor(const sem::Vector* vec_type,
|
|||
const Source& values_start = values[0]->source();
|
||||
const Source& values_end = values[values.size() - 1]->source();
|
||||
diagnostics_.add_error(
|
||||
"attempted to construct '" +
|
||||
vec_type->FriendlyName(builder_->Symbols()) + "' with " +
|
||||
"attempted to construct '" + TypeNameOf(ctor) + "' with " +
|
||||
std::to_string(value_cardinality_sum) + " component(s)",
|
||||
Source::Combine(values_start, values_end));
|
||||
return false;
|
||||
|
@ -1393,7 +1403,9 @@ bool Resolver::ValidateVectorConstructor(const sem::Vector* vec_type,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Resolver::ValidateMatrixConstructor(const sem::Matrix* matrix_type,
|
||||
bool Resolver::ValidateMatrixConstructor(
|
||||
const ast::TypeConstructorExpression* ctor,
|
||||
const sem::Matrix* matrix_type,
|
||||
const ast::ExpressionList& values) {
|
||||
// Zero Value expression
|
||||
if (values.empty()) {
|
||||
|
@ -1407,8 +1419,8 @@ bool Resolver::ValidateMatrixConstructor(const sem::Matrix* matrix_type,
|
|||
diagnostics_.add_error(
|
||||
"expected " + std::to_string(matrix_type->columns()) + " '" +
|
||||
VectorPretty(matrix_type->rows(), elem_type) + "' arguments in '" +
|
||||
matrix_type->FriendlyName(builder_->Symbols()) +
|
||||
"' constructor, found " + std::to_string(values.size()),
|
||||
TypeNameOf(ctor) + "' constructor, found " +
|
||||
std::to_string(values.size()),
|
||||
Source::Combine(values_start, values_end));
|
||||
return false;
|
||||
}
|
||||
|
@ -1419,12 +1431,11 @@ bool Resolver::ValidateMatrixConstructor(const sem::Matrix* matrix_type,
|
|||
|
||||
if (!value_vec || value_vec->size() != matrix_type->rows() ||
|
||||
elem_type != value_vec->type()->UnwrapAll()) {
|
||||
diagnostics_.add_error(
|
||||
"expected argument type '" +
|
||||
VectorPretty(matrix_type->rows(), elem_type) + "' in '" +
|
||||
matrix_type->FriendlyName(builder_->Symbols()) +
|
||||
"' constructor, found '" +
|
||||
value_type->FriendlyName(builder_->Symbols()) + "'",
|
||||
diagnostics_.add_error("expected argument type '" +
|
||||
VectorPretty(matrix_type->rows(), elem_type) +
|
||||
"' in '" + TypeNameOf(ctor) +
|
||||
"' constructor, found '" + TypeNameOf(value) +
|
||||
"'",
|
||||
value->source());
|
||||
return false;
|
||||
}
|
||||
|
@ -1440,12 +1451,14 @@ bool Resolver::Identifier(ast::IdentifierExpression* expr) {
|
|||
// A constant is the type, but a variable is always a pointer so synthesize
|
||||
// the pointer around the variable type.
|
||||
if (var->declaration->is_const()) {
|
||||
SetType(expr, var->type);
|
||||
SetType(expr, var->type, var->type_name);
|
||||
} else if (var->type->Is<sem::Pointer>()) {
|
||||
SetType(expr, var->type);
|
||||
SetType(expr, var->type, var->type_name);
|
||||
} else {
|
||||
SetType(expr, builder_->create<sem::Pointer>(
|
||||
const_cast<sem::Type*>(var->type), var->storage_class));
|
||||
SetType(expr,
|
||||
builder_->create<sem::Pointer>(const_cast<sem::Type*>(var->type),
|
||||
var->storage_class),
|
||||
var->type_name);
|
||||
}
|
||||
|
||||
var->users.push_back(expr);
|
||||
|
@ -1962,7 +1975,7 @@ bool Resolver::VariableDeclStatement(const ast::VariableDeclStatement* stmt) {
|
|||
return true;
|
||||
}
|
||||
|
||||
const sem::Type* Resolver::TypeOf(ast::Expression* expr) {
|
||||
const sem::Type* Resolver::TypeOf(const ast::Expression* expr) {
|
||||
auto it = expr_info_.find(expr);
|
||||
if (it != expr_info_.end()) {
|
||||
return it->second.type;
|
||||
|
@ -1970,12 +1983,45 @@ const sem::Type* Resolver::TypeOf(ast::Expression* expr) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
std::string Resolver::TypeNameOf(const ast::Expression* expr) {
|
||||
auto it = expr_info_.find(expr);
|
||||
if (it != expr_info_.end()) {
|
||||
return it->second.type_name;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
const sem::Type* Resolver::TypeOf(const ast::Literal* lit) {
|
||||
if (lit->Is<ast::SintLiteral>()) {
|
||||
return builder_->create<sem::I32>();
|
||||
}
|
||||
if (lit->Is<ast::UintLiteral>()) {
|
||||
return builder_->create<sem::U32>();
|
||||
}
|
||||
if (lit->Is<ast::FloatLiteral>()) {
|
||||
return builder_->create<sem::F32>();
|
||||
}
|
||||
if (lit->Is<ast::BoolLiteral>()) {
|
||||
return builder_->create<sem::Bool>();
|
||||
}
|
||||
TINT_UNREACHABLE(diagnostics_)
|
||||
<< "Unhandled literal type: " << lit->TypeInfo().name;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Resolver::SetType(ast::Expression* expr, const sem::Type* type) {
|
||||
SetType(expr, type, type->FriendlyName(builder_->Symbols()));
|
||||
}
|
||||
|
||||
void Resolver::SetType(ast::Expression* expr,
|
||||
const sem::Type* type,
|
||||
const std::string& type_name) {
|
||||
if (expr_info_.count(expr)) {
|
||||
TINT_ICE(builder_->Diagnostics())
|
||||
<< "SetType() called twice for the same expression";
|
||||
}
|
||||
expr_info_.emplace(expr, ExpressionInfo{type, current_statement_});
|
||||
type = Canonical(type);
|
||||
expr_info_.emplace(expr, ExpressionInfo{type, type_name, current_statement_});
|
||||
}
|
||||
|
||||
void Resolver::CreateSemanticNodes() const {
|
||||
|
@ -2071,7 +2117,8 @@ void Resolver::CreateSemanticNodes() const {
|
|||
continue;
|
||||
}
|
||||
sem.Add(expr,
|
||||
builder_->create<sem::Expression>(expr, info.type, info.statement));
|
||||
builder_->create<sem::Expression>(
|
||||
const_cast<ast::Expression*>(expr), info.type, info.statement));
|
||||
}
|
||||
|
||||
// Create semantic nodes for all structs
|
||||
|
@ -2488,7 +2535,7 @@ bool Resolver::ValidateSwitch(const ast::SwitchStatement* s) {
|
|||
}
|
||||
|
||||
for (auto* selector : case_stmt->selectors()) {
|
||||
if (cond_type != selector->type()) {
|
||||
if (cond_type != TypeOf(selector)) {
|
||||
diagnostics_.add_error("v-0026",
|
||||
"the case selector values must have the same "
|
||||
"type as the selector expression.",
|
||||
|
@ -2729,9 +2776,11 @@ void Resolver::Mark(const ast::Node* node) {
|
|||
}
|
||||
|
||||
Resolver::VariableInfo::VariableInfo(const ast::Variable* decl,
|
||||
const sem::Type* ctype)
|
||||
const sem::Type* ctype,
|
||||
const std::string& tn)
|
||||
: declaration(decl),
|
||||
type(ctype),
|
||||
type_name(tn),
|
||||
storage_class(decl->declared_storage_class()) {}
|
||||
|
||||
Resolver::VariableInfo::~VariableInfo() = default;
|
||||
|
|
|
@ -96,11 +96,14 @@ class Resolver {
|
|||
/// Structure holding semantic information about a variable.
|
||||
/// Used to build the sem::Variable nodes at the end of resolving.
|
||||
struct VariableInfo {
|
||||
VariableInfo(const ast::Variable* decl, const sem::Type* type);
|
||||
VariableInfo(const ast::Variable* decl,
|
||||
const sem::Type* type,
|
||||
const std::string& type_name);
|
||||
~VariableInfo();
|
||||
|
||||
ast::Variable const* const declaration;
|
||||
sem::Type const* type;
|
||||
std::string const type_name;
|
||||
ast::StorageClass storage_class;
|
||||
std::vector<ast::IdentifierExpression*> users;
|
||||
};
|
||||
|
@ -125,6 +128,7 @@ class Resolver {
|
|||
/// Used to build the sem::Expression nodes at the end of resolving.
|
||||
struct ExpressionInfo {
|
||||
sem::Type const* type;
|
||||
std::string const type_name; // Declared type name
|
||||
sem::Statement* statement;
|
||||
};
|
||||
|
||||
|
@ -246,14 +250,16 @@ class Resolver {
|
|||
bool ValidateEntryPoint(const ast::Function* func, const FunctionInfo* info);
|
||||
bool ValidateFunction(const ast::Function* func, const FunctionInfo* info);
|
||||
bool ValidateGlobalVariable(const VariableInfo* var);
|
||||
bool ValidateMatrixConstructor(const sem::Matrix* matrix_type,
|
||||
bool ValidateMatrixConstructor(const ast::TypeConstructorExpression* ctor,
|
||||
const sem::Matrix* matrix_type,
|
||||
const ast::ExpressionList& values);
|
||||
bool ValidateParameter(const ast::Variable* param);
|
||||
bool ValidateReturn(const ast::ReturnStatement* ret);
|
||||
bool ValidateStructure(const sem::StructType* st);
|
||||
bool ValidateSwitch(const ast::SwitchStatement* s);
|
||||
bool ValidateVariable(const ast::Variable* param);
|
||||
bool ValidateVectorConstructor(const sem::Vector* vec_type,
|
||||
bool ValidateVectorConstructor(const ast::TypeConstructorExpression* ctor,
|
||||
const sem::Vector* vec_type,
|
||||
const ast::ExpressionList& values);
|
||||
|
||||
/// @returns the sem::Type for the ast::Type `ty`, building it if it
|
||||
|
@ -303,7 +309,15 @@ class Resolver {
|
|||
|
||||
/// @returns the resolved type of the ast::Expression `expr`
|
||||
/// @param expr the expression
|
||||
const sem::Type* TypeOf(ast::Expression* expr);
|
||||
const sem::Type* TypeOf(const ast::Expression* expr);
|
||||
|
||||
/// @returns the declared type name of the ast::Expression `expr`
|
||||
/// @param expr the type name
|
||||
std::string TypeNameOf(const ast::Expression* expr);
|
||||
|
||||
/// @returns the semantic type of the AST literal `lit`
|
||||
/// @param lit the literal
|
||||
const sem::Type* TypeOf(const ast::Literal* lit);
|
||||
|
||||
/// Creates a sem::Expression node with the resolved type `type`, and
|
||||
/// assigns this semantic node to the expression `expr`.
|
||||
|
@ -311,6 +325,16 @@ class Resolver {
|
|||
/// @param type the resolved type
|
||||
void SetType(ast::Expression* expr, const sem::Type* type);
|
||||
|
||||
/// Creates a sem::Expression node with the resolved type `type`, the declared
|
||||
/// type name `type_name` and assigns this semantic node to the expression
|
||||
/// `expr`.
|
||||
/// @param expr the expression
|
||||
/// @param type the resolved type
|
||||
/// @param type_name the declared type name
|
||||
void SetType(ast::Expression* expr,
|
||||
const sem::Type* type,
|
||||
const std::string& type_name);
|
||||
|
||||
/// Constructs a new BlockInfo with the given type and with #current_block_ as
|
||||
/// its parent, assigns this to #current_block_, and then calls `callback`.
|
||||
/// The original #current_block_ is restored on exit.
|
||||
|
@ -340,7 +364,7 @@ class Resolver {
|
|||
std::unordered_map<const ast::Function*, FunctionInfo*> function_to_info_;
|
||||
std::unordered_map<const ast::Variable*, VariableInfo*> variable_to_info_;
|
||||
std::unordered_map<ast::CallExpression*, FunctionCallInfo> function_calls_;
|
||||
std::unordered_map<ast::Expression*, ExpressionInfo> expr_info_;
|
||||
std::unordered_map<const ast::Expression*, ExpressionInfo> expr_info_;
|
||||
std::unordered_map<const sem::StructType*, StructInfo*> struct_info_;
|
||||
std::unordered_map<const sem::Type*, const sem::Type*> type_to_canonical_;
|
||||
std::unordered_set<const ast::Node*> marked_;
|
||||
|
|
|
@ -81,7 +81,7 @@ TEST_F(ResolverTest, Stmt_Case) {
|
|||
auto* assign = Assign(lhs, rhs);
|
||||
auto* block = Block(assign);
|
||||
ast::CaseSelectorList lit;
|
||||
lit.push_back(create<ast::SintLiteral>(ty.i32(), 3));
|
||||
lit.push_back(create<ast::SintLiteral>(3));
|
||||
auto* cse = create<ast::CaseStatement>(lit, block);
|
||||
WrapInFunction(v, cse);
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ TEST_P(InferTypeTest_FromConstructorExpression, All) {
|
|||
WrapInFunction(Decl(a), Assign(a_ident, "a"));
|
||||
|
||||
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
||||
ASSERT_EQ(TypeOf(a_ident), ty.pointer(rhs_type, sc));
|
||||
ASSERT_EQ(TypeOf(a_ident), ty.pointer(rhs_type->UnwrapAliasIfNeeded(), sc));
|
||||
}
|
||||
|
||||
static constexpr Params from_constructor_expression_cases[] = {
|
||||
|
@ -173,7 +173,7 @@ TEST_P(InferTypeTest_FromCallExpression, All) {
|
|||
WrapInFunction(Decl(a), Assign(a_ident, "a"));
|
||||
|
||||
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
||||
ASSERT_EQ(TypeOf(a_ident), ty.pointer(rhs_type, sc));
|
||||
ASSERT_EQ(TypeOf(a_ident), ty.pointer(rhs_type->UnwrapAliasIfNeeded(), sc));
|
||||
}
|
||||
static constexpr Params from_call_expression_cases[] = {
|
||||
Params{ty_bool_},
|
||||
|
|
|
@ -1693,7 +1693,7 @@ TEST_F(ResolverValidationTest, Expr_Constructor_Vector_Alias_Argument_Error) {
|
|||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(r()->error(),
|
||||
"12:34 error: type in vector constructor does not match vector "
|
||||
"type: expected 'f32', found 'u32'");
|
||||
"type: expected 'f32', found 'UnsignedInt'");
|
||||
}
|
||||
|
||||
TEST_F(ResolverValidationTest, Expr_Constructor_Vector_Alias_Argument_Success) {
|
||||
|
@ -2040,7 +2040,7 @@ TEST_F(ResolverValidationTest, Expr_MatrixConstructor_ArgumentTypeAlias_Error) {
|
|||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(r()->error(),
|
||||
"12:34 error: expected argument type 'vec2<f32>' in 'mat2x2<f32>' "
|
||||
"constructor, found 'vec2<u32>'");
|
||||
"constructor, found 'VectorUnsigned2'");
|
||||
}
|
||||
|
||||
TEST_P(MatrixConstructorTest, Expr_Constructor_ArgumentTypeAlias_Success) {
|
||||
|
|
|
@ -752,16 +752,16 @@ bool Builder::GenerateGlobalVariable(ast::Variable* var) {
|
|||
// then WGSL requires an initializer.
|
||||
if (ast::HasDecoration<ast::ConstantIdDecoration>(var->decorations())) {
|
||||
if (type_no_ac->Is<sem::F32>()) {
|
||||
ast::FloatLiteral l(ProgramID(), Source{}, type_no_ac, 0.0f);
|
||||
ast::FloatLiteral l(ProgramID(), Source{}, 0.0f);
|
||||
init_id = GenerateLiteralIfNeeded(var, &l);
|
||||
} else if (type_no_ac->Is<sem::U32>()) {
|
||||
ast::UintLiteral l(ProgramID(), Source{}, type_no_ac, 0);
|
||||
ast::UintLiteral l(ProgramID(), Source{}, 0);
|
||||
init_id = GenerateLiteralIfNeeded(var, &l);
|
||||
} else if (type_no_ac->Is<sem::I32>()) {
|
||||
ast::SintLiteral l(ProgramID(), Source{}, type_no_ac, 0);
|
||||
ast::SintLiteral l(ProgramID(), Source{}, 0);
|
||||
init_id = GenerateLiteralIfNeeded(var, &l);
|
||||
} else if (type_no_ac->Is<sem::Bool>()) {
|
||||
ast::BoolLiteral l(ProgramID(), Source{}, type_no_ac, false);
|
||||
ast::BoolLiteral l(ProgramID(), Source{}, false);
|
||||
init_id = GenerateLiteralIfNeeded(var, &l);
|
||||
} else {
|
||||
error_ = "invalid type for constant_id, must be scalar";
|
||||
|
@ -2305,8 +2305,7 @@ bool Builder::GenerateTextureIntrinsic(ast::CallExpression* call,
|
|||
op = spv::Op::OpImageQuerySizeLod;
|
||||
spirv_params.emplace_back(gen(level));
|
||||
} else {
|
||||
ast::SintLiteral i32_0(ProgramID(), Source{},
|
||||
builder_.create<sem::I32>(), 0);
|
||||
ast::SintLiteral i32_0(ProgramID(), Source{}, 0);
|
||||
op = spv::Op::OpImageQuerySizeLod;
|
||||
spirv_params.emplace_back(
|
||||
Operand::Int(GenerateLiteralIfNeeded(nullptr, &i32_0)));
|
||||
|
@ -2338,8 +2337,7 @@ bool Builder::GenerateTextureIntrinsic(ast::CallExpression* call,
|
|||
texture_type->Is<sem::StorageTexture>()) {
|
||||
op = spv::Op::OpImageQuerySize;
|
||||
} else {
|
||||
ast::SintLiteral i32_0(ProgramID(), Source{},
|
||||
builder_.create<sem::I32>(), 0);
|
||||
ast::SintLiteral i32_0(ProgramID(), Source{}, 0);
|
||||
op = spv::Op::OpImageQuerySizeLod;
|
||||
spirv_params.emplace_back(
|
||||
Operand::Int(GenerateLiteralIfNeeded(nullptr, &i32_0)));
|
||||
|
@ -2449,8 +2447,7 @@ bool Builder::GenerateTextureIntrinsic(ast::CallExpression* call,
|
|||
}
|
||||
spirv_params.emplace_back(gen_arg(Usage::kDepthRef));
|
||||
|
||||
sem::F32 f32;
|
||||
ast::FloatLiteral float_0(ProgramID(), Source{}, &f32, 0.0);
|
||||
ast::FloatLiteral float_0(ProgramID(), Source{}, 0.0);
|
||||
image_operands.emplace_back(ImageOperand{
|
||||
SpvImageOperandsLodMask,
|
||||
Operand::Int(GenerateLiteralIfNeeded(nullptr, &float_0))});
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace spirv {
|
|||
using BuilderTest = TestHelper;
|
||||
|
||||
TEST_F(BuilderTest, Literal_Bool_True) {
|
||||
auto* b_true = create<ast::BoolLiteral>(ty.bool_(), true);
|
||||
auto* b_true = create<ast::BoolLiteral>(true);
|
||||
WrapInFunction(b_true);
|
||||
|
||||
spirv::Builder& b = Build();
|
||||
|
@ -37,7 +37,7 @@ TEST_F(BuilderTest, Literal_Bool_True) {
|
|||
}
|
||||
|
||||
TEST_F(BuilderTest, Literal_Bool_False) {
|
||||
auto* b_false = create<ast::BoolLiteral>(ty.bool_(), false);
|
||||
auto* b_false = create<ast::BoolLiteral>(false);
|
||||
WrapInFunction(b_false);
|
||||
|
||||
spirv::Builder& b = Build();
|
||||
|
@ -52,8 +52,8 @@ TEST_F(BuilderTest, Literal_Bool_False) {
|
|||
}
|
||||
|
||||
TEST_F(BuilderTest, Literal_Bool_Dedup) {
|
||||
auto* b_true = create<ast::BoolLiteral>(ty.bool_(), true);
|
||||
auto* b_false = create<ast::BoolLiteral>(ty.bool_(), false);
|
||||
auto* b_true = create<ast::BoolLiteral>(true);
|
||||
auto* b_false = create<ast::BoolLiteral>(false);
|
||||
WrapInFunction(b_true, b_false);
|
||||
|
||||
spirv::Builder& b = Build();
|
||||
|
@ -72,7 +72,7 @@ TEST_F(BuilderTest, Literal_Bool_Dedup) {
|
|||
}
|
||||
|
||||
TEST_F(BuilderTest, Literal_I32) {
|
||||
auto* i = create<ast::SintLiteral>(ty.i32(), -23);
|
||||
auto* i = create<ast::SintLiteral>(-23);
|
||||
WrapInFunction(i);
|
||||
spirv::Builder& b = Build();
|
||||
|
||||
|
@ -86,8 +86,8 @@ TEST_F(BuilderTest, Literal_I32) {
|
|||
}
|
||||
|
||||
TEST_F(BuilderTest, Literal_I32_Dedup) {
|
||||
auto* i1 = create<ast::SintLiteral>(ty.i32(), -23);
|
||||
auto* i2 = create<ast::SintLiteral>(ty.i32(), -23);
|
||||
auto* i1 = create<ast::SintLiteral>(-23);
|
||||
auto* i2 = create<ast::SintLiteral>(-23);
|
||||
WrapInFunction(i1, i2);
|
||||
|
||||
spirv::Builder& b = Build();
|
||||
|
@ -102,7 +102,7 @@ TEST_F(BuilderTest, Literal_I32_Dedup) {
|
|||
}
|
||||
|
||||
TEST_F(BuilderTest, Literal_U32) {
|
||||
auto* i = create<ast::UintLiteral>(ty.u32(), 23);
|
||||
auto* i = create<ast::UintLiteral>(23);
|
||||
WrapInFunction(i);
|
||||
|
||||
spirv::Builder& b = Build();
|
||||
|
@ -117,8 +117,8 @@ TEST_F(BuilderTest, Literal_U32) {
|
|||
}
|
||||
|
||||
TEST_F(BuilderTest, Literal_U32_Dedup) {
|
||||
auto* i1 = create<ast::UintLiteral>(ty.u32(), 23);
|
||||
auto* i2 = create<ast::UintLiteral>(ty.u32(), 23);
|
||||
auto* i1 = create<ast::UintLiteral>(23);
|
||||
auto* i2 = create<ast::UintLiteral>(23);
|
||||
WrapInFunction(i1, i2);
|
||||
|
||||
spirv::Builder& b = Build();
|
||||
|
@ -133,7 +133,7 @@ TEST_F(BuilderTest, Literal_U32_Dedup) {
|
|||
}
|
||||
|
||||
TEST_F(BuilderTest, Literal_F32) {
|
||||
auto* i = create<ast::FloatLiteral>(ty.f32(), 23.245f);
|
||||
auto* i = create<ast::FloatLiteral>(23.245f);
|
||||
WrapInFunction(i);
|
||||
|
||||
spirv::Builder& b = Build();
|
||||
|
@ -148,8 +148,8 @@ TEST_F(BuilderTest, Literal_F32) {
|
|||
}
|
||||
|
||||
TEST_F(BuilderTest, Literal_F32_Dedup) {
|
||||
auto* i1 = create<ast::FloatLiteral>(ty.f32(), 23.245f);
|
||||
auto* i2 = create<ast::FloatLiteral>(ty.f32(), 23.245f);
|
||||
auto* i1 = create<ast::FloatLiteral>(23.245f);
|
||||
auto* i2 = create<ast::FloatLiteral>(23.245f);
|
||||
WrapInFunction(i1, i2);
|
||||
|
||||
spirv::Builder& b = Build();
|
||||
|
|
Loading…
Reference in New Issue