[spirv-writer] Generate constants
This CL updates the SPIR-V writer to generate the OpConstantTrue,
OpConstantFalse and OpConstant instructions.
Bug: tint:5
Change-Id: I660554c491e4eb569e3902fce0973fae3f27e6c0
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/17820
Reviewed-by: David Neto <dneto@google.com>
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 10605fd..dc37b6e 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -264,6 +264,7 @@
ast/else_statement_test.cc
ast/entry_point_test.cc
ast/fallthrough_statement_test.cc
+ ast/float_literal_test.cc
ast/function_test.cc
ast/identifier_expression_test.cc
ast/if_statement_test.cc
@@ -406,9 +407,10 @@
list(APPEND TINT_TEST_SRCS
writer/spirv/binary_writer_test.cc
writer/spirv/builder_test.cc
- writer/spirv/builder_type_test.cc
writer/spirv/builder_entry_point_test.cc
writer/spirv/builder_function_test.cc
+ writer/spirv/builder_literal_test.cc
+ writer/spirv/builder_type_test.cc
writer/spirv/instruction_test.cc
writer/spirv/operand_test.cc
writer/spirv/spv_dump.cc
diff --git a/src/ast/bool_literal.cc b/src/ast/bool_literal.cc
index e11e8a5..2ab78b9 100644
--- a/src/ast/bool_literal.cc
+++ b/src/ast/bool_literal.cc
@@ -17,7 +17,8 @@
namespace tint {
namespace ast {
-BoolLiteral::BoolLiteral(bool value) : value_(value) {}
+BoolLiteral::BoolLiteral(ast::type::Type* type, bool value)
+ : Literal(type), value_(value) {}
BoolLiteral::~BoolLiteral() = default;
@@ -25,5 +26,9 @@
return value_ ? "true" : "false";
}
+std::string BoolLiteral::name() const {
+ return value_ ? "__bool_true" : "__bool_false";
+}
+
} // namespace ast
} // namespace tint
diff --git a/src/ast/bool_literal.h b/src/ast/bool_literal.h
index c568f27..d1749b1 100644
--- a/src/ast/bool_literal.h
+++ b/src/ast/bool_literal.h
@@ -26,8 +26,9 @@
class BoolLiteral : public Literal {
public:
/// Constructor
+ /// @param type the type of the literal
/// @param value the bool literals value
- explicit BoolLiteral(bool value);
+ BoolLiteral(ast::type::Type* type, bool value);
~BoolLiteral() override;
/// @returns true if this is a bool literal
@@ -38,6 +39,9 @@
/// @returns true if the bool literal is false
bool IsFalse() const { return !value_; }
+ /// @returns the name for this literal. This name is unique to this value.
+ std::string name() const override;
+
/// @returns the literal as a string
std::string to_str() const override;
diff --git a/src/ast/bool_literal_test.cc b/src/ast/bool_literal_test.cc
index 190a51b..10697ee 100644
--- a/src/ast/bool_literal_test.cc
+++ b/src/ast/bool_literal_test.cc
@@ -15,6 +15,7 @@
#include "src/ast/bool_literal.h"
#include "gtest/gtest.h"
+#include "src/ast/type/bool_type.h"
namespace tint {
namespace ast {
@@ -23,21 +24,24 @@
using BoolLiteralTest = testing::Test;
TEST_F(BoolLiteralTest, True) {
- BoolLiteral b{true};
+ ast::type::BoolType bool_type;
+ BoolLiteral b{&bool_type, true};
ASSERT_TRUE(b.IsBool());
ASSERT_TRUE(b.IsTrue());
ASSERT_FALSE(b.IsFalse());
}
TEST_F(BoolLiteralTest, False) {
- BoolLiteral b{false};
+ ast::type::BoolType bool_type;
+ BoolLiteral b{&bool_type, false};
ASSERT_TRUE(b.IsBool());
ASSERT_FALSE(b.IsTrue());
ASSERT_TRUE(b.IsFalse());
}
TEST_F(BoolLiteralTest, Is) {
- BoolLiteral b{false};
+ ast::type::BoolType bool_type;
+ BoolLiteral b{&bool_type, false};
EXPECT_TRUE(b.IsBool());
EXPECT_FALSE(b.IsInt());
EXPECT_FALSE(b.IsFloat());
@@ -45,8 +49,9 @@
}
TEST_F(BoolLiteralTest, ToStr) {
- BoolLiteral t{true};
- BoolLiteral f{false};
+ ast::type::BoolType bool_type;
+ BoolLiteral t{&bool_type, true};
+ BoolLiteral f{&bool_type, false};
EXPECT_EQ(t.to_str(), "true");
EXPECT_EQ(f.to_str(), "false");
diff --git a/src/ast/case_statement_test.cc b/src/ast/case_statement_test.cc
index dc1f90b..27b94c5 100644
--- a/src/ast/case_statement_test.cc
+++ b/src/ast/case_statement_test.cc
@@ -18,6 +18,7 @@
#include "src/ast/bool_literal.h"
#include "src/ast/if_statement.h"
#include "src/ast/nop_statement.h"
+#include "src/ast/type/bool_type.h"
namespace tint {
namespace ast {
@@ -26,7 +27,8 @@
using CaseStatementTest = testing::Test;
TEST_F(CaseStatementTest, Creation) {
- auto b = std::make_unique<BoolLiteral>(true);
+ ast::type::BoolType bool_type;
+ auto b = std::make_unique<BoolLiteral>(&bool_type, true);
std::vector<std::unique_ptr<Statement>> stmts;
stmts.push_back(std::make_unique<NopStatement>());
@@ -40,7 +42,8 @@
}
TEST_F(CaseStatementTest, Creation_WithSource) {
- auto b = std::make_unique<BoolLiteral>(true);
+ ast::type::BoolType bool_type;
+ auto b = std::make_unique<BoolLiteral>(&bool_type, true);
std::vector<std::unique_ptr<Statement>> stmts;
stmts.push_back(std::make_unique<NopStatement>());
@@ -60,7 +63,8 @@
}
TEST_F(CaseStatementTest, IsDefault_WithCondition) {
- auto b = std::make_unique<BoolLiteral>(true);
+ ast::type::BoolType bool_type;
+ auto b = std::make_unique<BoolLiteral>(&bool_type, true);
CaseStatement c;
c.set_condition(std::move(b));
EXPECT_FALSE(c.IsDefault());
@@ -77,7 +81,8 @@
}
TEST_F(CaseStatementTest, IsValid_NullBodyStatement) {
- auto b = std::make_unique<BoolLiteral>(true);
+ ast::type::BoolType bool_type;
+ auto b = std::make_unique<BoolLiteral>(&bool_type, true);
std::vector<std::unique_ptr<Statement>> stmts;
stmts.push_back(std::make_unique<NopStatement>());
stmts.push_back(nullptr);
@@ -87,7 +92,8 @@
}
TEST_F(CaseStatementTest, IsValid_InvalidBodyStatement) {
- auto b = std::make_unique<BoolLiteral>(true);
+ ast::type::BoolType bool_type;
+ auto b = std::make_unique<BoolLiteral>(&bool_type, true);
std::vector<std::unique_ptr<Statement>> stmts;
stmts.push_back(std::make_unique<IfStatement>());
@@ -96,7 +102,8 @@
}
TEST_F(CaseStatementTest, ToStr_WithCondition) {
- auto b = std::make_unique<BoolLiteral>(true);
+ ast::type::BoolType bool_type;
+ auto b = std::make_unique<BoolLiteral>(&bool_type, true);
std::vector<std::unique_ptr<Statement>> stmts;
stmts.push_back(std::make_unique<NopStatement>());
CaseStatement c(std::move(b), std::move(stmts));
diff --git a/src/ast/const_initializer_expression_test.cc b/src/ast/const_initializer_expression_test.cc
index a823a33..243df54 100644
--- a/src/ast/const_initializer_expression_test.cc
+++ b/src/ast/const_initializer_expression_test.cc
@@ -16,6 +16,7 @@
#include "gtest/gtest.h"
#include "src/ast/bool_literal.h"
+#include "src/ast/type/bool_type.h"
namespace tint {
namespace ast {
@@ -24,14 +25,16 @@
using ConstInitializerExpressionTest = testing::Test;
TEST_F(ConstInitializerExpressionTest, Creation) {
- auto b = std::make_unique<BoolLiteral>(true);
+ ast::type::BoolType bool_type;
+ auto b = std::make_unique<BoolLiteral>(&bool_type, true);
auto b_ptr = b.get();
ConstInitializerExpression c(std::move(b));
EXPECT_EQ(c.literal(), b_ptr);
}
TEST_F(ConstInitializerExpressionTest, Creation_WithSource) {
- auto b = std::make_unique<BoolLiteral>(true);
+ ast::type::BoolType bool_type;
+ auto b = std::make_unique<BoolLiteral>(&bool_type, true);
ConstInitializerExpression c(Source{20, 2}, std::move(b));
auto src = c.source();
EXPECT_EQ(src.line, 20);
@@ -39,7 +42,8 @@
}
TEST_F(ConstInitializerExpressionTest, IsValid) {
- auto b = std::make_unique<BoolLiteral>(true);
+ ast::type::BoolType bool_type;
+ auto b = std::make_unique<BoolLiteral>(&bool_type, true);
ConstInitializerExpression c(std::move(b));
EXPECT_TRUE(c.IsValid());
}
@@ -50,7 +54,8 @@
}
TEST_F(ConstInitializerExpressionTest, ToStr) {
- auto b = std::make_unique<BoolLiteral>(true);
+ ast::type::BoolType bool_type;
+ auto b = std::make_unique<BoolLiteral>(&bool_type, true);
ConstInitializerExpression c(std::move(b));
std::ostringstream out;
c.to_str(out, 2);
diff --git a/src/ast/else_statement_test.cc b/src/ast/else_statement_test.cc
index 9675e0b..3e1aadc 100644
--- a/src/ast/else_statement_test.cc
+++ b/src/ast/else_statement_test.cc
@@ -19,6 +19,7 @@
#include "src/ast/const_initializer_expression.h"
#include "src/ast/if_statement.h"
#include "src/ast/nop_statement.h"
+#include "src/ast/type/bool_type.h"
namespace tint {
namespace ast {
@@ -27,8 +28,9 @@
using ElseStatementTest = testing::Test;
TEST_F(ElseStatementTest, Creation) {
+ ast::type::BoolType bool_type;
auto cond = std::make_unique<ConstInitializerExpression>(
- std::make_unique<BoolLiteral>(true));
+ std::make_unique<BoolLiteral>(&bool_type, true));
std::vector<std::unique_ptr<Statement>> body;
body.push_back(std::make_unique<NopStatement>());
@@ -54,8 +56,9 @@
}
TEST_F(ElseStatementTest, HasCondition) {
+ ast::type::BoolType bool_type;
auto cond = std::make_unique<ConstInitializerExpression>(
- std::make_unique<BoolLiteral>(true));
+ std::make_unique<BoolLiteral>(&bool_type, true));
ElseStatement e(std::move(cond), {});
EXPECT_TRUE(e.HasCondition());
}
@@ -102,8 +105,9 @@
}
TEST_F(ElseStatementTest, ToStr) {
+ ast::type::BoolType bool_type;
auto cond = std::make_unique<ConstInitializerExpression>(
- std::make_unique<BoolLiteral>(true));
+ std::make_unique<BoolLiteral>(&bool_type, true));
std::vector<std::unique_ptr<Statement>> body;
body.push_back(std::make_unique<NopStatement>());
diff --git a/src/ast/float_literal.cc b/src/ast/float_literal.cc
index 1d8b40f..467a7bd 100644
--- a/src/ast/float_literal.cc
+++ b/src/ast/float_literal.cc
@@ -14,10 +14,13 @@
#include "src/ast/float_literal.h"
+#include <sstream>
+
namespace tint {
namespace ast {
-FloatLiteral::FloatLiteral(float value) : value_(value) {}
+FloatLiteral::FloatLiteral(ast::type::Type* type, float value)
+ : Literal(type), value_(value) {}
FloatLiteral::~FloatLiteral() = default;
@@ -25,5 +28,13 @@
return std::to_string(value_);
}
+std::string FloatLiteral::name() const {
+ std::ostringstream out;
+ out.flags(out.flags() | std::ios_base::showpoint);
+ out.precision(std::numeric_limits<float>::max_digits10);
+ out << "__float" << value_;
+ return out.str();
+}
+
} // namespace ast
} // namespace tint
diff --git a/src/ast/float_literal.h b/src/ast/float_literal.h
index baf088a..370a553 100644
--- a/src/ast/float_literal.h
+++ b/src/ast/float_literal.h
@@ -26,8 +26,9 @@
class FloatLiteral : public Literal {
public:
/// Constructor
+ /// @param type the type of the literal
/// @param value the float literals value
- explicit FloatLiteral(float value);
+ FloatLiteral(ast::type::Type* type, float value);
~FloatLiteral() override;
/// @returns true if this is a float literal
@@ -36,6 +37,9 @@
/// @returns the float literal value
float value() const { return value_; }
+ /// @returns the name for this literal. This name is unique to this value.
+ std::string name() const override;
+
/// @returns the literal as a string
std::string to_str() const override;
diff --git a/src/ast/float_literal_test.cc b/src/ast/float_literal_test.cc
index e9b3f4e..6f11018 100644
--- a/src/ast/float_literal_test.cc
+++ b/src/ast/float_literal_test.cc
@@ -15,6 +15,7 @@
#include "src/ast/float_literal.h"
#include "gtest/gtest.h"
+#include "src/ast/type/f32_type.h"
namespace tint {
namespace ast {
@@ -23,13 +24,15 @@
using FloatLiteralTest = testing::Test;
TEST_F(FloatLiteralTest, Value) {
- FloatLiteral f{47.2};
+ ast::type::F32Type f32;
+ FloatLiteral f{&f32, 47.2f};
ASSERT_TRUE(f.IsFloat());
- EXPECT_EQ(f.value(), 47.2);
+ EXPECT_EQ(f.value(), 47.2f);
}
TEST_F(FloatLiteralTest, Is) {
- FloatLiteral f{42};
+ ast::type::F32Type f32;
+ FloatLiteral f{&f32, 42.f};
EXPECT_FALSE(f.IsBool());
EXPECT_FALSE(f.IsInt());
EXPECT_TRUE(f.IsFloat());
@@ -37,9 +40,16 @@
}
TEST_F(FloatLiteralTest, ToStr) {
- FloatLiteral f{42.1};
+ ast::type::F32Type f32;
+ FloatLiteral f{&f32, 42.1f};
- EXPECT_EQ(f.to_str(), "42.1");
+ EXPECT_EQ(f.to_str(), "42.099998");
+}
+
+TEST_F(FloatLiteralTest, ToName) {
+ ast::type::F32Type f32;
+ FloatLiteral f{&f32, 42.1f};
+ EXPECT_EQ(f.name(), "__float42.0999985");
}
} // namespace
diff --git a/src/ast/int_literal.cc b/src/ast/int_literal.cc
index 99e476c..1fdf84f 100644
--- a/src/ast/int_literal.cc
+++ b/src/ast/int_literal.cc
@@ -17,7 +17,8 @@
namespace tint {
namespace ast {
-IntLiteral::IntLiteral(int32_t value) : value_(value) {}
+IntLiteral::IntLiteral(ast::type::Type* type, int32_t value)
+ : Literal(type), value_(value) {}
IntLiteral::~IntLiteral() = default;
@@ -25,5 +26,9 @@
return std::to_string(value_);
}
+std::string IntLiteral::name() const {
+ return "__int" + std::to_string(value_);
+}
+
} // namespace ast
} // namespace tint
diff --git a/src/ast/int_literal.h b/src/ast/int_literal.h
index b96e3b9..ccbd89c 100644
--- a/src/ast/int_literal.h
+++ b/src/ast/int_literal.h
@@ -26,8 +26,9 @@
class IntLiteral : public Literal {
public:
/// Constructor
+ /// @param type the type
/// @param value the int literals value
- explicit IntLiteral(int32_t value);
+ IntLiteral(ast::type::Type* type, int32_t value);
~IntLiteral() override;
/// @returns true if this is a int literal
@@ -36,6 +37,9 @@
/// @returns the int literal value
int32_t value() const { return value_; }
+ /// @returns the name for this literal. This name is unique to this value.
+ std::string name() const override;
+
/// @returns the literal as a string
std::string to_str() const override;
diff --git a/src/ast/int_literal_test.cc b/src/ast/int_literal_test.cc
index 8d35d5d..42ca665 100644
--- a/src/ast/int_literal_test.cc
+++ b/src/ast/int_literal_test.cc
@@ -15,6 +15,7 @@
#include "src/ast/int_literal.h"
#include "gtest/gtest.h"
+#include "src/ast/type/i32_type.h"
namespace tint {
namespace ast {
@@ -23,13 +24,15 @@
using IntLiteralTest = testing::Test;
TEST_F(IntLiteralTest, Value) {
- IntLiteral i{47};
+ ast::type::I32Type i32;
+ IntLiteral i{&i32, 47};
ASSERT_TRUE(i.IsInt());
EXPECT_EQ(i.value(), 47);
}
TEST_F(IntLiteralTest, Is) {
- IntLiteral i{42};
+ ast::type::I32Type i32;
+ IntLiteral i{&i32, 42};
EXPECT_FALSE(i.IsBool());
EXPECT_TRUE(i.IsInt());
EXPECT_FALSE(i.IsFloat());
@@ -37,7 +40,8 @@
}
TEST_F(IntLiteralTest, ToStr) {
- IntLiteral i{-42};
+ ast::type::I32Type i32;
+ IntLiteral i{&i32, -42};
EXPECT_EQ(i.to_str(), "-42");
}
diff --git a/src/ast/literal.cc b/src/ast/literal.cc
index 055d33d..3759274 100644
--- a/src/ast/literal.cc
+++ b/src/ast/literal.cc
@@ -24,7 +24,7 @@
namespace tint {
namespace ast {
-Literal::Literal() = default;
+Literal::Literal(ast::type::Type* type) : type_(type) {}
Literal::~Literal() = default;
diff --git a/src/ast/literal.h b/src/ast/literal.h
index af8b831..9f91478 100644
--- a/src/ast/literal.h
+++ b/src/ast/literal.h
@@ -17,6 +17,8 @@
#include <string>
+#include "src/ast/type/type.h"
+
namespace tint {
namespace ast {
@@ -48,12 +50,21 @@
/// @returns the literal as a unsigned int literal
UintLiteral* AsUint();
+ /// @returns the type of the literal
+ ast::type::Type* type() const { return type_; }
+
/// @returns the literal as a string
virtual std::string to_str() const = 0;
+ /// @returns the name for this literal. This name is unique to this value.
+ virtual std::string name() const = 0;
+
protected:
/// Constructor
- Literal();
+ Literal(ast::type::Type* type);
+
+ private:
+ ast::type::Type* type_ = nullptr;
};
} // namespace ast
diff --git a/src/ast/switch_statement_test.cc b/src/ast/switch_statement_test.cc
index 1f065ec..4bb71f5 100644
--- a/src/ast/switch_statement_test.cc
+++ b/src/ast/switch_statement_test.cc
@@ -20,6 +20,7 @@
#include "src/ast/bool_literal.h"
#include "src/ast/case_statement.h"
#include "src/ast/identifier_expression.h"
+#include "src/ast/type/bool_type.h"
namespace tint {
namespace ast {
@@ -28,7 +29,8 @@
using SwitchStatementTest = testing::Test;
TEST_F(SwitchStatementTest, Creation) {
- auto lit = std::make_unique<BoolLiteral>(true);
+ ast::type::BoolType bool_type;
+ auto lit = std::make_unique<BoolLiteral>(&bool_type, true);
auto ident = std::make_unique<IdentifierExpression>("ident");
std::vector<std::unique_ptr<CaseStatement>> body;
body.push_back(std::make_unique<CaseStatement>(
@@ -59,7 +61,8 @@
}
TEST_F(SwitchStatementTest, IsValid) {
- auto lit = std::make_unique<BoolLiteral>(true);
+ ast::type::BoolType bool_type;
+ auto lit = std::make_unique<BoolLiteral>(&bool_type, true);
auto ident = std::make_unique<IdentifierExpression>("ident");
std::vector<std::unique_ptr<CaseStatement>> body;
body.push_back(std::make_unique<CaseStatement>(
@@ -70,7 +73,8 @@
}
TEST_F(SwitchStatementTest, IsValid_Null_Condition) {
- auto lit = std::make_unique<BoolLiteral>(true);
+ ast::type::BoolType bool_type;
+ auto lit = std::make_unique<BoolLiteral>(&bool_type, true);
std::vector<std::unique_ptr<CaseStatement>> body;
body.push_back(std::make_unique<CaseStatement>(
std::move(lit), std::vector<std::unique_ptr<Statement>>()));
@@ -81,7 +85,8 @@
}
TEST_F(SwitchStatementTest, IsValid_Invalid_Condition) {
- auto lit = std::make_unique<BoolLiteral>(true);
+ ast::type::BoolType bool_type;
+ auto lit = std::make_unique<BoolLiteral>(&bool_type, true);
auto ident = std::make_unique<IdentifierExpression>("");
std::vector<std::unique_ptr<CaseStatement>> body;
body.push_back(std::make_unique<CaseStatement>(
@@ -92,7 +97,8 @@
}
TEST_F(SwitchStatementTest, IsValid_Null_BodyStatement) {
- auto lit = std::make_unique<BoolLiteral>(true);
+ ast::type::BoolType bool_type;
+ auto lit = std::make_unique<BoolLiteral>(&bool_type, true);
auto ident = std::make_unique<IdentifierExpression>("ident");
std::vector<std::unique_ptr<CaseStatement>> body;
body.push_back(std::make_unique<CaseStatement>(
@@ -132,7 +138,8 @@
}
TEST_F(SwitchStatementTest, ToStr) {
- auto lit = std::make_unique<BoolLiteral>(true);
+ ast::type::BoolType bool_type;
+ auto lit = std::make_unique<BoolLiteral>(&bool_type, true);
auto ident = std::make_unique<IdentifierExpression>("ident");
std::vector<std::unique_ptr<CaseStatement>> body;
body.push_back(std::make_unique<CaseStatement>(
diff --git a/src/ast/uint_literal.cc b/src/ast/uint_literal.cc
index 273f9ca..562d47a 100644
--- a/src/ast/uint_literal.cc
+++ b/src/ast/uint_literal.cc
@@ -17,7 +17,8 @@
namespace tint {
namespace ast {
-UintLiteral::UintLiteral(uint32_t value) : value_(value) {}
+UintLiteral::UintLiteral(ast::type::Type* type, uint32_t value)
+ : Literal(type), value_(value) {}
UintLiteral::~UintLiteral() = default;
@@ -25,5 +26,9 @@
return std::to_string(value_);
}
+std::string UintLiteral::name() const {
+ return "__uint" + std::to_string(value_);
+}
+
} // namespace ast
} // namespace tint
diff --git a/src/ast/uint_literal.h b/src/ast/uint_literal.h
index 0b2394e..c9e7731 100644
--- a/src/ast/uint_literal.h
+++ b/src/ast/uint_literal.h
@@ -26,8 +26,9 @@
class UintLiteral : public Literal {
public:
/// Constructor
+ /// @param type the type of the literal
/// @param value the uint literals value
- explicit UintLiteral(uint32_t value);
+ UintLiteral(ast::type::Type* type, uint32_t value);
~UintLiteral() override;
/// @returns true if this is a uint literal
@@ -36,6 +37,9 @@
/// @returns the uint literal value
uint32_t value() const { return value_; }
+ /// @returns the name for this literal. This name is unique to this value.
+ std::string name() const override;
+
/// @returns the literal as a string
std::string to_str() const override;
diff --git a/src/ast/uint_literal_test.cc b/src/ast/uint_literal_test.cc
index 137cded..d19811c 100644
--- a/src/ast/uint_literal_test.cc
+++ b/src/ast/uint_literal_test.cc
@@ -15,6 +15,7 @@
#include "src/ast/uint_literal.h"
#include "gtest/gtest.h"
+#include "src/ast/type/u32_type.h"
namespace tint {
namespace ast {
@@ -23,13 +24,15 @@
using UintLiteralTest = testing::Test;
TEST_F(UintLiteralTest, Value) {
- UintLiteral u{47};
+ ast::type::U32Type u32;
+ UintLiteral u{&u32, 47};
ASSERT_TRUE(u.IsUint());
EXPECT_EQ(u.value(), 47);
}
TEST_F(UintLiteralTest, Is) {
- UintLiteral u{42};
+ ast::type::U32Type u32;
+ UintLiteral u{&u32, 42};
EXPECT_FALSE(u.IsBool());
EXPECT_FALSE(u.IsInt());
EXPECT_FALSE(u.IsFloat());
@@ -37,7 +40,8 @@
}
TEST_F(UintLiteralTest, ToStr) {
- UintLiteral i{42};
+ ast::type::U32Type u32;
+ UintLiteral i{&u32, 42};
EXPECT_EQ(i.to_str(), "42");
}
diff --git a/src/reader/wgsl/parser_impl.cc b/src/reader/wgsl/parser_impl.cc
index 1b71bea..e2db44d 100644
--- a/src/reader/wgsl/parser_impl.cc
+++ b/src/reader/wgsl/parser_impl.cc
@@ -2097,23 +2097,44 @@
auto t = peek();
if (t.IsTrue()) {
next(); // Consume the peek
- return std::make_unique<ast::BoolLiteral>(true);
+
+ auto type = ctx_.type_mgr->Get(std::make_unique<ast::type::BoolType>());
+ if (!type) {
+ return nullptr;
+ }
+ return std::make_unique<ast::BoolLiteral>(type, true);
}
if (t.IsFalse()) {
next(); // Consume the peek
- return std::make_unique<ast::BoolLiteral>(false);
+ auto type = ctx_.type_mgr->Get(std::make_unique<ast::type::BoolType>());
+ if (!type) {
+ return nullptr;
+ }
+ return std::make_unique<ast::BoolLiteral>(type, false);
}
if (t.IsIntLiteral()) {
next(); // Consume the peek
- return std::make_unique<ast::IntLiteral>(t.to_i32());
+ auto type = ctx_.type_mgr->Get(std::make_unique<ast::type::I32Type>());
+ if (!type) {
+ return nullptr;
+ }
+ return std::make_unique<ast::IntLiteral>(type, t.to_i32());
}
if (t.IsUintLiteral()) {
next(); // Consume the peek
- return std::make_unique<ast::UintLiteral>(t.to_u32());
+ auto type = ctx_.type_mgr->Get(std::make_unique<ast::type::U32Type>());
+ if (!type) {
+ return nullptr;
+ }
+ return std::make_unique<ast::UintLiteral>(type, t.to_u32());
}
if (t.IsFloatLiteral()) {
next(); // Consume the peek
- return std::make_unique<ast::FloatLiteral>(t.to_f32());
+ auto type = ctx_.type_mgr->Get(std::make_unique<ast::type::F32Type>());
+ if (!type) {
+ return nullptr;
+ }
+ return std::make_unique<ast::FloatLiteral>(type, t.to_f32());
}
return nullptr;
}
diff --git a/src/writer/spirv/builder.cc b/src/writer/spirv/builder.cc
index f9c1584..bca5b92 100644
--- a/src/writer/spirv/builder.cc
+++ b/src/writer/spirv/builder.cc
@@ -1,5 +1,4 @@
-// Copyright 2020 The Tint Authors.
-//
+// Copyright 2020 The Tint Authors. //
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
@@ -17,12 +16,16 @@
#include <utility>
#include "spirv/unified1/spirv.h"
+#include "src/ast/bool_literal.h"
+#include "src/ast/float_literal.h"
+#include "src/ast/int_literal.h"
#include "src/ast/struct.h"
#include "src/ast/struct_member.h"
#include "src/ast/struct_member_offset_decoration.h"
#include "src/ast/type/matrix_type.h"
#include "src/ast/type/struct_type.h"
#include "src/ast/type/vector_type.h"
+#include "src/ast/uint_literal.h"
namespace tint {
namespace writer {
@@ -212,6 +215,44 @@
import_name_to_id_[imp->name()] = id;
}
+uint32_t Builder::GenerateLiteralIfNeeded(ast::Literal* lit) {
+ auto type_id = GenerateTypeIfNeeded(lit->type());
+ if (type_id == 0) {
+ return 0;
+ }
+ auto name = lit->name();
+ auto val = const_to_id_.find(name);
+ if (val != const_to_id_.end()) {
+ return val->second;
+ }
+
+ auto result = result_op();
+ auto result_id = result.to_i();
+
+ if (lit->IsBool()) {
+ if (lit->AsBool()->IsTrue()) {
+ push_type(spv::Op::OpConstantTrue, {Operand::Int(type_id), result});
+ } else {
+ push_type(spv::Op::OpConstantFalse, {Operand::Int(type_id), result});
+ }
+ } else if (lit->IsInt()) {
+ push_type(spv::Op::OpConstant, {Operand::Int(type_id), result,
+ Operand::Int(lit->AsInt()->value())});
+ } else if (lit->IsUint()) {
+ push_type(spv::Op::OpConstant, {Operand::Int(type_id), result,
+ Operand::Int(lit->AsUint()->value())});
+ } else if (lit->IsFloat()) {
+ push_type(spv::Op::OpConstant, {Operand::Int(type_id), result,
+ Operand::Float(lit->AsFloat()->value())});
+ } else {
+ error_ = "unknown literal type";
+ return 0;
+ }
+
+ const_to_id_[name] = result_id;
+ return result_id;
+}
+
uint32_t Builder::GenerateTypeIfNeeded(ast::type::Type* type) {
if (type->IsAlias()) {
return GenerateTypeIfNeeded(type->AsAlias()->type());
diff --git a/src/writer/spirv/builder.h b/src/writer/spirv/builder.h
index b075fa9..3045fe2 100644
--- a/src/writer/spirv/builder.h
+++ b/src/writer/spirv/builder.h
@@ -20,6 +20,7 @@
#include <unordered_map>
#include <vector>
+#include "src/ast/literal.h"
#include "src/ast/module.h"
#include "src/ast/struct_member.h"
#include "src/writer/spirv/instruction.h"
@@ -136,6 +137,10 @@
/// Generates an import instruction
/// @param imp the import
void GenerateImport(ast::Import* imp);
+ /// Generates a literal constant if needed
+ /// @param lit the literal to generate
+ /// @returns the ID on success or 0 on failure
+ uint32_t GenerateLiteralIfNeeded(ast::Literal* lit);
/// Generates a type if not already created
/// @param type the type to create
/// @returns the ID to use for the given type. Returns 0 on unknown type.
@@ -181,6 +186,7 @@
std::unordered_map<std::string, uint32_t> import_name_to_id_;
std::unordered_map<std::string, uint32_t> func_name_to_id_;
std::unordered_map<std::string, uint32_t> type_name_to_id_;
+ std::unordered_map<std::string, uint32_t> const_to_id_;
};
} // namespace spirv
diff --git a/src/writer/spirv/builder_literal_test.cc b/src/writer/spirv/builder_literal_test.cc
new file mode 100644
index 0000000..432ac16
--- /dev/null
+++ b/src/writer/spirv/builder_literal_test.cc
@@ -0,0 +1,172 @@
+// Copyright 2020 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "gtest/gtest.h"
+#include "spirv/unified1/spirv.h"
+#include "src/ast/bool_literal.h"
+#include "src/ast/float_literal.h"
+#include "src/ast/int_literal.h"
+#include "src/ast/literal.h"
+#include "src/ast/type/bool_type.h"
+#include "src/ast/type/f32_type.h"
+#include "src/ast/type/i32_type.h"
+#include "src/ast/type/u32_type.h"
+#include "src/ast/uint_literal.h"
+#include "src/writer/spirv/builder.h"
+#include "src/writer/spirv/spv_dump.h"
+
+namespace tint {
+namespace writer {
+namespace spirv {
+
+using BuilderTest = testing::Test;
+
+TEST_F(BuilderTest, Literal_Bool_True) {
+ ast::type::BoolType bool_type;
+ ast::BoolLiteral b_true(&bool_type, true);
+
+ Builder b;
+ auto id = b.GenerateLiteralIfNeeded(&b_true);
+ ASSERT_FALSE(b.has_error()) << b.error();
+ EXPECT_EQ(2, id);
+
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%1 = OpTypeBool
+%2 = OpConstantTrue %1
+)");
+}
+
+TEST_F(BuilderTest, Literal_Bool_False) {
+ ast::type::BoolType bool_type;
+ ast::BoolLiteral b_false(&bool_type, false);
+
+ Builder b;
+ auto id = b.GenerateLiteralIfNeeded(&b_false);
+ ASSERT_FALSE(b.has_error()) << b.error();
+ EXPECT_EQ(2, id);
+
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%1 = OpTypeBool
+%2 = OpConstantFalse %1
+)");
+}
+
+TEST_F(BuilderTest, Literal_Bool_Dedup) {
+ ast::type::BoolType bool_type;
+ ast::BoolLiteral b_true(&bool_type, true);
+ ast::BoolLiteral b_false(&bool_type, false);
+
+ Builder b;
+ ASSERT_NE(b.GenerateLiteralIfNeeded(&b_true), 0);
+ ASSERT_FALSE(b.has_error()) << b.error();
+ ASSERT_NE(b.GenerateLiteralIfNeeded(&b_false), 0);
+ ASSERT_FALSE(b.has_error()) << b.error();
+ ASSERT_NE(b.GenerateLiteralIfNeeded(&b_true), 0);
+ ASSERT_FALSE(b.has_error()) << b.error();
+
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%1 = OpTypeBool
+%2 = OpConstantTrue %1
+%3 = OpConstantFalse %1
+)");
+}
+
+TEST_F(BuilderTest, Literal_I32) {
+ ast::type::I32Type i32;
+ ast::IntLiteral i(&i32, -23);
+
+ Builder b;
+ auto id = b.GenerateLiteralIfNeeded(&i);
+ ASSERT_FALSE(b.has_error()) << b.error();
+ EXPECT_EQ(2, id);
+
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%1 = OpTypeInt 32 1
+%2 = OpConstant %1 -23
+)");
+}
+
+TEST_F(BuilderTest, Literal_I32_Dedup) {
+ ast::type::I32Type i32;
+ ast::IntLiteral i1(&i32, -23);
+ ast::IntLiteral i2(&i32, -23);
+
+ Builder b;
+ ASSERT_NE(b.GenerateLiteralIfNeeded(&i1), 0);
+ ASSERT_NE(b.GenerateLiteralIfNeeded(&i2), 0);
+ ASSERT_FALSE(b.has_error()) << b.error();
+
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%1 = OpTypeInt 32 1
+%2 = OpConstant %1 -23
+)");
+}
+
+TEST_F(BuilderTest, Literal_U32) {
+ ast::type::U32Type u32;
+ ast::UintLiteral i(&u32, 23);
+
+ Builder b;
+ auto id = b.GenerateLiteralIfNeeded(&i);
+ ASSERT_FALSE(b.has_error()) << b.error();
+ EXPECT_EQ(2, id);
+
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%1 = OpTypeInt 32 0
+%2 = OpConstant %1 23
+)");
+}
+
+TEST_F(BuilderTest, Literal_U32_Dedup) {
+ ast::type::U32Type u32;
+ ast::UintLiteral i1(&u32, 23);
+ ast::UintLiteral i2(&u32, 23);
+
+ Builder b;
+ ASSERT_NE(b.GenerateLiteralIfNeeded(&i1), 0);
+ ASSERT_NE(b.GenerateLiteralIfNeeded(&i2), 0);
+ ASSERT_FALSE(b.has_error()) << b.error();
+
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%1 = OpTypeInt 32 0
+%2 = OpConstant %1 23
+)");
+}
+
+TEST_F(BuilderTest, Literal_F32) {
+ ast::type::F32Type f32;
+ ast::FloatLiteral i(&f32, 23.245f);
+
+ Builder b;
+ auto id = b.GenerateLiteralIfNeeded(&i);
+ ASSERT_FALSE(b.has_error()) << b.error();
+ EXPECT_EQ(2, id);
+
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%1 = OpTypeFloat 32
+%2 = OpConstant %1 23.2450008
+)");
+}
+
+TEST_F(BuilderTest, Literal_F32_Dedup) {
+ ast::type::F32Type f32;
+ ast::FloatLiteral i1(&f32, 23.245f);
+ ast::FloatLiteral i2(&f32, 23.245f);
+
+ Builder b;
+ ASSERT_NE(b.GenerateLiteralIfNeeded(&i1), 0);
+ ASSERT_NE(b.GenerateLiteralIfNeeded(&i2), 0);
+ ASSERT_FALSE(b.has_error()) << b.error();
+
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%1 = OpTypeFloat 32
+%2 = OpConstant %1 23.2450008
+)");
+}
+
+} // namespace spirv
+} // namespace writer
+} // namespace tint
+;
diff --git a/src/writer/wgsl/generator_impl_array_accessor_test.cc b/src/writer/wgsl/generator_impl_array_accessor_test.cc
index 51f7c6c..4fd4c9d 100644
--- a/src/writer/wgsl/generator_impl_array_accessor_test.cc
+++ b/src/writer/wgsl/generator_impl_array_accessor_test.cc
@@ -19,6 +19,7 @@
#include "src/ast/const_initializer_expression.h"
#include "src/ast/identifier_expression.h"
#include "src/ast/int_literal.h"
+#include "src/ast/type/i32_type.h"
#include "src/writer/wgsl/generator_impl.h"
namespace tint {
@@ -29,7 +30,8 @@
using GeneratorImplTest = testing::Test;
TEST_F(GeneratorImplTest, EmitExpression_ArrayAccessor) {
- auto lit = std::make_unique<ast::IntLiteral>(5);
+ ast::type::I32Type i32;
+ auto lit = std::make_unique<ast::IntLiteral>(&i32, 5);
auto idx = std::make_unique<ast::ConstInitializerExpression>(std::move(lit));
auto ary = std::make_unique<ast::IdentifierExpression>("ary");
diff --git a/src/writer/wgsl/generator_impl_case_test.cc b/src/writer/wgsl/generator_impl_case_test.cc
index 06b6683..d23c785 100644
--- a/src/writer/wgsl/generator_impl_case_test.cc
+++ b/src/writer/wgsl/generator_impl_case_test.cc
@@ -20,6 +20,7 @@
#include "src/ast/case_statement.h"
#include "src/ast/identifier_expression.h"
#include "src/ast/int_literal.h"
+#include "src/ast/type/i32_type.h"
#include "src/writer/wgsl/generator_impl.h"
namespace tint {
@@ -30,7 +31,8 @@
using GeneratorImplTest = testing::Test;
TEST_F(GeneratorImplTest, Emit_Case) {
- auto cond = std::make_unique<ast::IntLiteral>(5);
+ ast::type::I32Type i32;
+ auto cond = std::make_unique<ast::IntLiteral>(&i32, 5);
std::vector<std::unique_ptr<ast::Statement>> body;
body.push_back(std::make_unique<ast::BreakStatement>());
diff --git a/src/writer/wgsl/generator_impl_initializer_test.cc b/src/writer/wgsl/generator_impl_initializer_test.cc
index 6a6876f..44ae88a 100644
--- a/src/writer/wgsl/generator_impl_initializer_test.cc
+++ b/src/writer/wgsl/generator_impl_initializer_test.cc
@@ -38,7 +38,8 @@
using GeneratorImplTest = testing::Test;
TEST_F(GeneratorImplTest, EmitInitializer_Bool) {
- auto lit = std::make_unique<ast::BoolLiteral>(false);
+ ast::type::BoolType bool_type;
+ auto lit = std::make_unique<ast::BoolLiteral>(&bool_type, false);
ast::ConstInitializerExpression expr(std::move(lit));
GeneratorImpl g;
@@ -47,7 +48,8 @@
}
TEST_F(GeneratorImplTest, EmitInitializer_Int) {
- auto lit = std::make_unique<ast::IntLiteral>(-12345);
+ ast::type::I32Type i32;
+ auto lit = std::make_unique<ast::IntLiteral>(&i32, -12345);
ast::ConstInitializerExpression expr(std::move(lit));
GeneratorImpl g;
@@ -56,7 +58,8 @@
}
TEST_F(GeneratorImplTest, EmitInitializer_UInt) {
- auto lit = std::make_unique<ast::UintLiteral>(56779);
+ ast::type::U32Type u32;
+ auto lit = std::make_unique<ast::UintLiteral>(&u32, 56779);
ast::ConstInitializerExpression expr(std::move(lit));
GeneratorImpl g;
@@ -65,7 +68,8 @@
}
TEST_F(GeneratorImplTest, EmitInitializer_Float) {
- auto lit = std::make_unique<ast::FloatLiteral>(1.5e27);
+ ast::type::F32Type f32;
+ auto lit = std::make_unique<ast::FloatLiteral>(&f32, 1.5e27);
ast::ConstInitializerExpression expr(std::move(lit));
GeneratorImpl g;
@@ -76,7 +80,7 @@
TEST_F(GeneratorImplTest, EmitInitializer_Type_Float) {
ast::type::F32Type f32;
- auto lit = std::make_unique<ast::FloatLiteral>(-1.2e-5);
+ auto lit = std::make_unique<ast::FloatLiteral>(&f32, -1.2e-5);
std::vector<std::unique_ptr<ast::Expression>> values;
values.push_back(
std::make_unique<ast::ConstInitializerExpression>(std::move(lit)));
@@ -91,7 +95,7 @@
TEST_F(GeneratorImplTest, EmitInitializer_Type_Bool) {
ast::type::BoolType b;
- auto lit = std::make_unique<ast::BoolLiteral>(true);
+ auto lit = std::make_unique<ast::BoolLiteral>(&b, true);
std::vector<std::unique_ptr<ast::Expression>> values;
values.push_back(
std::make_unique<ast::ConstInitializerExpression>(std::move(lit)));
@@ -106,7 +110,7 @@
TEST_F(GeneratorImplTest, EmitInitializer_Type_Int) {
ast::type::I32Type i32;
- auto lit = std::make_unique<ast::IntLiteral>(-12345);
+ auto lit = std::make_unique<ast::IntLiteral>(&i32, -12345);
std::vector<std::unique_ptr<ast::Expression>> values;
values.push_back(
std::make_unique<ast::ConstInitializerExpression>(std::move(lit)));
@@ -121,7 +125,7 @@
TEST_F(GeneratorImplTest, EmitInitializer_Type_Uint) {
ast::type::U32Type u32;
- auto lit = std::make_unique<ast::UintLiteral>(12345);
+ auto lit = std::make_unique<ast::UintLiteral>(&u32, 12345);
std::vector<std::unique_ptr<ast::Expression>> values;
values.push_back(
std::make_unique<ast::ConstInitializerExpression>(std::move(lit)));
@@ -137,9 +141,9 @@
ast::type::F32Type f32;
ast::type::VectorType vec(&f32, 3);
- auto lit1 = std::make_unique<ast::FloatLiteral>(1.f);
- auto lit2 = std::make_unique<ast::FloatLiteral>(2.f);
- auto lit3 = std::make_unique<ast::FloatLiteral>(3.f);
+ auto lit1 = std::make_unique<ast::FloatLiteral>(&f32, 1.f);
+ auto lit2 = std::make_unique<ast::FloatLiteral>(&f32, 2.f);
+ auto lit3 = std::make_unique<ast::FloatLiteral>(&f32, 3.f);
std::vector<std::unique_ptr<ast::Expression>> values;
values.push_back(
std::make_unique<ast::ConstInitializerExpression>(std::move(lit1)));
@@ -164,8 +168,8 @@
std::vector<std::unique_ptr<ast::Expression>> mat_values;
for (size_t i = 0; i < 3; i++) {
- auto lit1 = std::make_unique<ast::FloatLiteral>(1.f + (i * 2));
- auto lit2 = std::make_unique<ast::FloatLiteral>(2.f + (i * 2));
+ auto lit1 = std::make_unique<ast::FloatLiteral>(&f32, 1.f + (i * 2));
+ auto lit2 = std::make_unique<ast::FloatLiteral>(&f32, 2.f + (i * 2));
std::vector<std::unique_ptr<ast::Expression>> values;
values.push_back(
@@ -195,9 +199,9 @@
std::vector<std::unique_ptr<ast::Expression>> ary_values;
for (size_t i = 0; i < 3; i++) {
- auto lit1 = std::make_unique<ast::FloatLiteral>(1.f + (i * 3));
- auto lit2 = std::make_unique<ast::FloatLiteral>(2.f + (i * 3));
- auto lit3 = std::make_unique<ast::FloatLiteral>(3.f + (i * 3));
+ auto lit1 = std::make_unique<ast::FloatLiteral>(&f32, 1.f + (i * 3));
+ auto lit2 = std::make_unique<ast::FloatLiteral>(&f32, 2.f + (i * 3));
+ auto lit3 = std::make_unique<ast::FloatLiteral>(&f32, 3.f + (i * 3));
std::vector<std::unique_ptr<ast::Expression>> values;
values.push_back(
diff --git a/src/writer/wgsl/generator_impl_switch_test.cc b/src/writer/wgsl/generator_impl_switch_test.cc
index 22f8f43..af82f6d 100644
--- a/src/writer/wgsl/generator_impl_switch_test.cc
+++ b/src/writer/wgsl/generator_impl_switch_test.cc
@@ -21,6 +21,7 @@
#include "src/ast/identifier_expression.h"
#include "src/ast/int_literal.h"
#include "src/ast/switch_statement.h"
+#include "src/ast/type/i32_type.h"
#include "src/writer/wgsl/generator_impl.h"
namespace tint {
@@ -36,7 +37,8 @@
def_body.push_back(std::make_unique<ast::BreakStatement>());
def->set_body(std::move(def_body));
- auto case_val = std::make_unique<ast::IntLiteral>(5);
+ ast::type::I32Type i32;
+ auto case_val = std::make_unique<ast::IntLiteral>(&i32, 5);
std::vector<std::unique_ptr<ast::Statement>> case_body;
case_body.push_back(std::make_unique<ast::BreakStatement>());