Skip to content

Commit

Permalink
Merge pull request #393 from Xilinx/matthias.emitc_tu
Browse files Browse the repository at this point in the history
Add emitc.tu
  • Loading branch information
mgehre-amd authored Nov 6, 2024
2 parents ad4697c + a64ebcc commit cab7e24
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 9 deletions.
43 changes: 43 additions & 0 deletions mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ include "mlir/Interfaces/CastInterfaces.td"
include "mlir/Interfaces/ControlFlowInterfaces.td"
include "mlir/Interfaces/FunctionInterfaces.td"
include "mlir/Interfaces/SideEffectInterfaces.td"
include "mlir/IR/OpAsmInterface.td"
include "mlir/IR/RegionKindInterface.td"
include "mlir/IR/BuiltinAttributes.td"

//===----------------------------------------------------------------------===//
// EmitC op definitions
Expand Down Expand Up @@ -55,6 +57,47 @@ def IntegerIndexOrOpaqueType : Type<CPred<"emitc::isIntegerIndexOrOpaqueType($_s
"integer, index or opaque type supported by EmitC">;
def FloatIntegerIndexOrOpaqueType : AnyTypeOf<[EmitCFloatType, IntegerIndexOrOpaqueType]>;

def EmitC_TranslationUnitOp : EmitC_Op<"tu",
[IsolatedFromAbove, NoRegionArguments, SymbolTable,
OpAsmOpInterface
] # GraphRegionNoTerminator.traits> {
let summary = "A translation unit container operation";
let description = [{
A `tu` represents a translation unit that can be emitted
into a single C++ file.

`mlir-translate` emits only the translation unit selected via
the `-translation-unit-id=id` flag. By default, no translation units are
emitted.

Example:

```mlir
emitc.tu "main" {
emitc.func @func_one() {
emitc.return
}
}
```
}];

let arguments = (ins Builtin_StringAttr:$id);
let regions = (region SizedRegion<1>:$bodyRegion);

let assemblyFormat = "$id attr-dict-with-keyword $bodyRegion";
let extraClassDeclaration = [{
//===------------------------------------------------------------------===//
// OpAsmOpInterface Methods
//===------------------------------------------------------------------===//

/// EmitC ops in the body of the translation_unit can omit their 'emitc.'
/// prefix in the assembly.
static ::llvm::StringRef getDefaultDialect() {
return "emitc";
}
}];
}

def EmitC_AddOp : EmitC_BinaryOp<"add", [CExpression]> {
let summary = "Addition operation";
let description = [{
Expand Down
4 changes: 3 additions & 1 deletion mlir/include/mlir/Target/Cpp/CppEmitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#define MLIR_TARGET_CPP_CPPEMITTER_H

#include "mlir/Support/LLVM.h"
#include "llvm/ADT/StringRef.h"

namespace mlir {
class Operation;
Expand All @@ -24,7 +25,8 @@ namespace emitc {
/// 'declareVariablesAtTop' enforces that all variables for op results and block
/// arguments are declared at the beginning of the function.
LogicalResult translateToCpp(Operation *op, raw_ostream &os,
bool declareVariablesAtTop = false);
bool declareVariablesAtTop = false,
StringRef onlyTu = "");
} // namespace emitc
} // namespace mlir

Expand Down
8 changes: 7 additions & 1 deletion mlir/lib/Target/Cpp/TranslateRegistration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,18 @@ void registerToCppTranslation() {
llvm::cl::desc("Declare variables at top when emitting C/C++"),
llvm::cl::init(false));

static llvm::cl::opt<std::string> onlyTu(
"translation-unit-id",
llvm::cl::desc("Only emit the translation unit with the matching id"),
llvm::cl::init(""));

TranslateFromMLIRRegistration reg(
"mlir-to-cpp", "translate from mlir to cpp",
[](Operation *op, raw_ostream &output) {
return emitc::translateToCpp(
op, output,
/*declareVariablesAtTop=*/declareVariablesAtTop);
/*declareVariablesAtTop=*/declareVariablesAtTop,
/*onlyTu=*/onlyTu);
},
[](DialectRegistry &registry) {
// clang-format off
Expand Down
37 changes: 30 additions & 7 deletions mlir/lib/Target/Cpp/TranslateToCpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ static FailureOr<int> getOperatorPrecedence(Operation *operation) {
namespace {
/// Emitter that uses dialect specific emitters to emit C++ code.
struct CppEmitter {
explicit CppEmitter(raw_ostream &os, bool declareVariablesAtTop);
explicit CppEmitter(raw_ostream &os, bool declareVariablesAtTop,
StringRef onlyTu);

/// Emits attribute or returns failure.
LogicalResult emitAttribute(Location loc, Attribute attr);
Expand Down Expand Up @@ -231,6 +232,9 @@ struct CppEmitter {
/// be declared at the beginning of a function.
bool shouldDeclareVariablesAtTop() { return declareVariablesAtTop; };

/// Returns whether this translation unit should be emitted
bool shouldEmitTu(TranslationUnitOp tu) { return tu.getId() == onlyTu; }

/// Get expression currently being emitted.
ExpressionOp getEmittedExpression() { return emittedExpression; }

Expand Down Expand Up @@ -258,6 +262,9 @@ struct CppEmitter {
/// includes results from ops located in nested regions.
bool declareVariablesAtTop;

/// Only emit translation units whos id matches this value.
std::string onlyTu;

/// Map from value to name of C++ variable that contain the name.
ValueMapper valueMapper;

Expand Down Expand Up @@ -936,6 +943,19 @@ static LogicalResult printOperation(CppEmitter &emitter, ModuleOp moduleOp) {
return success();
}

static LogicalResult printOperation(CppEmitter &emitter, TranslationUnitOp tu) {
if (!emitter.shouldEmitTu(tu))
return success();

CppEmitter::Scope scope(emitter);

for (Operation &op : tu) {
if (failed(emitter.emitOperation(op, /*trailingSemicolon=*/false)))
return failure();
}
return success();
}

template <class FuncOpClass>
static LogicalResult printFunctionArgs(CppEmitter &emitter,
FuncOpClass functionOp,
Expand Down Expand Up @@ -1177,8 +1197,10 @@ static LogicalResult printOperation(CppEmitter &emitter,
return success();
}

CppEmitter::CppEmitter(raw_ostream &os, bool declareVariablesAtTop)
: os(os), declareVariablesAtTop(declareVariablesAtTop) {
CppEmitter::CppEmitter(raw_ostream &os, bool declareVariablesAtTop,
StringRef onlyTu)
: os(os), declareVariablesAtTop(declareVariablesAtTop),
onlyTu(onlyTu.str()) {
valueInScopeCount.push(0);
labelInScopeCount.push(0);
}
Expand Down Expand Up @@ -1580,8 +1602,8 @@ LogicalResult CppEmitter::emitOperation(Operation &op, bool trailingSemicolon) {
emitc::GlobalOp, emitc::IfOp, emitc::IncludeOp,
emitc::LogicalAndOp, emitc::LogicalNotOp, emitc::LogicalOrOp,
emitc::MulOp, emitc::RemOp, emitc::ReturnOp, emitc::SubOp,
emitc::UnaryMinusOp, emitc::UnaryPlusOp, emitc::VariableOp,
emitc::VerbatimOp>(
emitc::TranslationUnitOp, emitc::UnaryMinusOp,
emitc::UnaryPlusOp, emitc::VariableOp, emitc::VerbatimOp>(
[&](auto op) { return printOperation(*this, op); })
// Func ops.
.Case<func::CallOp, func::FuncOp, func::ReturnOp>(
Expand Down Expand Up @@ -1791,7 +1813,8 @@ LogicalResult CppEmitter::emitTupleType(Location loc, ArrayRef<Type> types) {
}

LogicalResult emitc::translateToCpp(Operation *op, raw_ostream &os,
bool declareVariablesAtTop) {
CppEmitter emitter(os, declareVariablesAtTop);
bool declareVariablesAtTop,
StringRef onlyTu) {
CppEmitter emitter(os, declareVariablesAtTop, onlyTu);
return emitter.emitOperation(*op, /*trailingSemicolon=*/false);
}
29 changes: 29 additions & 0 deletions mlir/test/Target/Cpp/tu.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// RUN: mlir-translate -mlir-to-cpp %s | FileCheck %s --check-prefix NO-FILTER
// RUN: mlir-translate -mlir-to-cpp -translation-unit-id=non-existing %s | FileCheck %s --check-prefix NON-EXISTING
// RUN: mlir-translate -mlir-to-cpp -translation-unit-id=tu_one %s | FileCheck %s --check-prefix TU-ONE
// RUN: mlir-translate -mlir-to-cpp -translation-unit-id=tu_two %s | FileCheck %s --check-prefix TU-TWO


// NO-FILTER-NOT: func_one
// NO-FILTER-NOT: func_two

// NON-EXISTING-NOT: func_one
// NON-EXISTING-NOT: func_two

// TU-ONE: func_one
// TU-ONE-NOT: func_two

// TU-TWO-NOT: func_one
// TU-TWO: func_two

emitc.tu "tu_one" {
emitc.func @func_one(%arg: f32) {
emitc.return
}
}

emitc.tu "tu_two" {
emitc.func @func_two(%arg: f32) {
emitc.return
}
}

0 comments on commit cab7e24

Please sign in to comment.