[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:
Nico Hartmann 2019-12-20 16:33:37 +01:00 committed by Commit Bot
parent e09a068026
commit d873128a67
7 changed files with 75 additions and 0 deletions

View File

@ -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",
]

View File

@ -181,6 +181,7 @@ namespace regexp {
}
extern enum Flag constexpr 'JSRegExp::Flag' {
kNone,
kGlobal,
kIgnoreCase,
kMultiline,

View File

@ -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";

View File

@ -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";

View File

@ -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);

View File

@ -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);

View File

@ -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)};