Skip to content

Commit 2f0750d

Browse files
committed
[mlir] Add Cpp emitter
This upstreams the Cpp emitter, initially presented with [1], from [2] to MLIR core. Together with the previously upstreamed EmitC dialect [3], the target allows to translate MLIR to C/C++. [1] https://reviews.llvm.org/D76571 [2] https://github.com/iml130/mlir-emitc [3] https://reviews.llvm.org/D103969 Co-authored-by: Jacques Pienaar <[email protected]> Co-authored-by: Simon Camphausen <[email protected]> Co-authored-by: Oliver Scherf <[email protected]> Reviewed By: jpienaar Differential Revision: https://reviews.llvm.org/D104632
1 parent 8647e4c commit 2f0750d

File tree

16 files changed

+1714
-0
lines changed

16 files changed

+1714
-0
lines changed

mlir/docs/Dialects/emitc.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
The EmitC dialect allows to convert operations from other MLIR dialects to
2+
EmitC ops. Those can be translated to C/C++ via the Cpp emitter.
3+
4+
The following convention is followed:
5+
6+
* If template arguments are passed to an `emitc.call` operation,
7+
C++ is generated.
8+
* If tensors are used, C++ is generated.
9+
* If multiple return values are used within in a functions or an
10+
`emitc.call` operation, C++11 is required.
11+
* If floating-point type template arguments are passed to an `emitc.call`
12+
operation, C++20 is required.
13+
* Else the generated code is compatible with C99.
14+
15+
These restrictions are neither inherent to the EmitC dialect itself nor to the
16+
Cpp emitter and therefore need to be considered while implementing conversions.
17+
18+
After the conversion, C/C++ code can be emitted with `mlir-translate`. The tool
19+
support translating MLIR to C/C++ by passing `-mlir-to-cpp`.
20+
Furthermore, code with variables declared at top can be generated by passing
21+
`-mlir-to-cpp-with-variable-declarations-at-top`.
22+
23+
Besides operations part of the EmitC dialect, the Cpp targets supports
24+
translating the following operations:
25+
26+
* 'std' Dialect
27+
* `std.br`
28+
* `std.call`
29+
* `std.cond_br`
30+
* `std.constant`
31+
* `std.return`
32+
* 'scf' Dialect
33+
* `scf.for`
34+
* `scf.yield`

mlir/include/mlir/Dialect/EmitC/IR/EmitCBase.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ include "mlir/IR/OpBase.td"
2222
def EmitC_Dialect : Dialect {
2323
let name = "emitc";
2424
let cppNamespace = "::mlir::emitc";
25+
26+
let summary = "Dialect to generate C/C++ from MLIR.";
27+
let description = [{
28+
[include "Dialects/emitc.md"]
29+
}];
30+
2531
let hasConstantMaterializer = 1;
2632
}
2733

mlir/include/mlir/InitAllTranslations.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ namespace mlir {
1818

1919
void registerFromLLVMIRTranslation();
2020
void registerFromSPIRVTranslation();
21+
void registerToCppTranslation();
2122
void registerToLLVMIRTranslation();
2223
void registerToSPIRVTranslation();
2324

@@ -28,6 +29,7 @@ inline void registerAllTranslations() {
2829
static bool initOnce = []() {
2930
registerFromLLVMIRTranslation();
3031
registerFromSPIRVTranslation();
32+
registerToCppTranslation();
3133
registerToLLVMIRTranslation();
3234
registerToSPIRVTranslation();
3335
return true;
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//===- CppEmitter.h - Helpers to create C++ emitter -------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file defines helpers to emit C++ code using the EmitC dialect.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef MLIR_TARGET_CPP_CPPEMITTER_H
14+
#define MLIR_TARGET_CPP_CPPEMITTER_H
15+
16+
#include "mlir/IR/BuiltinTypes.h"
17+
#include "mlir/IR/Value.h"
18+
#include "llvm/ADT/ScopedHashTable.h"
19+
#include "llvm/Support/raw_ostream.h"
20+
#include <stack>
21+
22+
namespace mlir {
23+
namespace emitc {
24+
25+
/// Translates the given operation to C++ code. The operation or operations in
26+
/// the region of 'op' need almost all be in EmitC dialect. The parameter
27+
/// 'declareVariablesAtTop' enforces that all variables for op results and block
28+
/// arguments are declared at the beginning of the function.
29+
LogicalResult translateToCpp(Operation *op, raw_ostream &os,
30+
bool declareVariablesAtTop = false);
31+
} // namespace emitc
32+
} // namespace mlir
33+
34+
#endif // MLIR_TARGET_CPP_CPPEMITTER_H

mlir/lib/Target/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1+
add_subdirectory(Cpp)
12
add_subdirectory(SPIRV)
23
add_subdirectory(LLVMIR)

mlir/lib/Target/Cpp/CMakeLists.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
add_mlir_translation_library(MLIRTargetCpp
2+
TranslateRegistration.cpp
3+
TranslateToCpp.cpp
4+
5+
ADDITIONAL_HEADER_DIRS
6+
${EMITC_MAIN_INCLUDE_DIR}/emitc/Target/Cpp
7+
8+
LINK_LIBS PUBLIC
9+
MLIREmitC
10+
MLIRIR
11+
MLIRSCF
12+
MLIRStandard
13+
MLIRSupport
14+
)
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//===- TranslateRegistration.cpp - Register translation -------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "mlir/Dialect/EmitC/IR/EmitC.h"
10+
#include "mlir/Dialect/SCF/SCF.h"
11+
#include "mlir/Dialect/StandardOps/IR/Ops.h"
12+
#include "mlir/IR/BuiltinOps.h"
13+
#include "mlir/IR/Dialect.h"
14+
#include "mlir/Target/Cpp/CppEmitter.h"
15+
#include "mlir/Translation.h"
16+
#include "llvm/Support/CommandLine.h"
17+
18+
using namespace mlir;
19+
20+
namespace mlir {
21+
22+
//===----------------------------------------------------------------------===//
23+
// Cpp registration
24+
//===----------------------------------------------------------------------===//
25+
26+
void registerToCppTranslation() {
27+
static llvm::cl::opt<bool> declareVariablesAtTop(
28+
"declare-variables-at-top",
29+
llvm::cl::desc("Declare variables at top when emitting C/C++"),
30+
llvm::cl::init(false));
31+
32+
TranslateFromMLIRRegistration reg(
33+
"mlir-to-cpp",
34+
[](ModuleOp module, raw_ostream &output) {
35+
return emitc::translateToCpp(
36+
module, output,
37+
/*declareVariablesAtTop=*/declareVariablesAtTop);
38+
},
39+
[](DialectRegistry &registry) {
40+
// clang-format off
41+
registry.insert<emitc::EmitCDialect,
42+
StandardOpsDialect,
43+
scf::SCFDialect>();
44+
// clang-format on
45+
});
46+
}
47+
48+
} // namespace mlir

0 commit comments

Comments
 (0)