Preserve iree.reflection attribute when converting from std.func -> vm.func.
PiperOrigin-RevId: 286500207
diff --git a/docs/function_abi.md b/docs/function_abi.md
index 0296a6a..bfd2002 100644
--- a/docs/function_abi.md
+++ b/docs/function_abi.md
@@ -52,7 +52,7 @@
'R' length-prefixed(type-sequence)
type-sequence ::= (arg-result-type)*
-arg-result-type ::= buffer-type | ref-object-type
+arg-result-type ::= buffer-type | ref-object-type | unrecognized-type
buffer-type ::= 'B' length-prefixed(scalar-type? dim*)
scalar-type ::= 't' (
'0' # IEEE float32 (default if not specified)
@@ -70,7 +70,7 @@
)
dim :: = 'd' integer # -1 indicates a dynamic dim
ref-object-type ::= 'O' length-prefixed() # Details TBD
-
+unrecognized-type ::= 'U' length-prefixed()
# Lexical primitives
integer ::= -?[0-9]+
diff --git a/iree/base/signature_mangle.cc b/iree/base/signature_mangle.cc
index 2009d6b..c156ceb 100644
--- a/iree/base/signature_mangle.cc
+++ b/iree/base/signature_mangle.cc
@@ -149,6 +149,10 @@
return func_builder;
}
+void RawSignatureMangler::AddUnrecognized() {
+ builder_.Span(absl::string_view(), 'U');
+}
+
void RawSignatureMangler::AddAnyReference() {
// A more constrained ref object would have a non empty span.
builder_.Span(absl::string_view(), 'O');
diff --git a/iree/base/signature_mangle.h b/iree/base/signature_mangle.h
index c398066..e1971e0 100644
--- a/iree/base/signature_mangle.h
+++ b/iree/base/signature_mangle.h
@@ -168,6 +168,10 @@
return ToFunctionSignature(inputs.builder(), results.builder());
}
+ // Adds an unrecognized type. By default, this is an empty span, but in the
+ // future, it may contain some further description.
+ void AddUnrecognized();
+
// Adds an unconstrained reference-type object.
void AddAnyReference();
diff --git a/iree/compiler/Dialect/Flow/Transforms/MaterializeExportedReflection.cpp b/iree/compiler/Dialect/Flow/Transforms/MaterializeExportedReflection.cpp
index ff806e4..f3969dd 100644
--- a/iree/compiler/Dialect/Flow/Transforms/MaterializeExportedReflection.cpp
+++ b/iree/compiler/Dialect/Flow/Transforms/MaterializeExportedReflection.cpp
@@ -94,8 +94,17 @@
auto mangledTensor = mangleTensorType(tensorType);
if (!mangledTensor) return nullptr;
mangledTensor->builder().AppendTo(fBuilder, tag);
+ return builder.getStringAttr(fBuilder.encoded());
}
+ return nullptr;
+}
+
+StringAttr unrecognizedTypeAttr(Builder builder, char tag) {
+ SignatureBuilder fBuilder;
+ RawSignatureMangler mangler;
+ mangler.AddUnrecognized();
+ mangler.builder().AppendTo(fBuilder, tag);
return builder.getStringAttr(fBuilder.encoded());
}
@@ -114,7 +123,13 @@
// Arguments.
for (int i = 0, e = funcType.getNumInputs(); i < e; ++i) {
auto mangled = mangleType(builder, funcType.getInput(i), 'I');
- if (!mangled) continue;
+ if (!mangled) {
+ func.emitWarning()
+ << "Argument #" << i << " of function " << func.getName()
+ << " is not a recognized public ABI type and the function"
+ << " may not be invokable by standard tools";
+ mangled = unrecognizedTypeAttr(builder, 'I');
+ }
NamedAttributeList l(
func.getArgAttrOfType<DictionaryAttr>(i, "iree.reflection"));
l.set(builder.getIdentifier("f_partial"), mangled);
@@ -124,7 +139,13 @@
// Results.
for (int i = 0, e = funcType.getNumResults(); i < e; ++i) {
auto mangled = mangleType(builder, funcType.getResult(i), 'R');
- if (!mangled) continue;
+ if (!mangled) {
+ func.emitWarning()
+ << "Result #" << i << " of function " << func.getName()
+ << " is not a recognized public ABI type and the function"
+ << " may not be invokable by standard tools";
+ mangled = unrecognizedTypeAttr(builder, 'R');
+ }
NamedAttributeList l(
func.getResultAttrOfType<DictionaryAttr>(i, "iree.reflection"));
l.set(builder.getIdentifier("f_partial"), mangled);
diff --git a/iree/compiler/Dialect/Flow/Transforms/Passes.cpp b/iree/compiler/Dialect/Flow/Transforms/Passes.cpp
index 58839e9..ecd5e26 100644
--- a/iree/compiler/Dialect/Flow/Transforms/Passes.cpp
+++ b/iree/compiler/Dialect/Flow/Transforms/Passes.cpp
@@ -93,16 +93,14 @@
// TODO(benvanik): run symbol DCE pass.
// Materialize default arg/result reflection metadata.
- // TODO(laurenzo): Enable this.
- // passManager.addPass(IREE::Flow::createMaterializeExportedReflection());
+ passManager.addPass(IREE::Flow::createMaterializeExportedReflection());
// Merge arg/result reflection metadata.
// NOTE(laurenzo): This will eventually not be the right place for this as
// it should happen after the HAL has further annotated the exported
// functions (which will be needed for dynamic shapes and synthetic barrier
// arguments).
- // TODO(laurenzo): Enable this.
- // passManager.addPass(IREE::Flow::createMergeExportedReflection());
+ passManager.addPass(IREE::Flow::createMergeExportedReflection());
}
static PassPipelineRegistration<> transformPassPipeline(
diff --git a/iree/compiler/Dialect/Flow/Transforms/test/materialize_exported_reflection.mlir b/iree/compiler/Dialect/Flow/Transforms/test/materialize_exported_reflection.mlir
index 2921d57..eaba6ab 100644
--- a/iree/compiler/Dialect/Flow/Transforms/test/materialize_exported_reflection.mlir
+++ b/iree/compiler/Dialect/Flow/Transforms/test/materialize_exported_reflection.mlir
@@ -19,6 +19,27 @@
}
// ----
+// CHECK-LABEL: func @unrecognizedArgument
+// CHECK-SAME: iree.reflection = {f_partial = "I4!U1!"}
+// expected-warning @+1 {{Argument #0 of function unrecognizedArgument is not a recognized public ABI type and the function may not be invokable by standard tools}}
+func @unrecognizedArgument(%arg0 : i1) -> ()
+ attributes {iree.module.export}
+{
+ return
+}
+
+// ----
+// CHECK-LABEL: func @unrecognizedResult
+// CHECK-SAME: iree.reflection = {f_partial = "R4!U1!"}
+// expected-warning @+1 {{Result #0 of function unrecognizedResult is not a recognized public ABI type and the function may not be invokable by standard tools}}
+func @unrecognizedResult() -> (i1)
+ attributes {iree.module.export}
+{
+ %0 = constant 0 : i1
+ return %0 : i1
+}
+
+// ----
// CHECK-LABEL: func @dynamicDim
// CHECK-SAME: iree.reflection = {f_partial = "I11!B8!t7d-1d4"}
func @dynamicDim(%arg0 : tensor<?x4xi64>) -> () attributes {iree.module.export}
diff --git a/iree/compiler/Dialect/VM/Conversion/StandardToVM/ConvertStandardToVM.cpp b/iree/compiler/Dialect/VM/Conversion/StandardToVM/ConvertStandardToVM.cpp
index e86465a..6ccb736 100644
--- a/iree/compiler/Dialect/VM/Conversion/StandardToVM/ConvertStandardToVM.cpp
+++ b/iree/compiler/Dialect/VM/Conversion/StandardToVM/ConvertStandardToVM.cpp
@@ -61,6 +61,11 @@
class FuncOpConversion : public OpConversionPattern<FuncOp> {
using OpConversionPattern::OpConversionPattern;
+ // Whitelist of function attributes to retain when converting to vm.func.
+ static constexpr std::array<const char *, 1> kRetainedAttributes = {
+ "iree.reflection",
+ };
+
PatternMatchResult matchAndRewrite(
FuncOp srcOp, ArrayRef<Value *> operands,
ConversionPatternRewriter &rewriter) const override {
@@ -92,6 +97,15 @@
auto newFuncOp = rewriter.create<IREE::VM::FuncOp>(
srcOp.getLoc(), srcOp.getName(), newFuncType);
+ // Retain function attributes in the whitelist.
+ for (auto retainAttrName : kRetainedAttributes) {
+ StringRef attrName(retainAttrName);
+ Attribute attr = srcOp.getAttr(attrName);
+ if (attr) {
+ newFuncOp.setAttr(attrName, attr);
+ }
+ }
+
// Move the body region from src -> new.
auto &srcRegion = srcOp.getOperation()->getRegion(0);
auto &newRegion = newFuncOp.getOperation()->getRegion(0);
diff --git a/iree/compiler/Dialect/VM/Conversion/StandardToVM/test/func_attrs.mlir b/iree/compiler/Dialect/VM/Conversion/StandardToVM/test/func_attrs.mlir
new file mode 100644
index 0000000..e6bc0f9
--- /dev/null
+++ b/iree/compiler/Dialect/VM/Conversion/StandardToVM/test/func_attrs.mlir
@@ -0,0 +1,16 @@
+// RUN: iree-opt -split-input-file -pass-pipeline='iree-convert-std-to-vm' %s | IreeFileCheck %s
+
+// -----
+// CHECK-LABEL: @t001_iree_reflection
+module @t001_iree_reflection {
+
+module {
+ // CHECK: func @t001_iree_reflection
+ // CHECK-SAME: iree.reflection = {f = "FOOBAR"}
+ func @t001_iree_reflection(%arg0: i32) -> (i32) attributes {iree.reflection = {f = "FOOBAR"}}
+ {
+ return %arg0 : i32
+ }
+}
+
+}