reader/wgsl: Optimize tokens by using string_view
Each Token was making a copy of the `val_str_`, despite the token being a slice on the original source.
Bug: tint:1383
Change-Id: I17b2da8f986ba105853aa47afe21bcc75f140f8e
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/78320
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
diff --git a/src/reader/wgsl/lexer.cc b/src/reader/wgsl/lexer.cc
index 94d8ced..04a10b4 100644
--- a/src/reader/wgsl/lexer.cc
+++ b/src/reader/wgsl/lexer.cc
@@ -62,38 +62,31 @@
Lexer::~Lexer() = default;
Token Lexer::next() {
- auto t = skip_whitespace_and_comments();
- if (!t.IsUninitialized()) {
+ if (auto t = skip_whitespace_and_comments(); !t.IsUninitialized()) {
return t;
}
- t = try_hex_float();
- if (!t.IsUninitialized()) {
+ if (auto t = try_hex_float(); !t.IsUninitialized()) {
return t;
}
- t = try_hex_integer();
- if (!t.IsUninitialized()) {
+ if (auto t = try_hex_integer(); !t.IsUninitialized()) {
return t;
}
- t = try_float();
- if (!t.IsUninitialized()) {
+ if (auto t = try_float(); !t.IsUninitialized()) {
return t;
}
- t = try_integer();
- if (!t.IsUninitialized()) {
+ if (auto t = try_integer(); !t.IsUninitialized()) {
return t;
}
- t = try_ident();
- if (!t.IsUninitialized()) {
+ if (auto t = try_ident(); !t.IsUninitialized()) {
return t;
}
- t = try_punctuation();
- if (!t.IsUninitialized()) {
+ if (auto t = try_punctuation(); !t.IsUninitialized()) {
return t;
}
@@ -771,7 +764,7 @@
return t;
}
- return {Token::Type::kIdentifier, source, std::string(str)};
+ return {Token::Type::kIdentifier, source, str};
}
Token Lexer::try_punctuation() {
diff --git a/src/reader/wgsl/parser_impl.cc b/src/reader/wgsl/parser_impl.cc
index f219eba..a1c236f 100644
--- a/src/reader/wgsl/parser_impl.cc
+++ b/src/reader/wgsl/parser_impl.cc
@@ -125,28 +125,22 @@
const char kWorkgroupSizeDecoration[] = "workgroup_size";
bool is_decoration(Token t) {
- if (!t.IsIdentifier()) {
- return false;
- }
-
- auto s = t.to_str();
- return s == kAlignDecoration || s == kBindingDecoration ||
- s == kBlockDecoration || s == kBuiltinDecoration ||
- s == kGroupDecoration || s == kInterpolateDecoration ||
- s == kLocationDecoration || s == kOverrideDecoration ||
- s == kSizeDecoration || s == kStageDecoration ||
- s == kStrideDecoration || s == kWorkgroupSizeDecoration;
+ return t == kAlignDecoration || t == kBindingDecoration ||
+ t == kBlockDecoration || t == kBuiltinDecoration ||
+ t == kGroupDecoration || t == kInterpolateDecoration ||
+ t == kLocationDecoration || t == kOverrideDecoration ||
+ t == kSizeDecoration || t == kStageDecoration ||
+ t == kStrideDecoration || t == kWorkgroupSizeDecoration;
}
// https://gpuweb.github.io/gpuweb/wgsl.html#reserved-keywords
bool is_reserved(Token t) {
- auto s = t.to_str();
- return s == "asm" || s == "bf16" || s == "const" || s == "do" ||
- s == "enum" || s == "f16" || s == "f64" || s == "handle" ||
- s == "i8" || s == "i16" || s == "i64" || s == "mat" ||
- s == "premerge" || s == "regardless" || s == "typedef" || s == "u8" ||
- s == "u16" || s == "u64" || s == "unless" || s == "using" ||
- s == "vec" || s == "void" || s == "while";
+ return t == "asm" || t == "bf16" || t == "const" || t == "do" ||
+ t == "enum" || t == "f16" || t == "f64" || t == "handle" ||
+ t == "i8" || t == "i16" || t == "i64" || t == "mat" ||
+ t == "premerge" || t == "regardless" || t == "typedef" || t == "u8" ||
+ t == "u16" || t == "u64" || t == "unless" || t == "using" ||
+ t == "vec" || t == "void" || t == "while";
}
/// Enter-exit counters for block token types.
@@ -760,59 +754,56 @@
// | 'rgba32sint'
// | 'rgba32float'
Expect<ast::TexelFormat> ParserImpl::expect_texel_format(std::string_view use) {
- auto tok = next();
- if (tok.IsIdentifier()) {
- auto s = tok.to_str();
- if (s == "rgba8unorm") {
- return ast::TexelFormat::kRgba8Unorm;
- }
- if (s == "rgba8snorm") {
- return ast::TexelFormat::kRgba8Snorm;
- }
- if (s == "rgba8uint") {
- return ast::TexelFormat::kRgba8Uint;
- }
- if (s == "rgba8sint") {
- return ast::TexelFormat::kRgba8Sint;
- }
- if (s == "rgba16uint") {
- return ast::TexelFormat::kRgba16Uint;
- }
- if (s == "rgba16sint") {
- return ast::TexelFormat::kRgba16Sint;
- }
- if (s == "rgba16float") {
- return ast::TexelFormat::kRgba16Float;
- }
- if (s == "r32uint") {
- return ast::TexelFormat::kR32Uint;
- }
- if (s == "r32sint") {
- return ast::TexelFormat::kR32Sint;
- }
- if (s == "r32float") {
- return ast::TexelFormat::kR32Float;
- }
- if (s == "rg32uint") {
- return ast::TexelFormat::kRg32Uint;
- }
- if (s == "rg32sint") {
- return ast::TexelFormat::kRg32Sint;
- }
- if (s == "rg32float") {
- return ast::TexelFormat::kRg32Float;
- }
- if (s == "rgba32uint") {
- return ast::TexelFormat::kRgba32Uint;
- }
- if (s == "rgba32sint") {
- return ast::TexelFormat::kRgba32Sint;
- }
- if (s == "rgba32float") {
- return ast::TexelFormat::kRgba32Float;
- }
+ auto t = next();
+ if (t == "rgba8unorm") {
+ return ast::TexelFormat::kRgba8Unorm;
}
- return add_error(tok.source(), "invalid format", use);
+ if (t == "rgba8snorm") {
+ return ast::TexelFormat::kRgba8Snorm;
+ }
+ if (t == "rgba8uint") {
+ return ast::TexelFormat::kRgba8Uint;
+ }
+ if (t == "rgba8sint") {
+ return ast::TexelFormat::kRgba8Sint;
+ }
+ if (t == "rgba16uint") {
+ return ast::TexelFormat::kRgba16Uint;
+ }
+ if (t == "rgba16sint") {
+ return ast::TexelFormat::kRgba16Sint;
+ }
+ if (t == "rgba16float") {
+ return ast::TexelFormat::kRgba16Float;
+ }
+ if (t == "r32uint") {
+ return ast::TexelFormat::kR32Uint;
+ }
+ if (t == "r32sint") {
+ return ast::TexelFormat::kR32Sint;
+ }
+ if (t == "r32float") {
+ return ast::TexelFormat::kR32Float;
+ }
+ if (t == "rg32uint") {
+ return ast::TexelFormat::kRg32Uint;
+ }
+ if (t == "rg32sint") {
+ return ast::TexelFormat::kRg32Sint;
+ }
+ if (t == "rg32float") {
+ return ast::TexelFormat::kRg32Float;
+ }
+ if (t == "rgba32uint") {
+ return ast::TexelFormat::kRgba32Uint;
+ }
+ if (t == "rgba32sint") {
+ return ast::TexelFormat::kRgba32Sint;
+ }
+ if (t == "rgba32float") {
+ return ast::TexelFormat::kRgba32Float;
+ }
+ return add_error(t.source(), "invalid format", use);
}
// variable_ident_decl
@@ -1431,24 +1422,18 @@
// | COMPUTE
Expect<ast::PipelineStage> ParserImpl::expect_pipeline_stage() {
auto t = peek();
- if (!t.IsIdentifier()) {
- return add_error(t, "invalid value for stage decoration");
- }
-
- auto s = t.to_str();
- if (s == kVertexStage) {
+ if (t == kVertexStage) {
next(); // Consume the peek
return {ast::PipelineStage::kVertex, t.source()};
}
- if (s == kFragmentStage) {
+ if (t == kFragmentStage) {
next(); // Consume the peek
return {ast::PipelineStage::kFragment, t.source()};
}
- if (s == kComputeStage) {
+ if (t == kComputeStage) {
next(); // Consume the peek
return {ast::PipelineStage::kCompute, t.source()};
}
-
return add_error(peek(), "invalid value for stage decoration");
}
@@ -2932,9 +2917,7 @@
return Failure::kNoMatch;
}
- auto s = t.to_str();
-
- if (s == kLocationDecoration) {
+ if (t == kLocationDecoration) {
const char* use = "location decoration";
return expect_paren_block(use, [&]() -> Result {
auto val = expect_positive_sint(use);
@@ -2945,7 +2928,7 @@
});
}
- if (s == kBindingDecoration) {
+ if (t == kBindingDecoration) {
const char* use = "binding decoration";
return expect_paren_block(use, [&]() -> Result {
auto val = expect_positive_sint(use);
@@ -2956,7 +2939,7 @@
});
}
- if (s == kGroupDecoration) {
+ if (t == kGroupDecoration) {
const char* use = "group decoration";
return expect_paren_block(use, [&]() -> Result {
auto val = expect_positive_sint(use);
@@ -2967,18 +2950,17 @@
});
}
- if (s == kInterpolateDecoration) {
+ if (t == kInterpolateDecoration) {
return expect_paren_block("interpolate decoration", [&]() -> Result {
ast::InterpolationType type;
ast::InterpolationSampling sampling = ast::InterpolationSampling::kNone;
auto type_tok = next();
- auto type_str = type_tok.to_str();
- if (type_str == "perspective") {
+ if (type_tok == "perspective") {
type = ast::InterpolationType::kPerspective;
- } else if (type_str == "linear") {
+ } else if (type_tok == "linear") {
type = ast::InterpolationType::kLinear;
- } else if (type_str == "flat") {
+ } else if (type_tok == "flat") {
type = ast::InterpolationType::kFlat;
} else {
return add_error(type_tok, "invalid interpolation type");
@@ -2986,12 +2968,11 @@
if (match(Token::Type::kComma)) {
auto sampling_tok = next();
- auto sampling_str = sampling_tok.to_str();
- if (sampling_str == "center") {
+ if (sampling_tok == "center") {
sampling = ast::InterpolationSampling::kCenter;
- } else if (sampling_str == "centroid") {
+ } else if (sampling_tok == "centroid") {
sampling = ast::InterpolationSampling::kCentroid;
- } else if (sampling_str == "sample") {
+ } else if (sampling_tok == "sample") {
sampling = ast::InterpolationSampling::kSample;
} else {
return add_error(sampling_tok, "invalid interpolation sampling");
@@ -3002,11 +2983,11 @@
});
}
- if (s == kInvariantDecoration) {
+ if (t == kInvariantDecoration) {
return create<ast::InvariantDecoration>(t.source());
}
- if (s == kBuiltinDecoration) {
+ if (t == kBuiltinDecoration) {
return expect_paren_block("builtin decoration", [&]() -> Result {
auto builtin = expect_builtin();
if (builtin.errored)
@@ -3016,7 +2997,7 @@
});
}
- if (s == kWorkgroupSizeDecoration) {
+ if (t == kWorkgroupSizeDecoration) {
return expect_paren_block("workgroup_size decoration", [&]() -> Result {
const ast::Expression* x = nullptr;
const ast::Expression* y = nullptr;
@@ -3054,7 +3035,7 @@
});
}
- if (s == kStageDecoration) {
+ if (t == kStageDecoration) {
return expect_paren_block("stage decoration", [&]() -> Result {
auto stage = expect_pipeline_stage();
if (stage.errored)
@@ -3064,12 +3045,12 @@
});
}
- if (s == kBlockDecoration) {
+ if (t == kBlockDecoration) {
deprecated(t.source(), "[[block]] attributes have been removed from WGSL");
return create<ast::StructBlockDecoration>(t.source());
}
- if (s == kStrideDecoration) {
+ if (t == kStrideDecoration) {
const char* use = "stride decoration";
return expect_paren_block(use, [&]() -> Result {
auto val = expect_nonzero_positive_sint(use);
@@ -3082,7 +3063,7 @@
});
}
- if (s == kSizeDecoration) {
+ if (t == kSizeDecoration) {
const char* use = "size decoration";
return expect_paren_block(use, [&]() -> Result {
auto val = expect_positive_sint(use);
@@ -3093,7 +3074,7 @@
});
}
- if (s == kAlignDecoration) {
+ if (t == kAlignDecoration) {
const char* use = "align decoration";
return expect_paren_block(use, [&]() -> Result {
auto val = expect_positive_sint(use);
@@ -3104,7 +3085,7 @@
});
}
- if (s == kOverrideDecoration) {
+ if (t == kOverrideDecoration) {
const char* use = "override decoration";
if (peek_is(Token::Type::kParenLeft)) {
diff --git a/src/reader/wgsl/token.cc b/src/reader/wgsl/token.cc
index 82147d5..ce462c2 100644
--- a/src/reader/wgsl/token.cc
+++ b/src/reader/wgsl/token.cc
@@ -254,19 +254,25 @@
Token::Token() : type_(Type::kUninitialized) {}
-Token::Token(Type type, const Source& source, const std::string& val)
- : type_(type), source_(source), val_str_(val) {}
+Token::Token(Type type, const Source& source, const std::string_view& view)
+ : type_(type), source_(source), value_(view) {}
+
+Token::Token(Type type, const Source& source, const std::string& str)
+ : type_(type), source_(source), value_(str) {}
+
+Token::Token(Type type, const Source& source, const char* str)
+ : type_(type), source_(source), value_(std::string_view(str)) {}
Token::Token(const Source& source, uint32_t val)
- : type_(Type::kUintLiteral), source_(source), val_uint_(val) {}
+ : type_(Type::kUintLiteral), source_(source), value_(val) {}
Token::Token(const Source& source, int32_t val)
- : type_(Type::kSintLiteral), source_(source), val_int_(val) {}
+ : type_(Type::kSintLiteral), source_(source), value_(val) {}
Token::Token(const Source& source, float val)
- : type_(Type::kFloatLiteral), source_(source), val_float_(val) {}
+ : type_(Type::kFloatLiteral), source_(source), value_(val) {}
-Token::Token(Type type, const Source& source) : Token(type, source, "") {}
+Token::Token(Type type, const Source& source) : type_(type), source_(source) {}
Token::Token(Token&&) = default;
@@ -274,31 +280,47 @@
Token::~Token() = default;
-Token& Token::operator=(const Token&) = default;
+Token& Token::operator=(const Token& rhs) = default;
+
+bool Token::operator==(std::string_view ident) {
+ if (type_ != Type::kIdentifier) {
+ return false;
+ }
+ if (auto* view = std::get_if<std::string_view>(&value_)) {
+ return *view == ident;
+ }
+ return std::get<std::string>(value_) == ident;
+}
std::string Token::to_str() const {
- if (type_ == Type::kFloatLiteral) {
- return std::to_string(val_float_);
+ switch (type_) {
+ case Type::kFloatLiteral:
+ return std::to_string(std::get<float>(value_));
+ case Type::kSintLiteral:
+ return std::to_string(std::get<int32_t>(value_));
+ case Type::kUintLiteral:
+ return std::to_string(std::get<uint32_t>(value_));
+ case Type::kIdentifier:
+ case Type::kError:
+ if (auto* view = std::get_if<std::string_view>(&value_)) {
+ return std::string(*view);
+ }
+ return std::get<std::string>(value_);
+ default:
+ return "";
}
- if (type_ == Type::kSintLiteral) {
- return std::to_string(val_int_);
- }
- if (type_ == Type::kUintLiteral) {
- return std::to_string(val_uint_);
- }
- return val_str_;
}
float Token::to_f32() const {
- return val_float_;
+ return std::get<float>(value_);
}
uint32_t Token::to_u32() const {
- return val_uint_;
+ return std::get<uint32_t>(value_);
}
int32_t Token::to_i32() const {
- return val_int_;
+ return std::get<int32_t>(value_);
}
} // namespace wgsl
diff --git a/src/reader/wgsl/token.h b/src/reader/wgsl/token.h
index bc955dd..0a62ce6 100644
--- a/src/reader/wgsl/token.h
+++ b/src/reader/wgsl/token.h
@@ -17,6 +17,7 @@
#include <string>
#include <string_view>
+#include <variant> // NOLINT: cpplint doesn't recognise this
#include "src/source.h"
@@ -273,8 +274,18 @@
/// Create a string Token
/// @param type the Token::Type of the token
/// @param source the source of the token
- /// @param val the source string for the token
- Token(Type type, const Source& source, const std::string& val);
+ /// @param view the source string view for the token
+ Token(Type type, const Source& source, const std::string_view& view);
+ /// Create a string Token
+ /// @param type the Token::Type of the token
+ /// @param source the source of the token
+ /// @param str the source string for the token
+ Token(Type type, const Source& source, const std::string& str);
+ /// Create a string Token
+ /// @param type the Token::Type of the token
+ /// @param source the source of the token
+ /// @param str the source string for the token
+ Token(Type type, const Source& source, const char* str);
/// Create a unsigned integer Token
/// @param source the source of the token
/// @param val the source unsigned for the token
@@ -298,6 +309,11 @@
/// @return Token
Token& operator=(const Token& b);
+ /// Equality operator with an identifier
+ /// @param ident the identifier string
+ /// @return true if this token is an identifier and is equal to ident.
+ bool operator==(std::string_view ident);
+
/// Returns true if the token is of the given type
/// @param t the type to check against.
/// @returns true if the token is of type `t`
@@ -378,14 +394,8 @@
Type type_ = Type::kError;
/// The source where the token appeared
Source source_;
- /// The string represented by the token
- std::string val_str_;
- /// The signed integer represented by the token
- int32_t val_int_ = 0;
- /// The unsigned integer represented by the token
- uint32_t val_uint_ = 0;
- /// The float value represented by the token
- float val_float_ = 0.0;
+ /// The value represented by the token
+ std::variant<int32_t, uint32_t, float, std::string, std::string_view> value_;
};
#ifndef NDEBUG