[torque] Add helpers for C++ code generation

Change-Id: I75a4a2af4bbe9d495d583b13fb6d885d8509c2b8
Bug: v8:7793
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1611797
Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
Reviewed-by: Simon Zünd <szuend@chromium.org>
Reviewed-by: Tobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#61491}
This commit is contained in:
Sigurd Schneider 2019-05-14 15:19:49 +02:00 committed by Commit Bot
parent f6f31d154e
commit bdff71b648
4 changed files with 278 additions and 244 deletions

View File

@ -2706,13 +2706,73 @@ void ImplementationVisitor::Visit(Declarable* declarable) {
}
}
void ImplementationVisitor::GenerateBuiltinDefinitions(std::string& file_name) {
namespace {
class IfDefScope {
public:
IfDefScope(std::ostream& os, std::string d) : os_(os), d_(std::move(d)) {
os_ << "#ifdef " << d_ << "\n";
}
~IfDefScope() { os_ << "#endif // " << d_ << "\n"; }
private:
std::ostream& os_;
std::string d_;
};
class NamespaceScope {
public:
NamespaceScope(std::ostream& os, std::string namespace_name)
: os_(os), d_(std::move(namespace_name)) {
os_ << "namespace " << d_ << " {\n";
}
~NamespaceScope() { os_ << "} // namespace " << d_ << "\n"; }
private:
std::ostream& os_;
std::string d_;
};
class IncludeGuardScope {
public:
IncludeGuardScope(std::ostream& os, std::string file_name)
: os_(os),
d_("V8_GEN_TORQUE_GENERATED_" + CapifyStringWithUnderscores(file_name) +
"_") {
os_ << "#ifndef " << d_ << "\n";
os_ << "#define " << d_ << "\n\n";
}
~IncludeGuardScope() { os_ << "#endif // " << d_ << "\n"; }
private:
std::ostream& os_;
std::string d_;
};
class IncludeObjectMacros {
public:
explicit IncludeObjectMacros(std::ostream& os) : os_(os) {
os_ << "\n// Has to be the last include (doesn't have include guards):\n"
"#include \"src/objects/object-macros.h\"\n";
}
~IncludeObjectMacros() {
os_ << "\n#include \"src/objects/object-macros-undef.h\"\n";
}
private:
std::ostream& os_;
};
} // namespace
void ImplementationVisitor::GenerateBuiltinDefinitions(
const std::string& output_directory) {
std::stringstream new_contents_stream;
std::string file_name = "builtin-definitions-tq.h";
{
IncludeGuardScope include_guard(new_contents_stream, file_name);
new_contents_stream
<< "#ifndef V8_GEN_TORQUE_GENERATED_BUILTIN_DEFINITIONS_TQ_H_\n"
"#define V8_GEN_TORQUE_GENERATED_BUILTIN_DEFINITIONS_TQ_H_\n"
"\n"
"#define BUILTIN_LIST_FROM_TORQUE(CPP, API, TFJ, TFC, TFS, TFH, ASM) "
<< "\n"
"#define BUILTIN_LIST_FROM_TORQUE(CPP, API, TFJ, TFC, TFS, TFH, "
"ASM) "
"\\\n";
for (auto& declarable : GlobalContext::AllDeclarables()) {
Builtin* builtin = Builtin::DynamicCast(declarable.get());
@ -2754,7 +2814,8 @@ void ImplementationVisitor::GenerateBuiltinDefinitions(std::string& file_name) {
new_contents_stream
<< "#define TORQUE_FUNCTION_POINTER_TYPE_TO_BUILTIN_MAP(V) \\\n";
for (const BuiltinPointerType* type : TypeOracle::AllBuiltinPointerTypes()) {
for (const BuiltinPointerType* type :
TypeOracle::AllBuiltinPointerTypes()) {
Builtin* example_builtin =
Declarations::FindSomeInternalBuiltinWithType(type);
if (!example_builtin) {
@ -2766,12 +2827,10 @@ void ImplementationVisitor::GenerateBuiltinDefinitions(std::string& file_name) {
<< example_builtin->ExternalName() << ")\\\n";
}
new_contents_stream << "\n";
new_contents_stream
<< "#endif // V8_GEN_TORQUE_GENERATED_BUILTIN_DEFINITIONS_TQ_H_\n";
}
std::string new_contents(new_contents_stream.str());
ReplaceFileContentsIfDifferent(file_name, new_contents);
ReplaceFileContentsIfDifferent(output_directory + "/" + file_name,
new_contents);
}
namespace {
@ -2850,9 +2909,9 @@ void CompleteFieldSection(FieldSectionType* section,
void ImplementationVisitor::GenerateClassFieldOffsets(
const std::string& output_directory) {
std::stringstream new_contents_stream;
new_contents_stream << "#ifndef V8_GEN_TORQUE_GENERATED_FIELD_OFFSETS_TQ_H_\n"
"#define V8_GEN_TORQUE_GENERATED_FIELD_OFFSETS_TQ_H_\n"
"\n\n";
std::string file_name = "field-offsets-tq.h";
{
IncludeGuardScope include_guard(new_contents_stream, file_name);
for (auto i : GlobalContext::GetClasses()) {
ClassType* type = i.second;
@ -2860,9 +2919,9 @@ void ImplementationVisitor::GenerateClassFieldOffsets(
// TODO(danno): Ideally (and we've got several core V8 dev's feedback
// supporting this), Torque should generate the constants for the offsets
// directly and not go through the existing layer of macros, which actually
// currently just serves to additionally obfuscate where these values come
// from.
// directly and not go through the existing layer of macros, which
// actually currently just serves to additionally obfuscate where these
// values come from.
new_contents_stream << "#define ";
new_contents_stream << "TORQUE_GENERATED_"
<< CapifyStringWithUnderscores(i.first)
@ -2899,7 +2958,8 @@ void ImplementationVisitor::GenerateClassFieldOffsets(
ProcessFieldInSection(&section, &completed_sections,
FieldSectionType::kNoSection, &new_contents_stream);
CompleteFieldSection(&section, &completed_sections,
FieldSectionType::kWeakSection, &new_contents_stream);
FieldSectionType::kWeakSection,
&new_contents_stream);
CompleteFieldSection(&section, &completed_sections,
FieldSectionType::kStrongSection,
&new_contents_stream);
@ -2907,27 +2967,25 @@ void ImplementationVisitor::GenerateClassFieldOffsets(
new_contents_stream << "V(kSize, 0) \\\n";
new_contents_stream << "\n";
}
new_contents_stream
<< "\n#endif // V8_GEN_TORQUE_GENERATED_FIELD_OFFSETS_TQ_H_\n";
const std::string output_header_path =
output_directory + "/field-offsets-tq.h";
}
const std::string output_header_path = output_directory + "/" + file_name;
std::string new_contents(new_contents_stream.str());
ReplaceFileContentsIfDifferent(output_header_path, new_contents);
}
void ImplementationVisitor::GeneratePrintDefinitions(std::string& file_name) {
void ImplementationVisitor::GeneratePrintDefinitions(
const std::string& output_directory) {
std::stringstream new_contents_stream;
new_contents_stream << "#ifdef OBJECT_PRINT\n\n";
std::string file_name = "objects-printer-tq.cc";
{
IfDefScope object_print(new_contents_stream, "OBJECT_PRINT");
new_contents_stream << "#include \"src/objects.h\"\n\n";
new_contents_stream << "#include <iosfwd>\n\n";
new_contents_stream << "#include \"src/objects/struct-inl.h\"\n\n";
new_contents_stream << "namespace v8 {\n";
new_contents_stream << "namespace internal {\n\n";
NamespaceScope namespace_v8(new_contents_stream, "v8");
NamespaceScope namespace_internal(new_contents_stream, "internal");
for (auto i : GlobalContext::GetClasses()) {
ClassType* type = i.second;
@ -2949,14 +3007,11 @@ void ImplementationVisitor::GeneratePrintDefinitions(std::string& file_name) {
new_contents_stream << " os << \"\\n\";\n";
new_contents_stream << "}\n\n";
}
new_contents_stream << "} // namespace internal\"\n";
new_contents_stream << "} // namespace v8\"\n";
new_contents_stream << "\n#endif // OBJECT_PRINT\n\n";
}
std::string new_contents(new_contents_stream.str());
ReplaceFileContentsIfDifferent(file_name, new_contents);
ReplaceFileContentsIfDifferent(output_directory + "/" + file_name,
new_contents);
}
namespace {
@ -3033,16 +3088,13 @@ void GenerateClassFieldVerifier(const std::string& class_name,
void ImplementationVisitor::GenerateClassVerifiers(
const std::string& output_directory) {
const char* file_name = "class-verifiers-tq";
std::string file_name = "class-verifiers-tq";
std::stringstream h_contents;
std::stringstream cc_contents;
h_contents << "#ifndef V8_GEN_TORQUE_GENERATED_CLASS_VERIFIERS_TQ_H_\n"
"#define V8_GEN_TORQUE_GENERATED_CLASS_VERIFIERS_TQ_H_\n"
"\n";
const char* enabled_check = "\n#ifdef VERIFY_HEAP\n";
h_contents << enabled_check;
cc_contents << enabled_check;
{
IncludeGuardScope include_guard(h_contents, file_name + ".h");
IfDefScope verify_heap_h(h_contents, "VERIFY_HEAP");
IfDefScope verify_heap_cc(cc_contents, "VERIFY_HEAP");
cc_contents << "\n#include \"src/objects.h\"\n";
@ -3050,16 +3102,14 @@ void ImplementationVisitor::GenerateClassVerifiers(
cc_contents << "#include " << StringLiteralQuote(include_path) << "\n";
}
cc_contents << "#include \"torque-generated/" << file_name << ".h\"\n";
cc_contents
<< "\n// Has to be the last include (doesn't have include guards):\n"
"#include \"src/objects/object-macros.h\"\n";
const char* namespaces =
"\nnamespace v8 {\n"
"namespace internal {\n"
"\n";
h_contents << namespaces;
cc_contents << namespaces;
IncludeObjectMacros object_macros(cc_contents);
NamespaceScope namespace_v8_h(h_contents, "v8");
NamespaceScope namespace_internal_h(h_contents, "internal");
NamespaceScope namespace_v8_cc(cc_contents, "v8");
NamespaceScope namespace_internal_cc(cc_contents, "internal");
// Generate forward declarations to avoid including any headers.
h_contents << "class Isolate;\n";
@ -3071,7 +3121,7 @@ void ImplementationVisitor::GenerateClassVerifiers(
const char* verifier_class = "TorqueGeneratedClassVerifiers";
h_contents << "class " << verifier_class << " {\n";
h_contents << "class " << verifier_class << "{\n";
h_contents << " public:\n";
for (auto i : GlobalContext::GetClasses()) {
@ -3095,11 +3145,11 @@ void ImplementationVisitor::GenerateClassVerifiers(
if (super_type) {
std::string super_name = super_type->name();
if (super_name == "HeapObject") {
// Special case: HeapObjectVerify checks the Map type and dispatches to
// more specific types, so calling it here would cause infinite
// recursion. We could consider moving that behavior into a different
// method to make the contract of *Verify methods more consistent, but
// for now we'll just avoid the bad case.
// Special case: HeapObjectVerify checks the Map type and dispatches
// to more specific types, so calling it here would cause infinite
// recursion. We could consider moving that behavior into a
// different method to make the contract of *Verify methods more
// consistent, but for now we'll just avoid the bad case.
cc_contents << " " << super_name << "Verify(o, isolate);\n";
} else {
cc_contents << " o->" << super_name << "Verify(isolate);\n";
@ -3119,21 +3169,7 @@ void ImplementationVisitor::GenerateClassVerifiers(
}
h_contents << "};\n";
const char* end_namespaces =
"\n} // namespace internal\n"
"} // namespace v8\n";
h_contents << end_namespaces;
cc_contents << end_namespaces;
cc_contents << "\n#include \"src/objects/object-macros-undef.h\"\n";
const char* end_enabled_check = "\n#endif // VERIFY_HEAP\n";
h_contents << end_enabled_check;
cc_contents << end_enabled_check;
h_contents << "\n#endif // V8_GEN_TORQUE_GENERATED_CLASS_VERIFIERS_TQ_H_\n";
}
ReplaceFileContentsIfDifferent(output_directory + "/" + file_name + ".h",
h_contents.str());
ReplaceFileContentsIfDifferent(output_directory + "/" + file_name + ".cc",

View File

@ -275,9 +275,9 @@ bool IsCompatibleSignature(const Signature& sig, const TypeVector& types,
class ImplementationVisitor {
public:
void GenerateBuiltinDefinitions(std::string& file_name);
void GenerateBuiltinDefinitions(const std::string& output_directory);
void GenerateClassFieldOffsets(const std::string& output_directory);
void GeneratePrintDefinitions(std::string& file_name);
void GeneratePrintDefinitions(const std::string& output_directory);
void GenerateClassVerifiers(const std::string& output_directory);
VisitResult Visit(Expression* expr);

View File

@ -76,16 +76,9 @@ void CompileCurrentAst(TorqueCompilerOptions options) {
std::string output_directory = options.output_directory;
if (output_directory.length() != 0) {
std::string output_header_path = output_directory;
output_header_path += "/builtin-definitions-tq.h";
implementation_visitor.GenerateBuiltinDefinitions(output_header_path);
implementation_visitor.GenerateBuiltinDefinitions(output_directory);
implementation_visitor.GenerateClassFieldOffsets(output_directory);
std::string output_source_path =
output_directory + "/objects-printer-tq.cc";
implementation_visitor.GeneratePrintDefinitions(output_source_path);
implementation_visitor.GeneratePrintDefinitions(output_directory);
implementation_visitor.GenerateClassVerifiers(output_directory);
for (Namespace* n : GlobalContext::Get().GetNamespaces()) {

View File

@ -217,6 +217,11 @@ std::string CapifyStringWithUnderscores(const std::string& camellified_string) {
if (previousWasLower && isupper(current)) {
result += "_";
}
if (current == '.' || current == '-') {
result += "_";
previousWasLower = false;
continue;
}
result += toupper(current);
previousWasLower = (islower(current));
}