tint/ast: Generate ast::Extension from intrinsics.def

Emit unit tests for parsing and printing.
Emit benchmarks for parsing.
Uses intrinsics.def as a single-source-of-truth.
The generators provide a way to optimize the enum parsers.

Change-Id: I7f13128f510b2156c2ef724c89df7bb85dae17ed
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/97151
Commit-Queue: Ben Clayton <bclayton@chromium.org>
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
This commit is contained in:
Ben Clayton
2022-07-27 18:32:19 +00:00
committed by Dawn LUCI CQ
parent 9e5415dbeb
commit f50d56aa05
18 changed files with 383 additions and 153 deletions

View File

@@ -12,40 +12,46 @@
// See the License for the specific language governing permissions and
// limitations under the License.
////////////////////////////////////////////////////////////////////////////////
// File generated by tools/src/cmd/gen
// using the template:
// src/tint/ast/extension.cc.tmpl
//
// Do not modify this file directly
////////////////////////////////////////////////////////////////////////////////
#include "src/tint/ast/extension.h"
namespace tint::ast {
Extension ParseExtension(const std::string& name) {
if (name == "chromium_experimental_dp4a") {
return Extension::kChromiumExperimentalDP4a;
}
if (name == "chromium_disable_uniformity_analysis") {
return Extension::kChromiumDisableUniformityAnalysis;
}
if (name == "f16") {
/// ParseExtension parses a Extension from a string.
/// @param str the string to parse
/// @returns the parsed enum, or Extension::kInvalid if the string could not be parsed.
Extension ParseExtension(std::string_view str) {
if (str == "f16") {
return Extension::kF16;
}
return Extension::kNone;
}
const char* str(Extension ext) {
switch (ext) {
case Extension::kChromiumExperimentalDP4a:
return "chromium_experimental_dp4a";
case Extension::kChromiumDisableUniformityAnalysis:
return "chromium_disable_uniformity_analysis";
case Extension::kF16:
return "f16";
case Extension::kNone:
return "<none>";
if (str == "chromium_experimental_dp4a") {
return Extension::kChromiumExperimentalDp4A;
}
return "<unknown>";
if (str == "chromium_disable_uniformity_analysis") {
return Extension::kChromiumDisableUniformityAnalysis;
}
return Extension::kInvalid;
}
std::ostream& operator<<(std::ostream& out, Extension i) {
out << str(i);
return out;
std::ostream& operator<<(std::ostream& out, Extension value) {
switch (value) {
case Extension::kInvalid:
return out << "invalid";
case Extension::kF16:
return out << "f16";
case Extension::kChromiumExperimentalDp4A:
return out << "chromium_experimental_dp4a";
case Extension::kChromiumDisableUniformityAnalysis:
return out << "chromium_disable_uniformity_analysis";
}
return out << "<unknown>";
}
} // namespace tint::ast

View File

@@ -0,0 +1,22 @@
{{- /*
--------------------------------------------------------------------------------
Template file for use with tools/src/cmd/gen to generate extension.cc
See:
* tools/src/cmd/gen for structures used by this template
* https://golang.org/pkg/text/template/ for documentation on the template syntax
--------------------------------------------------------------------------------
*/ -}}
{{- Import "src/tint/templates/enums.tmpl.inc" -}}
{{- $enum := (Sem.Enum "extension") -}}
#include "src/tint/ast/extension.h"
namespace tint::ast {
{{ Eval "ParseEnum" $enum}}
{{ Eval "EnumOStream" $enum}}
} // namespace tint::ast

View File

@@ -12,53 +12,41 @@
// See the License for the specific language governing permissions and
// limitations under the License.
////////////////////////////////////////////////////////////////////////////////
// File generated by tools/src/cmd/gen
// using the template:
// src/tint/ast/extension.h.tmpl
//
// Do not modify this file directly
////////////////////////////////////////////////////////////////////////////////
#ifndef SRC_TINT_AST_EXTENSION_H_
#define SRC_TINT_AST_EXTENSION_H_
#include <sstream>
#include <string>
#include <ostream>
#include "src/tint/utils/unique_vector.h"
namespace tint::ast {
/// An enumerator of WGSL extensions
/// @see src/tint/intrinsics.def for extension descriptions
enum class Extension {
/// WGSL Extension "f16"
kInvalid,
kF16,
/// An extension for the experimental feature
/// "chromium_experimental_dp4a".
/// See crbug.com/tint/1497 for more details
kChromiumExperimentalDP4a,
/// A Chromium-specific extension for disabling uniformity analysis.
kChromiumExperimentalDp4A,
kChromiumDisableUniformityAnalysis,
/// Reserved for representing "No extension required" or "Not a valid extension".
kNone,
};
/// Convert a string of extension name into one of Extension enum value, the result will be
/// Extension::kNone if the name is not a known extension name. A extension node of kind
/// kNone must not exist in the AST tree, and using a unknown extension name in WGSL code
/// should result in a shader-creation error.
/// @param name string of the extension name
/// @return the Extension enum value for the extension of given name, or kNone if no known extension
/// has the given name
Extension ParseExtension(const std::string& name);
/// @param out the std::ostream to write to
/// @param value the Extension
/// @returns `out` so calls can be chained
std::ostream& operator<<(std::ostream& out, Extension value);
/// Convert the Extension enum value to corresponding extension name string.
/// @param ext the Extension enum value
/// @return string of the extension name corresponding to the given kind, or
/// an empty string if the given enum value is kNone or don't have a
/// known corresponding name
const char* ExtensionName(Extension ext);
/// @returns the name of the extension.
const char* str(Extension i);
/// Emits the name of the extension type.
std::ostream& operator<<(std::ostream& out, Extension i);
/// ParseExtension parses a Extension from a string.
/// @param str the string to parse
/// @returns the parsed enum, or Extension::kInvalid if the string could not be parsed.
Extension ParseExtension(std::string_view str);
// A unique vector of extensions
using Extensions = utils::UniqueVector<Extension>;

View File

@@ -0,0 +1,32 @@
{{- /*
--------------------------------------------------------------------------------
Template file for use with tools/src/cmd/gen to generate extension.h
See:
* tools/src/cmd/gen for structures used by this template
* https://golang.org/pkg/text/template/ for documentation on the template syntax
--------------------------------------------------------------------------------
*/ -}}
{{- Import "src/tint/templates/enums.tmpl.inc" -}}
{{- $enum := (Sem.Enum "extension") -}}
#ifndef SRC_TINT_AST_EXTENSION_H_
#define SRC_TINT_AST_EXTENSION_H_
#include <ostream>
#include "src/tint/utils/unique_vector.h"
namespace tint::ast {
/// An enumerator of WGSL extensions
/// @see src/tint/intrinsics.def for extension descriptions
{{ Eval "DeclareEnum" $enum}}
// A unique vector of extensions
using Extensions = utils::UniqueVector<Extension>;
} // namespace tint::ast
#endif // SRC_TINT_AST_EXTENSION_H_

View File

@@ -0,0 +1,67 @@
// Copyright 2022 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.
////////////////////////////////////////////////////////////////////////////////
// File generated by tools/src/cmd/gen
// using the template:
// src/tint/ast/extension_bench.cc.tmpl
//
// Do not modify this file directly
////////////////////////////////////////////////////////////////////////////////
#include "src/tint/ast/extension.h"
#include <array>
#include "benchmark/benchmark.h"
namespace tint::ast {
namespace {
void ExtensionParser(::benchmark::State& state) {
std::array kStrings{
"cc6",
"s",
"HH6",
"f16",
"116",
"qJ6",
"f17ll",
"chromippHm_experqqmetal_dp4a",
"chrmium_expecimntal_dp4",
"chrmiumGexpebimental_dp4a",
"chromium_experimental_dp4a",
"chromium_exverimentiil_dp4a",
"chro8ium_experimenWWal_dp4a",
"chromiMm_eperimxxntal_dp4a",
"chXggmium_disable_uniformity_aalysis",
"Xhomiuu_disale_uniformity_analysis",
"chromium_3isable_uniformity_analysis",
"chromium_disable_uniformity_analysis",
"chromiuE_disable_uniformity_analysis",
"chromium_disable_uniTTormity_aPPalsis",
"ddhromium_disabexxuniformity_analysis",
};
for (auto _ : state) {
for (auto& str : kStrings) {
auto result = ParseExtension(str);
benchmark::DoNotOptimize(result);
}
}
}
BENCHMARK(ExtensionParser);
} // namespace
} // namespace tint::ast

View File

@@ -0,0 +1,26 @@
{{- /*
--------------------------------------------------------------------------------
Template file for use with tools/src/cmd/gen to generate extension_bench.cc
See:
* tools/src/cmd/gen for structures used by this template
* https://golang.org/pkg/text/template/ for documentation on the template syntax
--------------------------------------------------------------------------------
*/ -}}
{{- Import "src/tint/templates/enums.tmpl.inc" -}}
{{- $enum := (Sem.Enum "extension") -}}
#include "src/tint/ast/extension.h"
#include <array>
#include "benchmark/benchmark.h"
namespace tint::ast {
namespace {
{{ Eval "BenchmarkParseEnum" $enum }}
} // namespace
} // namespace tint::ast

View File

@@ -1,4 +1,3 @@
// Copyright 2021 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -13,24 +12,75 @@
// See the License for the specific language governing permissions and
// limitations under the License.
////////////////////////////////////////////////////////////////////////////////
// File generated by tools/src/cmd/gen
// using the template:
// src/tint/ast/extension_test.cc.tmpl
//
// Do not modify this file directly
////////////////////////////////////////////////////////////////////////////////
#include "src/tint/ast/extension.h"
#include "gtest/gtest.h"
#include <string>
#include "src/tint/ast/test_helper.h"
#include "src/tint/utils/string.h"
namespace tint::ast {
namespace {
TEST(ExtensionTest, NameToKind_InvalidName) {
EXPECT_EQ(ParseExtension("f16"), Extension::kF16);
EXPECT_EQ(ParseExtension(""), Extension::kNone);
EXPECT_EQ(ParseExtension("__ImpossibleExtensionName"), Extension::kNone);
EXPECT_EQ(ParseExtension("123"), Extension::kNone);
namespace parse_print_tests {
struct Case {
const char* string;
Extension value;
};
inline std::ostream& operator<<(std::ostream& out, Case c) {
return out << "'" << std::string(c.string) << "'";
}
TEST(ExtensionTest, KindToName) {
EXPECT_EQ(std::string(str(Extension::kF16)), "f16");
EXPECT_EQ(std::string(str(Extension::kNone)), "<none>");
static constexpr Case kValidCases[] = {
{"f16", Extension::kF16},
{"chromium_experimental_dp4a", Extension::kChromiumExperimentalDp4A},
{"chromium_disable_uniformity_analysis", Extension::kChromiumDisableUniformityAnalysis},
};
static constexpr Case kInvalidCases[] = {
{"cc6", Extension::kInvalid},
{"s", Extension::kInvalid},
{"HH6", Extension::kInvalid},
{"chro1ium_experimental_dp4a", Extension::kInvalid},
{"chrJmium_experiqqetal_dp4a", Extension::kInvalid},
{"chromium_experimenll77l_dp4a", Extension::kInvalid},
{"chromiumppdisableqquniformity_aalysHHs", Extension::kInvalid},
{"chromiu_disable_unifovmitc_analyi", Extension::kInvalid},
{"chromium_diable_uGbformity_analysis", Extension::kInvalid},
};
using ExtensionParseTest = testing::TestWithParam<Case>;
TEST_P(ExtensionParseTest, Parse) {
const char* string = GetParam().string;
Extension expect = GetParam().value;
EXPECT_EQ(expect, ParseExtension(string));
}
INSTANTIATE_TEST_SUITE_P(ValidCases, ExtensionParseTest, testing::ValuesIn(kValidCases));
INSTANTIATE_TEST_SUITE_P(InvalidCases, ExtensionParseTest, testing::ValuesIn(kInvalidCases));
using ExtensionPrintTest = testing::TestWithParam<Case>;
TEST_P(ExtensionPrintTest, Print) {
Extension value = GetParam().value;
const char* expect = GetParam().string;
EXPECT_EQ(expect, utils::ToString(value));
}
INSTANTIATE_TEST_SUITE_P(ValidCases, ExtensionPrintTest, testing::ValuesIn(kValidCases));
} // namespace parse_print_tests
} // namespace
} // namespace tint::ast

View File

@@ -0,0 +1,27 @@
{{- /*
--------------------------------------------------------------------------------
Template file for use with tools/src/cmd/gen to generate extension_test.cc
See:
* tools/src/cmd/gen for structures used by this template
* https://golang.org/pkg/text/template/ for documentation on the template syntax
--------------------------------------------------------------------------------
*/ -}}
{{- Import "src/tint/templates/enums.tmpl.inc" -}}
{{- $enum := (Sem.Enum "extension") -}}
#include "src/tint/ast/extension.h"
#include <string>
#include "src/tint/ast/test_helper.h"
#include "src/tint/utils/string.h"
namespace tint::ast {
namespace {
{{ Eval "TestParsePrintEnum" $enum}}
} // namespace
} // namespace tint::ast