[torque] Adds enum verifier to check closed enums for completeness
Bug: v8:10053 Change-Id: I90e0798ce490dea035cf4ecb934a4b8d98c61bc3 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1977859 Auto-Submit: Nico Hartmann <nicohartmann@chromium.org> Reviewed-by: Tobias Tebbi <tebbi@chromium.org> Commit-Queue: Tobias Tebbi <tebbi@chromium.org> Cr-Commit-Position: refs/heads/master@{#65551}
This commit is contained in:
parent
e09a068026
commit
d873128a67
2
BUILD.gn
2
BUILD.gn
@ -1126,6 +1126,7 @@ action("run_torque") {
|
||||
"$target_gen_dir/torque-generated/field-offsets-tq.h",
|
||||
"$target_gen_dir/torque-generated/class-verifiers-tq.cc",
|
||||
"$target_gen_dir/torque-generated/class-verifiers-tq.h",
|
||||
"$target_gen_dir/torque-generated/enum-verifiers-tq.cc",
|
||||
"$target_gen_dir/torque-generated/objects-printer-tq.cc",
|
||||
"$target_gen_dir/torque-generated/class-definitions-tq.cc",
|
||||
"$target_gen_dir/torque-generated/class-definitions-tq-inl.h",
|
||||
@ -1181,6 +1182,7 @@ v8_source_set("torque_generated_initializers") {
|
||||
|
||||
sources = [
|
||||
"$target_gen_dir/torque-generated/csa-types-tq.h",
|
||||
"$target_gen_dir/torque-generated/enum-verifiers-tq.cc",
|
||||
"$target_gen_dir/torque-generated/exported-macros-assembler-tq.cc",
|
||||
"$target_gen_dir/torque-generated/exported-macros-assembler-tq.h",
|
||||
]
|
||||
|
@ -181,6 +181,7 @@ namespace regexp {
|
||||
}
|
||||
|
||||
extern enum Flag constexpr 'JSRegExp::Flag' {
|
||||
kNone,
|
||||
kGlobal,
|
||||
kIgnoreCase,
|
||||
kMultiline,
|
||||
|
@ -184,6 +184,23 @@ struct NamespaceDeclaration : Declaration {
|
||||
std::string name;
|
||||
};
|
||||
|
||||
struct EnumDescription {
|
||||
SourcePosition pos;
|
||||
std::string name;
|
||||
std::string constexpr_generates;
|
||||
bool is_open;
|
||||
std::vector<std::string> entries;
|
||||
|
||||
EnumDescription(SourcePosition pos, std::string name,
|
||||
std::string constexpr_generates, bool is_open,
|
||||
std::vector<std::string> entries = {})
|
||||
: pos(std::move(pos)),
|
||||
name(std::move(name)),
|
||||
constexpr_generates(std::move(constexpr_generates)),
|
||||
is_open(is_open),
|
||||
entries(std::move(entries)) {}
|
||||
};
|
||||
|
||||
class Ast {
|
||||
public:
|
||||
Ast() {}
|
||||
@ -203,10 +220,26 @@ class Ast {
|
||||
declared_imports_[CurrentSourcePosition::Get().source].insert(import_id);
|
||||
}
|
||||
|
||||
void AddEnumDescription(EnumDescription description) {
|
||||
std::string name = description.name;
|
||||
DCHECK(!name.empty());
|
||||
auto f = [&](const auto& d) { return d.name == name; };
|
||||
USE(f); // Suppress unused in release.
|
||||
DCHECK_EQ(
|
||||
std::find_if(enum_descriptions_.begin(), enum_descriptions_.end(), f),
|
||||
enum_descriptions_.end());
|
||||
enum_descriptions_.push_back(std::move(description));
|
||||
}
|
||||
|
||||
std::vector<EnumDescription>& EnumDescriptions() {
|
||||
return enum_descriptions_;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<Declaration*> declarations_;
|
||||
std::vector<std::unique_ptr<AstNode>> nodes_;
|
||||
std::map<SourceId, std::set<SourceId>> declared_imports_;
|
||||
std::vector<EnumDescription> enum_descriptions_;
|
||||
};
|
||||
|
||||
static const char* const kThisParameterName = "this";
|
||||
|
@ -3893,6 +3893,38 @@ void ImplementationVisitor::GenerateClassVerifiers(
|
||||
WriteFile(output_directory + "/" + file_name + ".cc", cc_contents.str());
|
||||
}
|
||||
|
||||
void ImplementationVisitor::GenerateEnumVerifiers(
|
||||
const std::string& output_directory) {
|
||||
std::string file_name = "enum-verifiers-tq";
|
||||
std::stringstream cc_contents;
|
||||
{
|
||||
cc_contents << "#include \"src/compiler/code-assembler.h\"\n";
|
||||
for (const std::string& include_path : GlobalContext::CppIncludes()) {
|
||||
cc_contents << "#include " << StringLiteralQuote(include_path) << "\n";
|
||||
}
|
||||
cc_contents << "\n";
|
||||
|
||||
NamespaceScope cc_namespaces(cc_contents, {"v8", "internal", ""});
|
||||
|
||||
cc_contents << "class EnumVerifier {\n";
|
||||
for (const auto& desc : GlobalContext::Get().ast()->EnumDescriptions()) {
|
||||
cc_contents << " // " << desc.name << " (" << desc.pos << ")\n";
|
||||
cc_contents << " void VerifyEnum_" << desc.name << "("
|
||||
<< desc.constexpr_generates
|
||||
<< " x) {\n"
|
||||
" switch(x) {\n";
|
||||
for (const auto& entry : desc.entries) {
|
||||
cc_contents << " case " << entry << ": break;\n";
|
||||
}
|
||||
if (desc.is_open) cc_contents << " default: break;\n";
|
||||
cc_contents << " }\n }\n\n";
|
||||
}
|
||||
cc_contents << "};\n";
|
||||
}
|
||||
|
||||
WriteFile(output_directory + "/" + file_name + ".cc", cc_contents.str());
|
||||
}
|
||||
|
||||
void ImplementationVisitor::GenerateExportedMacrosAssembler(
|
||||
const std::string& output_directory) {
|
||||
std::string file_name = "exported-macros-assembler-tq";
|
||||
|
@ -390,6 +390,7 @@ class ImplementationVisitor {
|
||||
void GenerateClassDefinitions(const std::string& output_directory);
|
||||
void GenerateInstanceTypes(const std::string& output_directory);
|
||||
void GenerateClassVerifiers(const std::string& output_directory);
|
||||
void GenerateEnumVerifiers(const std::string& output_directory);
|
||||
void GenerateClassDebugReaders(const std::string& output_directory);
|
||||
void GenerateExportedMacrosAssembler(const std::string& output_directory);
|
||||
void GenerateCSATypes(const std::string& output_directory);
|
||||
|
@ -87,6 +87,7 @@ void CompileCurrentAst(TorqueCompilerOptions options) {
|
||||
implementation_visitor.GenerateClassDefinitions(output_directory);
|
||||
implementation_visitor.GenerateClassVerifiers(output_directory);
|
||||
implementation_visitor.GenerateClassDebugReaders(output_directory);
|
||||
implementation_visitor.GenerateEnumVerifiers(output_directory);
|
||||
implementation_visitor.GenerateExportedMacrosAssembler(output_directory);
|
||||
implementation_visitor.GenerateCSATypes(output_directory);
|
||||
implementation_visitor.GenerateInstanceTypes(output_directory);
|
||||
|
@ -1249,11 +1249,15 @@ base::Optional<ParseResult> MakeEnumDeclaration(
|
||||
fromconstexpr_parameter_identifier)})}));
|
||||
}
|
||||
|
||||
EnumDescription enum_description{CurrentSourcePosition::Get(), name,
|
||||
constexpr_generates, is_open};
|
||||
std::vector<Declaration*> entry_decls;
|
||||
for (const auto& entry_name_identifier : entries) {
|
||||
const std::string entry_name = entry_name_identifier->value;
|
||||
const std::string entry_constexpr_type =
|
||||
std::string(CONSTEXPR_TYPE_PREFIX) + entry_name;
|
||||
enum_description.entries.push_back(constexpr_generates +
|
||||
"::" + entry_name);
|
||||
|
||||
entry_decls.push_back(MakeNode<AbstractTypeDeclaration>(
|
||||
MakeNode<Identifier>(entry_constexpr_type), false,
|
||||
@ -1290,6 +1294,7 @@ base::Optional<ParseResult> MakeEnumDeclaration(
|
||||
|
||||
result.push_back(
|
||||
MakeNode<NamespaceDeclaration>(name, std::move(entry_decls)));
|
||||
CurrentAst::Get().AddEnumDescription(std::move(enum_description));
|
||||
}
|
||||
|
||||
return ParseResult{std::move(result)};
|
||||
|
Loading…
Reference in New Issue
Block a user