Commit a667b6b3 authored by Sigurd Schneider's avatar Sigurd Schneider Committed by Commit Bot

[torque] Add @generatePrint annotation

The new @generatePrint annotation automatically generates ...Print
methods for objects from their Torque class definition. While this
is mostly geared towards objects derived from Struct, it works on
any Torque class.

Bug: v8:7793
Change-Id: Iaa772879d397b95c7853dafdd9f09a85dbde8e35
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1557152
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#60708}
parent cdeb88e3
......@@ -1021,6 +1021,7 @@ action("run_torque") {
outputs = [
"$target_gen_dir/torque-generated/builtin-definitions-from-dsl.h",
"$target_gen_dir/torque-generated/class-definitions-from-dsl.h",
"$target_gen_dir/torque-generated/objects-printer-from-dsl.cc",
]
foreach(namespace, torque_namespaces) {
outputs += [
......@@ -1067,6 +1068,26 @@ v8_source_set("torque_generated_initializers") {
configs = [ ":internal_config" ]
}
v8_source_set("torque_generated_definitions") {
visibility = [ ":*" ] # Only targets in this file can depend on this.
deps = [
":run_torque",
]
if (v8_enable_i18n_support) {
public_deps = [
"//third_party/icu",
]
}
sources = [
"$target_gen_dir/torque-generated/objects-printer-from-dsl.cc",
]
configs = [ ":internal_config" ]
}
action("generate_bytecode_builtins_list") {
script = "tools/run.py"
outputs = [
......@@ -3096,6 +3117,7 @@ v8_source_set("v8_base") {
defines = []
deps = [
":torque_generated_definitions",
":v8_headers",
":v8_libbase",
":v8_libsampler",
......
......@@ -114,12 +114,16 @@ type NaN extends HeapNumber;
extern class Struct extends HeapObject {}
@generatePrint
extern class Tuple2 extends Struct {
value_1: Object;
value_2: Object;
value1: Object;
value2: Object;
}
extern class Tuple3 extends Tuple2 { value_3: Object; }
@generatePrint
extern class Tuple3 extends Tuple2 {
value3: Object;
}
// A direct string can be accessed directly through CSA without going into the
// C++ runtime. See also: ToDirectStringAssembler.
......
......@@ -1766,21 +1766,6 @@ void PrototypeInfo::PrototypeInfoPrint(std::ostream& os) { // NOLINT
os << "\n";
}
void Tuple2::Tuple2Print(std::ostream& os) { // NOLINT
PrintHeader(os, "Tuple2");
os << "\n - value1: " << Brief(value1());
os << "\n - value2: " << Brief(value2());
os << "\n";
}
void Tuple3::Tuple3Print(std::ostream& os) { // NOLINT
PrintHeader(os, "Tuple3");
os << "\n - value1: " << Brief(value1());
os << "\n - value2: " << Brief(value2());
os << "\n - value3: " << Brief(value3());
os << "\n";
}
void ClassPositions::ClassPositionsPrint(std::ostream& os) { // NOLINT
PrintHeader(os, "ClassPositions");
os << "\n - start position: " << start();
......
......@@ -922,13 +922,15 @@ struct StructDeclaration : Declaration {
struct ClassDeclaration : Declaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(ClassDeclaration)
ClassDeclaration(SourcePosition pos, Identifier* name, bool is_extern,
bool transient, base::Optional<std::string> super,
bool generate_print, bool transient,
base::Optional<std::string> super,
base::Optional<std::string> generates,
std::vector<Declaration*> methods,
std::vector<ClassFieldExpression> fields)
: Declaration(kKind, pos),
name(name),
is_extern(is_extern),
generate_print(generate_print),
transient(transient),
super(std::move(super)),
generates(std::move(generates)),
......@@ -936,6 +938,7 @@ struct ClassDeclaration : Declaration {
fields(std::move(fields)) {}
Identifier* name;
bool is_extern;
bool generate_print;
bool transient;
base::Optional<std::string> super;
base::Optional<std::string> generates;
......
......@@ -303,7 +303,8 @@ void DeclarationVisitor::Visit(ClassDeclaration* decl) {
}
new_class = Declarations::DeclareClass(
super_type, decl->name, decl->is_extern, decl->transient, generates);
super_type, decl->name, decl->is_extern, decl->generate_print,
decl->transient, generates);
} else {
if (decl->super) {
ReportError("Only extern classes can inherit.");
......@@ -311,9 +312,9 @@ void DeclarationVisitor::Visit(ClassDeclaration* decl) {
if (decl->generates) {
ReportError("Only extern classes can specify a generated type.");
}
new_class = Declarations::DeclareClass(TypeOracle::GetTaggedType(),
decl->name, decl->is_extern,
decl->transient, "FixedArray");
new_class = Declarations::DeclareClass(
TypeOracle::GetTaggedType(), decl->name, decl->is_extern,
decl->generate_print, decl->transient, "FixedArray");
}
GlobalContext::RegisterClass(decl->name->value, new_class);
class_declarations_.push_back(
......
......@@ -195,10 +195,10 @@ StructType* Declarations::DeclareStruct(const Identifier* name) {
ClassType* Declarations::DeclareClass(const Type* super_type,
const Identifier* name, bool is_extern,
bool transient,
bool generate_print, bool transient,
const std::string& generates) {
ClassType* new_type = TypeOracle::GetClassType(
super_type, name->value, is_extern, transient, generates);
super_type, name->value, is_extern, generate_print, transient, generates);
DeclareType(name, new_type, false);
return new_type;
}
......
......@@ -85,8 +85,8 @@ class Declarations {
static StructType* DeclareStruct(const Identifier* name);
static ClassType* DeclareClass(const Type* super, const Identifier* name,
bool is_extern, bool transient,
const std::string& generates);
bool is_extern, bool generate_print,
bool transient, const std::string& generates);
static Macro* CreateMacro(std::string external_name,
std::string readable_name,
......
......@@ -2871,6 +2871,48 @@ void ImplementationVisitor::GenerateClassDefinitions(std::string& file_name) {
ReplaceFileContentsIfDifferent(file_name, new_contents);
}
void ImplementationVisitor::GeneratePrintDefinitions(std::string& file_name) {
std::stringstream new_contents_stream;
new_contents_stream << "#ifdef OBJECT_PRINT\n\n";
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";
for (auto i : GlobalContext::GetClasses()) {
ClassType* type = i.second;
if (!type->ShouldGeneratePrint()) continue;
new_contents_stream << "void " << type->name() << "::" << type->name()
<< "Print(std::ostream& os) {\n";
new_contents_stream << " PrintHeader(os, \"" << type->name() << "\");\n";
auto hierarchy = type->GetHierarchy();
std::map<std::string, const AggregateType*> field_names;
for (const AggregateType* aggregate_type : hierarchy) {
for (const Field& f : aggregate_type->fields()) {
if (f.name_and_type.name == "map") continue;
new_contents_stream << " os << \"\\n - " << f.name_and_type.name
<< ": \" << "
<< "Brief(" << f.name_and_type.name << "());\n";
}
}
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);
}
} // namespace torque
} // namespace internal
} // namespace v8
......@@ -257,6 +257,7 @@ class ImplementationVisitor : public FileVisitor {
public:
void GenerateBuiltinDefinitions(std::string& file_name);
void GenerateClassDefinitions(std::string& file_name);
void GeneratePrintDefinitions(std::string& file_name);
VisitResult Visit(Expression* expr);
const Type* Visit(Statement* stmt);
......
......@@ -74,6 +74,10 @@ void CompileCurrentAst(TorqueCompilerOptions options) {
output_header_path = output_directory + "/class-definitions-from-dsl.h";
implementation_visitor.GenerateClassDefinitions(output_header_path);
std::string output_source_path =
output_directory + "/objects-printer-from-dsl.cc";
implementation_visitor.GeneratePrintDefinitions(output_source_path);
for (Namespace* n : GlobalContext::Get().GetNamespaces()) {
implementation_visitor.EndNamespaceFile(n);
implementation_visitor.GenerateImplementation(output_directory, n);
......
......@@ -572,6 +572,7 @@ base::Optional<ParseResult> MakeMethodDeclaration(
base::Optional<ParseResult> MakeClassDeclaration(
ParseResultIterator* child_results) {
auto generate_print = child_results->NextAs<bool>();
auto is_extern = child_results->NextAs<bool>();
auto transient = child_results->NextAs<bool>();
auto name = child_results->NextAs<Identifier*>();
......@@ -583,8 +584,8 @@ base::Optional<ParseResult> MakeClassDeclaration(
auto methods = child_results->NextAs<std::vector<Declaration*>>();
auto fields = child_results->NextAs<std::vector<ClassFieldExpression>>();
Declaration* result = MakeNode<ClassDeclaration>(
name, is_extern, transient, std::move(extends), std::move(generates),
std::move(methods), fields);
name, is_extern, generate_print, transient, std::move(extends),
std::move(generates), std::move(methods), fields);
return ParseResult{result};
}
......@@ -1636,8 +1637,8 @@ struct TorqueGrammar : Grammar {
Rule({Token("const"), &name, Token(":"), &type, Token("generates"),
&externalString, Token(";")},
MakeExternConstDeclaration),
Rule({CheckIf(Token("extern")), CheckIf(Token("transient")),
Token("class"), &name,
Rule({CheckIf(Token("@generatePrint")), CheckIf(Token("extern")),
CheckIf(Token("transient")), Token("class"), &name,
Optional<std::string>(Sequence({Token("extends"), &identifier})),
Optional<std::string>(
Sequence({Token("generates"), &externalString})),
......
......@@ -35,10 +35,11 @@ class TypeOracle : public ContextualClass<TypeOracle> {
}
static ClassType* GetClassType(const Type* parent, const std::string& name,
bool is_extern, bool transient,
const std::string& generates) {
ClassType* result = new ClassType(parent, CurrentNamespace(), name,
is_extern, transient, generates);
bool is_extern, bool generate_print,
bool transient, const std::string& generates) {
ClassType* result =
new ClassType(parent, CurrentNamespace(), name, is_extern,
generate_print, transient, generates);
Get().struct_types_.push_back(std::unique_ptr<ClassType>(result));
return result;
}
......
......@@ -288,10 +288,12 @@ std::string StructType::ToExplicitString() const {
}
ClassType::ClassType(const Type* parent, Namespace* nspace,
const std::string& name, bool is_extern, bool transient,
const std::string& name, bool is_extern,
bool generate_print, bool transient,
const std::string& generates)
: AggregateType(Kind::kClassType, parent, nspace, name),
is_extern_(is_extern),
generate_print_(generate_print),
transient_(transient),
size_(0),
has_indexed_field_(false),
......
......@@ -471,6 +471,7 @@ class ClassType final : public AggregateType {
std::string GetGeneratedTypeNameImpl() const override;
std::string GetGeneratedTNodeTypeNameImpl() const override;
bool IsExtern() const { return is_extern_; }
bool ShouldGeneratePrint() const { return generate_print_; }
bool IsTransient() const override { return transient_; }
bool HasIndexedField() const override;
size_t size() const { return size_; }
......@@ -490,9 +491,11 @@ class ClassType final : public AggregateType {
private:
friend class TypeOracle;
ClassType(const Type* parent, Namespace* nspace, const std::string& name,
bool is_extern, bool transient, const std::string& generates);
bool is_extern, bool generate_print, bool transient,
const std::string& generates);
bool is_extern_;
bool generate_print_;
bool transient_;
size_t size_;
bool has_indexed_field_;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment