Skip to content

Commit e0b3bf4

Browse files
committed
feat: Add SCF dialect and generate IR for a few basic expressions and statements
Also, add the option `-emit-ir` to the CLI to generate the IR to the standard output. Signed-off-by: Roberto Raggi <[email protected]>
1 parent 5eb7527 commit e0b3bf4

File tree

8 files changed

+155
-40
lines changed

8 files changed

+155
-40
lines changed

src/frontend/cxx/frontend.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ auto runOnFile(const CLI& cli, const std::string& fileName) -> bool {
296296
}
297297

298298
#ifdef CXX_WITH_MLIR
299-
if (cli.opt_ir_dump) {
299+
if (cli.opt_emit_ir) {
300300
mlir::MLIRContext context;
301301
context.loadDialect<mlir::cxx::CxxDialect>();
302302

@@ -305,7 +305,7 @@ auto runOnFile(const CLI& cli, const std::string& fileName) -> bool {
305305
auto ir = codegen(unit.ast());
306306

307307
mlir::OpPrintingFlags flags;
308-
flags.enableDebugInfo(true);
308+
flags.enableDebugInfo(true, true);
309309
ir.module->print(llvm::outs(), flags);
310310
}
311311
#endif

src/mlir/cxx/mlir/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ target_link_libraries(cxx-mlir PUBLIC
1818
MLIRIR
1919
MLIRFuncDialect
2020
MLIRControlFlowDialect
21+
MLIRSCFDialect
2122
)
2223
add_dependencies(cxx-mlir MLIRCxxOpsIncGen)
2324

src/mlir/cxx/mlir/CxxOps.td

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ def Cxx_Dialect : Dialect {
2828
let dependentDialects = [
2929
"mlir::func::FuncDialect",
3030
"mlir::cf::ControlFlowDialect",
31+
"mlir::scf::SCFDialect",
3132
];
3233
}
3334

@@ -40,7 +41,7 @@ class Cxx_Op<string mnemonic, list<Trait> traits = []> : Op<Cxx_Dialect, mnemoni
4041

4142
def Cxx_ExprType : Cxx_Type<"Expr", "expr">;
4243

43-
def Cxx_TodoExprOp : Cxx_Op<"todo.expr"> {
44+
def TodoExprOp : Cxx_Op<"todo.expr"> {
4445
let arguments = (ins StrAttr:$message);
4546
let results = (outs Cxx_ExprType:$result);
4647
let assemblyFormat = "$message attr-dict `:` type($result)";
@@ -50,8 +51,69 @@ def Cxx_TodoExprOp : Cxx_Op<"todo.expr"> {
5051
];
5152
}
5253

53-
def Cxx_TodoStmtOp : Cxx_Op<"todo.stmt"> {
54+
def TodoStmtOp : Cxx_Op<"todo.stmt"> {
5455
let arguments = (ins StrAttr:$message);
5556
let results = (outs);
5657
let assemblyFormat = "$message attr-dict";
5758
}
59+
60+
def ToBoolOp : Cxx_Op<"to.bool"> {
61+
let arguments = (ins Cxx_ExprType:$value);
62+
let results = (outs I1:$result);
63+
let assemblyFormat = "`(` $value `)` attr-dict `:` type($result)";
64+
}
65+
66+
def ImplicitCastOp : Cxx_Op<"implicit.cast"> {
67+
let arguments = (ins StrAttr:$cast, Cxx_ExprType:$value);
68+
let results = (outs Cxx_ExprType:$result);
69+
let assemblyFormat = "$cast `(` $value `)` attr-dict `:` type($result)";
70+
let builders = [
71+
OpBuilder<(ins "llvm::StringRef":$cast, "mlir::Value":$value),
72+
[{ build($_builder, $_state, $_builder.getType<ExprType>(), cast, value); }]>,
73+
];
74+
}
75+
76+
def IntLiteralOp : Cxx_Op<"int.literal"> {
77+
let arguments = (ins I64Attr:$value);
78+
let results = (outs Cxx_ExprType:$result);
79+
let assemblyFormat = "$value attr-dict `:` type($result)";
80+
let builders = [
81+
OpBuilder<(ins "int64_t":$value),
82+
[{ build($_builder, $_state, $_builder.getType<ExprType>(), value); }]>,
83+
];
84+
}
85+
86+
def IdOp : Cxx_Op<"id"> {
87+
let arguments = (ins StrAttr:$name);
88+
let results = (outs Cxx_ExprType:$result);
89+
let assemblyFormat = "$name attr-dict `:` type($result)";
90+
let builders = [
91+
OpBuilder<(ins "llvm::StringRef":$name),
92+
[{ build($_builder, $_state, $_builder.getType<ExprType>(), name); }]>,
93+
];
94+
}
95+
96+
def BinOp : Cxx_Op<"binary"> {
97+
let arguments = (ins StrAttr:$op, Cxx_ExprType:$lhs, Cxx_ExprType:$rhs);
98+
let results = (outs Cxx_ExprType:$result);
99+
let assemblyFormat = "`op` $op `(` $lhs `,` $rhs `)` attr-dict `:` type($result)";
100+
let builders = [
101+
OpBuilder<(ins "llvm::StringRef":$op, "mlir::Value":$lhs, "mlir::Value":$rhs),
102+
[{ build($_builder, $_state, $_builder.getType<ExprType>(), op, lhs, rhs); }]>,
103+
];
104+
}
105+
106+
def CallOp : Cxx_Op<"call"> {
107+
let arguments = (ins Cxx_ExprType:$callee, Variadic<AnyType>:$arguments);
108+
let results = (outs Cxx_ExprType:$result);
109+
let assemblyFormat = "$callee `(` $arguments `:` type($arguments) `)` attr-dict `:` type($result)";
110+
let builders = [
111+
OpBuilder<(ins "mlir::Value":$callee, "mlir::ValueRange":$arguments),
112+
[{ build($_builder, $_state, $_builder.getType<ExprType>(), callee, arguments); }]>,
113+
];
114+
}
115+
116+
def ReturnOp : Cxx_Op<"return"> {
117+
let arguments = (ins Optional<Cxx_ExprType>:$value);
118+
let results = (outs);
119+
}

src/mlir/cxx/mlir/codegen.cc

Lines changed: 80 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,13 @@
3030
#include <cxx/names.h>
3131
#include <cxx/symbols.h>
3232
#include <cxx/translation_unit.h>
33+
#include <cxx/type_printer.h>
3334
#include <cxx/types.h>
35+
#include <mlir/Dialect/ControlFlow/IR/ControlFlowOps.h>
3436
#include <mlir/Dialect/Func/IR/FuncOps.h>
37+
#include <mlir/Dialect/SCF/IR/SCF.h>
3538

36-
#if __has_include(<cxxabi.h>)
37-
#include <cxxabi.h>
38-
#endif
39+
#include <format>
3940

4041
namespace cxx {
4142

@@ -638,13 +639,19 @@ Codegen::~Codegen() {}
638639

639640
auto Codegen::control() const -> Control* { return unit_->control(); }
640641

641-
auto Codegen::emitTodoStmt(SourceLocation location, std::string_view message)
642-
-> mlir::cxx::TodoStmtOp {
643-
#if true
642+
auto Codegen::getLocation(SourceLocation location) -> mlir::Location {
644643
auto [filename, line, column] = unit_->tokenStartPosition(location);
645644

646645
auto loc =
647646
mlir::FileLineColLoc::get(builder_.getContext(), filename, line, column);
647+
648+
return loc;
649+
}
650+
651+
auto Codegen::emitTodoStmt(SourceLocation location, std::string_view message)
652+
-> mlir::cxx::TodoStmtOp {
653+
#if true
654+
auto loc = getLocation(location);
648655
#else
649656
auto loc = builder_.getUnknownLoc();
650657
#endif
@@ -656,10 +663,7 @@ auto Codegen::emitTodoStmt(SourceLocation location, std::string_view message)
656663
auto Codegen::emitTodoExpr(SourceLocation location, std::string_view message)
657664
-> mlir::cxx::TodoExprOp {
658665
#if true
659-
auto [filename, line, column] = unit_->tokenStartPosition(location);
660-
661-
auto loc =
662-
mlir::FileLineColLoc::get(builder_.getContext(), filename, line, column);
666+
auto loc = getLocation(location);
663667
#else
664668
auto loc = builder_.getUnknownLoc();
665669
#endif
@@ -1218,7 +1222,7 @@ auto Codegen::DeclarationVisitor::operator()(FunctionDefinitionAST* ast)
12181222
// generate unique names until we have proper name mangling
12191223
name += std::format("_{}", ++gen.count_);
12201224

1221-
auto savedInsertionPoint = gen.builder_.getInsertionBlock();
1225+
auto savedInsertionPoint = gen.builder_.saveInsertionPoint();
12221226

12231227
auto func = gen.builder_.create<mlir::func::FuncOp>(loc, name, funcType);
12241228

@@ -1247,7 +1251,7 @@ auto Codegen::DeclarationVisitor::operator()(FunctionDefinitionAST* ast)
12471251

12481252
gen.builder_.create<mlir::func::ReturnOp>(gen.builder_.getUnknownLoc());
12491253

1250-
gen.builder_.setInsertionPointToEnd(savedInsertionPoint);
1254+
gen.builder_.restoreInsertionPoint(savedInsertionPoint);
12511255

12521256
return {};
12531257
}
@@ -1455,9 +1459,6 @@ auto Codegen::StatementVisitor::operator()(ExpressionStatementAST* ast)
14551459

14561460
auto Codegen::StatementVisitor::operator()(CompoundStatementAST* ast)
14571461
-> StatementResult {
1458-
auto op =
1459-
gen.emitTodoStmt(ast->firstSourceLocation(), "CompoundStatementAST");
1460-
14611462
for (auto node : ListView{ast->statementList}) {
14621463
auto value = gen(node);
14631464
}
@@ -1467,12 +1468,31 @@ auto Codegen::StatementVisitor::operator()(CompoundStatementAST* ast)
14671468

14681469
auto Codegen::StatementVisitor::operator()(IfStatementAST* ast)
14691470
-> StatementResult {
1470-
auto op = gen.emitTodoStmt(ast->firstSourceLocation(), "IfStatementAST");
1471-
14721471
auto initializerResult = gen(ast->initializer);
1472+
14731473
auto conditionResult = gen(ast->condition);
1474-
auto statementResult = gen(ast->statement);
1475-
auto elseStatementResult = gen(ast->elseStatement);
1474+
1475+
auto condition = gen.builder_.create<mlir::cxx::ToBoolOp>(
1476+
gen.getLocation(ast->ifLoc), gen.builder_.getI1Type(),
1477+
conditionResult.value);
1478+
1479+
auto ifOp = gen.builder_.create<mlir::scf::IfOp>(gen.getLocation(ast->ifLoc),
1480+
condition,
1481+
/*withElse=*/true);
1482+
1483+
auto ip = gen.builder_.saveInsertionPoint();
1484+
1485+
if (ast->statement) {
1486+
gen.builder_.setInsertionPointToStart(&ifOp.getThenRegion().front());
1487+
auto statementResult = gen(ast->statement);
1488+
}
1489+
1490+
if (ast->elseStatement) {
1491+
gen.builder_.setInsertionPointToStart(&ifOp.getElseRegion().front());
1492+
auto elseStatementResult = gen(ast->elseStatement);
1493+
}
1494+
1495+
gen.builder_.restoreInsertionPoint(ip);
14761496

14771497
return {};
14781498
}
@@ -1560,9 +1580,13 @@ auto Codegen::StatementVisitor::operator()(ContinueStatementAST* ast)
15601580

15611581
auto Codegen::StatementVisitor::operator()(ReturnStatementAST* ast)
15621582
-> StatementResult {
1563-
auto op = gen.emitTodoStmt(ast->firstSourceLocation(), "ReturnStatementAST");
1564-
15651583
auto expressionResult = gen(ast->expression);
1584+
1585+
auto loc = gen.getLocation(ast->firstSourceLocation());
1586+
1587+
auto op =
1588+
gen.builder_.create<mlir::cxx::ReturnOp>(loc, expressionResult.value);
1589+
15661590
return {};
15671591
}
15681592

@@ -1629,8 +1653,11 @@ auto Codegen::ExpressionVisitor::operator()(BoolLiteralExpressionAST* ast)
16291653

16301654
auto Codegen::ExpressionVisitor::operator()(IntLiteralExpressionAST* ast)
16311655
-> ExpressionResult {
1632-
auto op =
1633-
gen.emitTodoExpr(ast->firstSourceLocation(), "IntLiteralExpressionAST");
1656+
auto loc = gen.getLocation(ast->literalLoc);
1657+
1658+
auto op = gen.builder_.create<mlir::cxx::IntLiteralOp>(
1659+
loc, ast->literal->integerValue());
1660+
16341661
return {op};
16351662
}
16361663

@@ -1685,9 +1712,18 @@ auto Codegen::ExpressionVisitor::operator()(NestedExpressionAST* ast)
16851712

16861713
auto Codegen::ExpressionVisitor::operator()(IdExpressionAST* ast)
16871714
-> ExpressionResult {
1688-
auto op = gen.emitTodoExpr(ast->firstSourceLocation(), "IdExpressionAST");
16891715
auto nestedNameSpecifierResult = gen(ast->nestedNameSpecifier);
16901716
auto unqualifiedIdResult = gen(ast->unqualifiedId);
1717+
1718+
if (auto id = ast_cast<NameIdAST>(ast->unqualifiedId);
1719+
id && !ast->nestedNameSpecifier) {
1720+
auto loc = gen.getLocation(ast->firstSourceLocation());
1721+
auto name = id->identifier->name();
1722+
auto op = gen.builder_.create<mlir::cxx::IdOp>(loc, name);
1723+
return {op};
1724+
}
1725+
1726+
auto op = gen.emitTodoExpr(ast->firstSourceLocation(), "IdExpressionAST");
16911727
return {op};
16921728
}
16931729

@@ -1788,14 +1824,20 @@ auto Codegen::ExpressionVisitor::operator()(SubscriptExpressionAST* ast)
17881824

17891825
auto Codegen::ExpressionVisitor::operator()(CallExpressionAST* ast)
17901826
-> ExpressionResult {
1791-
auto op = gen.emitTodoExpr(ast->firstSourceLocation(), "CallExpressionAST");
1792-
17931827
auto baseExpressionResult = gen(ast->baseExpression);
17941828

1829+
std::vector<mlir::Value> arguments;
1830+
17951831
for (auto node : ListView{ast->expressionList}) {
17961832
auto value = gen(node);
1833+
arguments.push_back(value.value);
17971834
}
17981835

1836+
auto loc = gen.getLocation(ast->lparenLoc);
1837+
1838+
auto op = gen.builder_.create<mlir::cxx::CallOp>(
1839+
loc, baseExpressionResult.value, arguments);
1840+
17991841
return {op};
18001842
}
18011843

@@ -2064,21 +2106,28 @@ auto Codegen::ExpressionVisitor::operator()(CastExpressionAST* ast)
20642106

20652107
auto Codegen::ExpressionVisitor::operator()(ImplicitCastExpressionAST* ast)
20662108
-> ExpressionResult {
2067-
auto op =
2068-
gen.emitTodoExpr(ast->firstSourceLocation(), "ImplicitCastExpressionAST");
2069-
20702109
auto expressionResult = gen(ast->expression);
20712110

2111+
auto loc = gen.getLocation(ast->firstSourceLocation());
2112+
2113+
auto op = gen.builder_.create<mlir::cxx::ImplicitCastOp>(
2114+
loc, to_string(ast->castKind), expressionResult.value);
2115+
20722116
return {op};
20732117
}
20742118

20752119
auto Codegen::ExpressionVisitor::operator()(BinaryExpressionAST* ast)
20762120
-> ExpressionResult {
2077-
auto op = gen.emitTodoExpr(ast->firstSourceLocation(), "BinaryExpressionAST");
2078-
20792121
auto leftExpressionResult = gen(ast->leftExpression);
20802122
auto rightExpressionResult = gen(ast->rightExpression);
20812123

2124+
auto loc = gen.getLocation(ast->opLoc);
2125+
2126+
auto operation = Token::spell(ast->op);
2127+
2128+
auto op = gen.builder_.create<mlir::cxx::BinOp>(
2129+
loc, operation, leftExpressionResult.value, rightExpressionResult.value);
2130+
20822131
return {op};
20832132
}
20842133

src/mlir/cxx/mlir/codegen.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,10 +163,12 @@ class Codegen {
163163
-> NestedNamespaceSpecifierResult;
164164

165165
private:
166-
auto emitTodoStmt(SourceLocation loc, std::string_view message)
166+
[[nodiscard]] auto getLocation(SourceLocation loc) -> mlir::Location;
167+
168+
[[nodiscard]] auto emitTodoStmt(SourceLocation loc, std::string_view message)
167169
-> mlir::cxx::TodoStmtOp;
168170

169-
auto emitTodoExpr(SourceLocation loc, std::string_view message)
171+
[[nodiscard]] auto emitTodoExpr(SourceLocation loc, std::string_view message)
170172
-> mlir::cxx::TodoExprOp;
171173

172174
struct UnitVisitor;

src/mlir/cxx/mlir/cxx_dialect.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <llvm/ADT/TypeSwitch.h>
2525
#include <mlir/Dialect/ControlFlow/IR/ControlFlowOps.h>
2626
#include <mlir/Dialect/Func/IR/FuncOps.h>
27+
#include <mlir/Dialect/SCF/IR/SCF.h>
2728
#include <mlir/IR/Builders.h>
2829
#include <mlir/IR/DialectImplementation.h>
2930

src/parser/cxx/cli.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,9 +155,9 @@ std::vector<CLIOptionDescr> options{
155155

156156
{"-emit-ast", "Emit AST files for source inputs", &CLI::opt_emit_ast},
157157

158-
{"-ast-dump", "Build ASTs and then debug dump them", &CLI::opt_ast_dump},
158+
{"-emit-ir", "Emit the IR for the source inputs", &CLI::opt_emit_ir},
159159

160-
{"-ir-dump", "Dump the IR", &CLI::opt_ir_dump},
160+
{"-ast-dump", "Build ASTs and then debug dump them", &CLI::opt_ast_dump},
161161

162162
{"-dump-symbols", "Dump the symbol tables", &CLI::opt_dump_symbols},
163163

src/parser/cxx/cli.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ class CLI {
5252

5353
std::string app_name;
5454
bool opt_ast_dump = false;
55-
bool opt_ir_dump = false;
55+
bool opt_emit_ir = false;
5656
bool opt_dM = false;
5757
bool opt_dump_symbols = false;
5858
bool opt_dump_tokens = false;

0 commit comments

Comments
 (0)