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