-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[MLIR] emitc: Add emitc.file op #123298
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[MLIR] emitc: Add emitc.file op #123298
Conversation
@llvm/pr-subscribers-mlir-emitc Author: Matthias Gehre (mgehre-amd) ChangesA This allows to manage multiple translation units within the same MLIR module, but emit them into separate files. When specifying the Example: emitc.tu "main" {
func @<!-- -->func_one() {
return
}
}
emitc.tu "test" {
func @<!-- -->func_two() {
return
}
}
Full diff: https://github.com/llvm/llvm-project/pull/123298.diff 6 Files Affected:
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
index b16f5a8619fe7b..1fe4e34b3fa5ab 100644
--- a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
@@ -23,6 +23,7 @@ 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
@@ -56,6 +57,54 @@ 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 builders = [OpBuilder<(ins CArg<"StringRef">:$id)>];
+ let extraClassDeclaration = [{
+ /// Construct a module from the given location with an optional name.
+ static TranslationUnitOp create(Location loc, StringRef name);
+
+ //===------------------------------------------------------------------===//
+ // 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";
+ }
+ }];
+
+ // We need to ensure that the body region has a block;
+ // the auto-generated builders do not guarantee that.
+ let skipDefaultBuilders = 1;
+}
+
def EmitC_AddOp : EmitC_BinaryOp<"add", [CExpression]> {
let summary = "Addition operation";
let description = [{
diff --git a/mlir/include/mlir/Target/Cpp/CppEmitter.h b/mlir/include/mlir/Target/Cpp/CppEmitter.h
index 99d8696cc8e077..d76cfc9107332e 100644
--- a/mlir/include/mlir/Target/Cpp/CppEmitter.h
+++ b/mlir/include/mlir/Target/Cpp/CppEmitter.h
@@ -14,6 +14,7 @@
#define MLIR_TARGET_CPP_CPPEMITTER_H
#include "mlir/Support/LLVM.h"
+#include "llvm/ADT/StringRef.h"
namespace mlir {
class Operation;
@@ -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
diff --git a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
index fdc21d6c6e24b9..b51221b721dde3 100644
--- a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
+++ b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
@@ -1289,6 +1289,16 @@ void SwitchOp::getRegionInvocationBounds(
bounds.emplace_back(/*lb=*/0, /*ub=*/regIndex == liveIndex);
}
+//===----------------------------------------------------------------------===//
+// TranslationUnitOp
+//===----------------------------------------------------------------------===//
+void TranslationUnitOp::build(OpBuilder &builder, OperationState &state,
+ StringRef id) {
+ state.addRegion()->emplaceBlock();
+ state.attributes.push_back(
+ builder.getNamedAttr("id", builder.getStringAttr(id)));
+}
+
//===----------------------------------------------------------------------===//
// TableGen'd op method definitions
//===----------------------------------------------------------------------===//
diff --git a/mlir/lib/Target/Cpp/TranslateRegistration.cpp b/mlir/lib/Target/Cpp/TranslateRegistration.cpp
index 1aa98834a73f49..7e2bc9ad012b38 100644
--- a/mlir/lib/Target/Cpp/TranslateRegistration.cpp
+++ b/mlir/lib/Target/Cpp/TranslateRegistration.cpp
@@ -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 ®istry) {
// clang-format off
diff --git a/mlir/lib/Target/Cpp/TranslateToCpp.cpp b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
index a91f5ab9311401..c9d66ad349db52 100644
--- a/mlir/lib/Target/Cpp/TranslateToCpp.cpp
+++ b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
@@ -114,7 +114,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);
@@ -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; }
@@ -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;
@@ -960,6 +967,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();
+}
+
static LogicalResult printFunctionArgs(CppEmitter &emitter,
Operation *functionOp,
ArrayRef<Type> arguments) {
@@ -1159,8 +1179,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);
}
@@ -1561,8 +1583,9 @@ LogicalResult CppEmitter::emitOperation(Operation &op, bool trailingSemicolon) {
emitc::GlobalOp, emitc::IfOp, emitc::IncludeOp, emitc::LoadOp,
emitc::LogicalAndOp, emitc::LogicalNotOp, emitc::LogicalOrOp,
emitc::MulOp, emitc::RemOp, emitc::ReturnOp, emitc::SubOp,
- emitc::SwitchOp, emitc::UnaryMinusOp, emitc::UnaryPlusOp,
- emitc::VariableOp, emitc::VerbatimOp>(
+ emitc::SwitchOp, 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>(
@@ -1742,7 +1765,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);
}
diff --git a/mlir/test/Target/Cpp/tu.mlir b/mlir/test/Target/Cpp/tu.mlir
new file mode 100644
index 00000000000000..ca10e0263a64fc
--- /dev/null
+++ b/mlir/test/Target/Cpp/tu.mlir
@@ -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
+ }
+}
|
@llvm/pr-subscribers-mlir Author: Matthias Gehre (mgehre-amd) ChangesA This allows to manage multiple translation units within the same MLIR module, but emit them into separate files. When specifying the Example: emitc.tu "main" {
func @<!-- -->func_one() {
return
}
}
emitc.tu "test" {
func @<!-- -->func_two() {
return
}
}
Full diff: https://github.com/llvm/llvm-project/pull/123298.diff 6 Files Affected:
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
index b16f5a8619fe7b..1fe4e34b3fa5ab 100644
--- a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
@@ -23,6 +23,7 @@ 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
@@ -56,6 +57,54 @@ 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 builders = [OpBuilder<(ins CArg<"StringRef">:$id)>];
+ let extraClassDeclaration = [{
+ /// Construct a module from the given location with an optional name.
+ static TranslationUnitOp create(Location loc, StringRef name);
+
+ //===------------------------------------------------------------------===//
+ // 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";
+ }
+ }];
+
+ // We need to ensure that the body region has a block;
+ // the auto-generated builders do not guarantee that.
+ let skipDefaultBuilders = 1;
+}
+
def EmitC_AddOp : EmitC_BinaryOp<"add", [CExpression]> {
let summary = "Addition operation";
let description = [{
diff --git a/mlir/include/mlir/Target/Cpp/CppEmitter.h b/mlir/include/mlir/Target/Cpp/CppEmitter.h
index 99d8696cc8e077..d76cfc9107332e 100644
--- a/mlir/include/mlir/Target/Cpp/CppEmitter.h
+++ b/mlir/include/mlir/Target/Cpp/CppEmitter.h
@@ -14,6 +14,7 @@
#define MLIR_TARGET_CPP_CPPEMITTER_H
#include "mlir/Support/LLVM.h"
+#include "llvm/ADT/StringRef.h"
namespace mlir {
class Operation;
@@ -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
diff --git a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
index fdc21d6c6e24b9..b51221b721dde3 100644
--- a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
+++ b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
@@ -1289,6 +1289,16 @@ void SwitchOp::getRegionInvocationBounds(
bounds.emplace_back(/*lb=*/0, /*ub=*/regIndex == liveIndex);
}
+//===----------------------------------------------------------------------===//
+// TranslationUnitOp
+//===----------------------------------------------------------------------===//
+void TranslationUnitOp::build(OpBuilder &builder, OperationState &state,
+ StringRef id) {
+ state.addRegion()->emplaceBlock();
+ state.attributes.push_back(
+ builder.getNamedAttr("id", builder.getStringAttr(id)));
+}
+
//===----------------------------------------------------------------------===//
// TableGen'd op method definitions
//===----------------------------------------------------------------------===//
diff --git a/mlir/lib/Target/Cpp/TranslateRegistration.cpp b/mlir/lib/Target/Cpp/TranslateRegistration.cpp
index 1aa98834a73f49..7e2bc9ad012b38 100644
--- a/mlir/lib/Target/Cpp/TranslateRegistration.cpp
+++ b/mlir/lib/Target/Cpp/TranslateRegistration.cpp
@@ -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 ®istry) {
// clang-format off
diff --git a/mlir/lib/Target/Cpp/TranslateToCpp.cpp b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
index a91f5ab9311401..c9d66ad349db52 100644
--- a/mlir/lib/Target/Cpp/TranslateToCpp.cpp
+++ b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
@@ -114,7 +114,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);
@@ -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; }
@@ -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;
@@ -960,6 +967,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();
+}
+
static LogicalResult printFunctionArgs(CppEmitter &emitter,
Operation *functionOp,
ArrayRef<Type> arguments) {
@@ -1159,8 +1179,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);
}
@@ -1561,8 +1583,9 @@ LogicalResult CppEmitter::emitOperation(Operation &op, bool trailingSemicolon) {
emitc::GlobalOp, emitc::IfOp, emitc::IncludeOp, emitc::LoadOp,
emitc::LogicalAndOp, emitc::LogicalNotOp, emitc::LogicalOrOp,
emitc::MulOp, emitc::RemOp, emitc::ReturnOp, emitc::SubOp,
- emitc::SwitchOp, emitc::UnaryMinusOp, emitc::UnaryPlusOp,
- emitc::VariableOp, emitc::VerbatimOp>(
+ emitc::SwitchOp, 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>(
@@ -1742,7 +1765,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);
}
diff --git a/mlir/test/Target/Cpp/tu.mlir b/mlir/test/Target/Cpp/tu.mlir
new file mode 100644
index 00000000000000..ca10e0263a64fc
--- /dev/null
+++ b/mlir/test/Target/Cpp/tu.mlir
@@ -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
+ }
+}
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Can you reformat this line, please; and maybe I'm reading this wrong, but I expected the code to emit all TUs if not filtered by the |
Quick question before having a change to take a deeper look. Would it make sense to introduce an |
I don't mind the naming. In practice, we use a structure like
and I liked that the |
I have reformulated the description. Does that sound better? |
At least in C99, "translation unit" seems to refer to the output of the preprocessor, i.e. the source file after all preprocessing directives have been expanded. As emitc supports emitting preprocessing directives, notably As C++20 defined a C++ |
Thanks, I didn't had C++20 modules in mind at that moment, but let's avoid this therefore. |
How about |
Thinking about the semantics of the proposed op, such a file-scope (a) Specifying the C dialect the (b) For offload/launch semantics such as in (c) Validation: Utilizing standard op validation to verify that all its internal ops are Would be good to discuss this op's designated uses to make sure we don't introduce backward compatibility later. |
I think this needs to be modeled in the dialect. With this you wouldn't pass a flag to the emitter but of course the emitter would need to know how to handle those ops with dialect information.
Not sure I see how this is related to a file-scope as proposed by this patch.
Adding a validation pass is something I started some time ago but didn't had time to finish. So yes, +1 from me. However, does it influence changed introduced by this patch?
Makes sense, yes. |
Thinking more about the naming I actually also ended several times with
Any further opinions or suggestions? |
Exactly. It could also guide the lowering process, e.g. by scalarizing vectors for C, implementing tuples as
So in order to support Another aspect is the necessity of a dedicated
So I was thinking whether the op should have a ::verify() method. Unless the translator itself runs such a verifying pass (which I'm not sure translators are supposed to do) this pass would be optional, letting users call the translator on invalid files. If we implement ::verify() the op would have to be introduced after all lowering to
Any other potential uses for this op? |
Adding an additional attribute later would not break compatibility. And we don't know yet if we actually going to get this, right?
I think that would work. It would limit us if we want to extend it in the future, e.g. by adding language standards to the scope.
I'm opposed to recursive verification in
I think we should be pragmatic here. A source file is a source file. If we need different more elaborate constructs, there is always the option to add new ops, or change existing onces. MLIR/emitc have not been backwards compatible, so we shouldn't make it too hard for us. In summary, I see consensus to rename this to Is there any objection to afterwards get this merged? I heard many ideas about possible extensions, |
Yes, that sounds reasonable to me.
Yes, with
👍
No objections. I would say, lets go ahead with |
Yes, IIUC we're all OK with changing its behavior later as needed, so let's move forward.
Agreed. |
e3524e5
to
cdf3b0a
Compare
A `emitc.file` represents a file that can be emitted into a single C++ file. This allows to manage multiple source files within the same MLIR module, but emit them into separate files. This feature is opt-in. By default, `mlir-translate` emits all ops outside of `emitc.file` and ignores all `emitc.file` ops and their bodies. When specifying the `-file-id=id` flag, `mlir-translate` emits all ops outside of `emitc.file` and the ops within the `emitc.file` with matching `id`. Example: ```mlir emitc.file "main" { func @func_one() { return } } emitc.file "test" { func @func_two() { return } } ``` `mlir-translate -file-id=main` will emit `func_one` and `mlir-translate -file-id=test` will emit `func_two`.
cdf3b0a
to
58b6d86
Compare
I updated the PR to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some quick comments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
A `emitc.file` represents a file that can be emitted into a single C++ file. This allows to manage multiple source files within the same MLIR module, but emit them into separate files. This feature is opt-in. By default, `mlir-translate` emits all ops outside of `emitc.file` and ignores all `emitc.file` ops and their bodies. When specifying the `-file-id=id` flag, `mlir-translate` emits all ops outside of `emitc.file` and the ops within the `emitc.file` with matching `id`. Example: ```mlir emitc.file "main" { func @func_one() { return } } emitc.file "test" { func @func_two() { return } } ``` `mlir-translate -file-id=main` will emit `func_one` and `mlir-translate -file-id=test` will emit `func_two`.
A
emitc.file
represents a file that can be emittedinto a single C++ file.
This allows to manage multiple source files within the same MLIR module,
but emit them into separate files.
This feature is opt-in.
By default,
mlir-translate
emits all ops outside ofemitc.file
and ignores all
emitc.file
ops and their bodies.When specifying the
-file-id=id
flag,mlir-translate
emits all ops outside ofemitc.file
andthe ops within the
emitc.file
with matchingid
.Example:
mlir-translate -file-id=main
will emitfunc_one
andmlir-translate -file-id=test
will emitfunc_two
.