Skip to content

Commit 3f2d458

Browse files
No public description
PiperOrigin-RevId: 922796132
1 parent 4264635 commit 3f2d458

14 files changed

Lines changed: 628 additions & 329 deletions

maldoca/astgen/ast_def.cc

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,24 @@ absl::StatusOr<AstDef> AstDef::FromProto(const AstDefPb& pb) {
360360
for (auto kind : union_type_pb.kinds()) {
361361
union_type_node->kinds_.push_back(static_cast<FieldKind>(kind));
362362
}
363+
if (union_type_pb.has_ir_op_name()) {
364+
union_type_node->ir_op_name_ = union_type_pb.ir_op_name();
365+
}
366+
if (union_type_pb.has_should_generate_dispatch()) {
367+
union_type_node->should_generate_dispatch_ =
368+
union_type_pb.should_generate_dispatch();
369+
}
370+
for (const auto& o : union_type_pb.dispatch_overrides()) {
371+
std::optional<std::string> ir_op_name;
372+
if (o.has_ir_op_name()) {
373+
ir_op_name = o.ir_op_name();
374+
}
375+
union_type_node->dispatch_overrides_.emplace(
376+
o.type(), NodeDef::DispatchOverride{o.visitor(), ir_op_name});
377+
}
378+
for (const auto& s : union_type_pb.dispatch_skip()) {
379+
union_type_node->dispatch_skip_.insert(s);
380+
}
363381
if (nodes.contains(union_type_pb.name())) {
364382
return absl::InvalidArgumentError(
365383
absl::StrCat(union_type_pb.name(), " already exists!"));

maldoca/astgen/ast_def.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <vector>
2323

2424
#include "absl/container/flat_hash_map.h"
25+
#include "absl/container/flat_hash_set.h"
2526
#include "absl/log/log.h"
2627
#include "absl/status/statusor.h"
2728
#include "absl/strings/string_view.h"
@@ -175,6 +176,44 @@ class NodeDef {
175176
// If false, the op is expected to be manually written.
176177
bool should_generate_ir_op() const { return should_generate_ir_op_; }
177178

179+
// Whether IR dispatch code should be automatically generated for unions.
180+
bool should_generate_dispatch() const { return should_generate_dispatch_; }
181+
182+
// Overrides for generated dispatch code.
183+
//
184+
// For a union type (e.g., `Expression`), the generator automatically
185+
// produces dispatch code (e.g., `dynamic_cast` chain in AST-to-IR, or
186+
// `TypeSwitch` in IR-to-AST) to route to the correct visitor for each member
187+
// (e.g., `VisitIdentifier`).
188+
//
189+
// `DispatchOverride` allows customizing this routing for specific members.
190+
struct DispatchOverride {
191+
// The name of the visitor function to call.
192+
// E.g., "VisitIdentifierRef" instead of the default "VisitIdentifier".
193+
std::string visitor;
194+
195+
// The IR op name to use for this member.
196+
// E.g., "jsir.IdentifierRef" instead of "jsir.Identifier".
197+
std::optional<std::string> ir_op_name;
198+
};
199+
200+
// Map from union member type name (e.g., "Identifier") to its dispatch
201+
// override.
202+
const absl::flat_hash_map<std::string, DispatchOverride>&
203+
dispatch_overrides() const {
204+
return dispatch_overrides_;
205+
}
206+
207+
// Set of union member type names to skip in the generated dispatch code.
208+
//
209+
// If a member is skipped, it will not be included in the generated
210+
// dispatch methods, and must be handled manually if needed.
211+
//
212+
// E.g., {"InvalidExpression"} to skip generating dispatch for invalid nodes.
213+
const absl::flat_hash_set<std::string>& dispatch_skip() const {
214+
return dispatch_skip_;
215+
}
216+
178217
// The allowed FieldKinds for this node. Does not include those specified in
179218
// ancestors.
180219
//
@@ -293,6 +332,9 @@ class NodeDef {
293332
std::vector<FieldKind> aggregated_kinds_;
294333
bool has_control_flow_;
295334
std::optional<std::string> ir_op_name_;
335+
bool should_generate_dispatch_ = true;
336+
absl::flat_hash_map<std::string, DispatchOverride> dispatch_overrides_;
337+
absl::flat_hash_set<std::string> dispatch_skip_;
296338
bool has_fold_;
297339
std::vector<MlirTrait> additional_mlir_traits_;
298340
std::vector<MlirTrait> aggregated_additional_mlir_traits_;

maldoca/astgen/ast_def.proto

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,40 @@ message UnionTypePb {
342342

343343
// Supported kinds. Each kind leads to a different IR op.
344344
repeated FieldKind kinds = 5;
345+
346+
// [Optional] Custom MLIR op name.
347+
optional string ir_op_name = 6;
348+
349+
// If true, automatically generate the corresponding IR dispatch code.
350+
optional bool should_generate_dispatch = 7 [default = true];
351+
352+
message DispatchOverridePb {
353+
// The name of the union member type to override.
354+
// E.g., "Identifier".
355+
optional string type = 1;
356+
357+
// The name of the visitor function to call.
358+
// E.g., "VisitIdentifierRef" instead of the default "VisitIdentifier".
359+
optional string visitor = 2;
360+
361+
// The IR op name to use for this member.
362+
// E.g., "jsir.IdentifierRef" instead of "jsir.Identifier".
363+
optional string ir_op_name = 3;
364+
}
365+
366+
// Overrides for generated dispatch code.
367+
//
368+
// Allows customizing the generated visitor and IR op name for specific
369+
// union members.
370+
repeated DispatchOverridePb dispatch_overrides = 8;
371+
372+
// Set of union member type names to skip in the generated dispatch code.
373+
//
374+
// If a member is skipped, it will not be included in the generated
375+
// dispatch methods, and must be handled manually if needed.
376+
//
377+
// E.g., "InvalidExpression" to skip generating dispatch for invalid nodes.
378+
repeated string dispatch_skip = 9;
345379
}
346380

347381
// Top-level AST definition.

maldoca/astgen/ast_gen_main.cc

Lines changed: 59 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,31 @@ ABSL_FLAG(std::string, ast_path, "", "The directory for the AST code in C++.");
5050
ABSL_FLAG(std::string, ir_path, "",
5151
"The directory for the IR code in TableGen and C++.");
5252

53+
// Flags to support mapping AST nodes to a different target IR dialect
54+
// (e.g. mapping SWC's "jsswc" AST to the standard "jsir" dialect).
55+
ABSL_FLAG(std::string, ir_lang_name, "",
56+
"The language name for the IR (e.g. 'js').");
57+
58+
// Overrides to prevent generated files from overwriting other dialect
59+
// conversions and to use custom names/paths.
60+
ABSL_FLAG(std::string, ast_to_ir_cc_path, "",
61+
"Override output path for generated AST to IR C++ source.");
62+
63+
ABSL_FLAG(std::string, ir_to_ast_cc_path, "",
64+
"Override output path for generated IR to AST C++ source.");
65+
66+
ABSL_FLAG(std::string, ast_to_ir_header_include_path, "",
67+
"Override include path for AST to IR header in generated source.");
68+
69+
ABSL_FLAG(std::string, ir_to_ast_header_include_path, "",
70+
"Override include path for IR to AST header in generated source.");
71+
72+
ABSL_FLAG(std::string, ast_to_ir_class_name, "",
73+
"Override class name for AST to IR converter.");
74+
75+
ABSL_FLAG(std::string, ir_to_ast_class_name, "",
76+
"Override class name for IR to AST converter.");
77+
5378
namespace maldoca {
5479
namespace {
5580

@@ -58,6 +83,15 @@ absl::Status AstGenMain() {
5883
auto cc_namespace = absl::GetFlag(FLAGS_cc_namespace);
5984
auto ast_path = absl::GetFlag(FLAGS_ast_path);
6085
auto ir_path = absl::GetFlag(FLAGS_ir_path);
86+
auto ir_lang_name = absl::GetFlag(FLAGS_ir_lang_name);
87+
auto ast_to_ir_cc_path_flag = absl::GetFlag(FLAGS_ast_to_ir_cc_path);
88+
auto ir_to_ast_cc_path_flag = absl::GetFlag(FLAGS_ir_to_ast_cc_path);
89+
auto ast_to_ir_header_include_path =
90+
absl::GetFlag(FLAGS_ast_to_ir_header_include_path);
91+
auto ir_to_ast_header_include_path =
92+
absl::GetFlag(FLAGS_ir_to_ast_header_include_path);
93+
auto ast_to_ir_class_name = absl::GetFlag(FLAGS_ast_to_ir_class_name);
94+
auto ir_to_ast_class_name = absl::GetFlag(FLAGS_ir_to_ast_class_name);
6195

6296
AstDefPb ast_def_pb;
6397
MALDOCA_RETURN_IF_ERROR(ParseTextProtoFile(ast_def_path, &ast_def_pb));
@@ -87,27 +121,35 @@ absl::Status AstGenMain() {
87121
SetFileContents(ast_from_json_path, ast_from_json));
88122

89123
if (!ir_path.empty()) {
90-
std::string ir_tablegen = PrintIrTableGen(ast_def, ir_path);
91-
auto ir_tablegen_path = JoinPath(
92-
ir_path, absl::StrCat(ast_def.lang_name(), "ir_ops.generated.td"));
93-
std::cout << "Writing ir_tablegen to " << ir_tablegen_path << "\n";
94-
MALDOCA_RETURN_IF_ERROR(
95-
SetFileContents(ir_tablegen_path, ir_tablegen));
96-
97-
std::string ast_to_ir =
98-
PrintAstToIrSource(ast_def, cc_namespace, ast_path, ir_path);
99-
auto ast_to_ir_path = JoinPath(
100-
ir_path, "conversion",
101-
absl::StrCat("ast_to_", ast_def.lang_name(), "ir.generated.cc"));
124+
if (ir_lang_name.empty() || ir_lang_name == ast_def.lang_name()) {
125+
std::string ir_tablegen = PrintIrTableGen(ast_def, ir_path);
126+
auto ir_tablegen_path = JoinPath(
127+
ir_path, absl::StrCat(ast_def.lang_name(), "ir_ops.generated.td"));
128+
std::cout << "Writing ir_tablegen to " << ir_tablegen_path << "\n";
129+
MALDOCA_RETURN_IF_ERROR(SetFileContents(ir_tablegen_path, ir_tablegen));
130+
}
131+
132+
std::string ast_to_ir = PrintAstToIrSource(
133+
ast_def, cc_namespace, ast_path, ir_path, ir_lang_name,
134+
ast_to_ir_header_include_path, ast_to_ir_class_name);
135+
auto ast_to_ir_path =
136+
ast_to_ir_cc_path_flag.empty()
137+
? JoinPath(ir_path, "conversion",
138+
absl::StrCat("ast_to_", ast_def.lang_name(),
139+
"ir.generated.cc"))
140+
: ast_to_ir_cc_path_flag;
102141
std::cout << "Writing ast_to_ir to " << ast_to_ir_path << "\n";
103142
MALDOCA_RETURN_IF_ERROR(
104143
SetFileContents(ast_to_ir_path, ast_to_ir));
105144

106-
std::string ir_to_ast =
107-
PrintIrToAstSource(ast_def, cc_namespace, ast_path, ir_path);
108-
auto ir_to_ast_path = JoinPath(
109-
ir_path, "conversion",
110-
absl::StrCat(ast_def.lang_name(), "ir_to_ast.generated.cc"));
145+
std::string ir_to_ast = PrintIrToAstSource(
146+
ast_def, cc_namespace, ast_path, ir_path, ir_lang_name,
147+
ir_to_ast_header_include_path, ir_to_ast_class_name);
148+
auto ir_to_ast_path = ir_to_ast_cc_path_flag.empty()
149+
? JoinPath(ir_path, "conversion",
150+
absl::StrCat(ast_def.lang_name(),
151+
"ir_to_ast.generated.cc"))
152+
: ir_to_ast_cc_path_flag;
111153
std::cout << "Writing ir_to_ast to " << ir_to_ast_path << "\n";
112154
MALDOCA_RETURN_IF_ERROR(
113155
SetFileContents(ir_to_ast_path, ir_to_ast));

maldoca/astgen/ast_source_printer.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,9 @@ void AstSourcePrinter::PrintConstructor(const NodeDef& node,
275275
}
276276

277277
Print(")");
278+
if (!ancestor->aggregated_fields().empty()) {
279+
Print(" /* NOLINT */");
280+
}
278281
}
279282

280283
for (const FieldDef& field : node.fields()) {

0 commit comments

Comments
 (0)