[mlir] Model StringRef in C API
authorAlex Zinenko <zinenko@google.com>
Tue, 15 Sep 2020 10:04:59 +0000 (12:04 +0200)
committerAlex Zinenko <zinenko@google.com>
Wed, 16 Sep 2020 14:04:36 +0000 (16:04 +0200)
Numerous MLIR functions return instances of `StringRef` to refer to a
non-owning fragment of a string (usually owned by the context). This is a
relatively simple class that is defined in LLVM. Provide a simple wrapper in
the MLIR C API that contains the pointer and length of the string fragment and
use it for Standard attribute functions that return StringRef instead of the
previous, callback-based mechanism.

Reviewed By: stellaraccident

Differential Revision: https://reviews.llvm.org/D87677

mlir/docs/CAPI.md
mlir/include/mlir-c/StandardAttributes.h
mlir/include/mlir-c/Support.h [new file with mode: 0644]
mlir/include/mlir/CAPI/Support.h [new file with mode: 0644]
mlir/lib/Bindings/Python/IRModules.cpp
mlir/lib/CAPI/IR/CMakeLists.txt
mlir/lib/CAPI/IR/StandardAttributes.cpp
mlir/lib/CAPI/IR/Support.cpp [new file with mode: 0644]
mlir/test/CAPI/ir.c

index 2ec25d1..e71dee0 100644 (file)
@@ -97,37 +97,32 @@ as follows.
     its first argument is `Y`, and it is the responsibility of the caller to
     ensure it is indeed the case.
 
-### Returning String References
+### Auxiliary Types
+
+#### `StringRef`
 
 Numerous MLIR functions return instances of `StringRef` to refer to a non-owning
 segment of a string. This segment may or may not be null-terminated. In C API,
-these functions take an additional callback argument of type
-`MlirStringCallback` (pointer to a function with signature `void (*)(const char
-*, intptr_t, void *)`) and a pointer to user-defined data. This callback is
-invoked with a pointer to the string segment, its size and is forwarded the
-user-defined data. The caller is in charge of managing the string segment
-according to its memory model: for strings owned by the object (e.g., string
-attributes), the caller can store the pointer and the size and use them directly
-as long as the parent object is live or copy the string to a new location with a
-null terminator if expected; for generated strings (e.g., in printing), the
-caller is expected to copy the string segment if it intends to use it later.
-
-**Note:** this interface may be revised in the near future.
-
-### Conversion To String and Printing
-
-IR objects can be converted to a string representation, for example for
-printing, using `mlirXPrint(MlirX, MlirStringCallback, void *)` functions. These
-functions accept take arguments a callback with signature `void (*)(const char
-*, intptr_t, void *)` and a pointer to user-defined data. They call the callback
-and supply it with chunks of the string representation, provided as a pointer to
-the first character and a length, and forward the user-defined data unmodified.
-It is up to the caller to allocate memory if the string representation must be
-stored and perform the copy. There is no guarantee that the pointer supplied to
-the callback points to a null-terminated string, the size argument should be
-used to find the end of the string. The callback may be called multiple times
-with consecutive chunks of the string representation (the printing itself is
-buffered).
+these are represented as instances of `MlirStringRef` structure that contains a
+pointer to the first character of the string fragment (`str`) and the fragment
+length (`length`). Note that the fragment is _not necessarily_ null-terminated,
+the `length` field must be used to identify the last character. `MlirStringRef`
+is a non-owning pointer, the caller is in charge of perfoming the copy or
+ensuring that the pointee outlives all uses of `MlirStringRef`.
+
+### Printing
+
+IR objects can be printed using `mlirXPrint(MlirX, MlirStringCallback, void *)`
+functions. These functions accept take arguments a callback with signature `void
+(*)(const char *, intptr_t, void *)` and a pointer to user-defined data. They
+call the callback and supply it with chunks of the string representation,
+provided as a pointer to the first character and a length, and forward the
+user-defined data unmodified. It is up to the caller to allocate memory if the
+string representation must be stored and perform the copy. There is no guarantee
+that the pointer supplied to the callback points to a null-terminated string,
+the size argument should be used to find the end of the string. The callback may
+be called multiple times with consecutive chunks of the string representation
+(the printing itself is buffered).
 
 *Rationale*: this approach allows the caller to have full control of the
 allocation and avoid unnecessary allocation and copying inside the printer.
index ab8d837..2ea2ba7 100644 (file)
@@ -16,6 +16,7 @@
 
 #include "mlir-c/AffineMap.h"
 #include "mlir-c/IR.h"
+#include "mlir-c/Support.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -152,13 +153,9 @@ MlirAttribute mlirOpaqueAttrGet(MlirContext ctx, const char *dialectNamespace,
  * is associated. The namespace string is owned by the context. */
 const char *mlirOpaqueAttrGetDialectNamespace(MlirAttribute attr);
 
-/** Calls the provided callback with the opaque byte data stored in the given
- * opaque attribute. The callback is invoked once, and the data it receives is
- * not necessarily null terminated. The data remains live as long as the context
- * in which the attribute lives. */
-/* TODO: consider exposing StringRef and using it instead of the callback. */
-void mlirOpaqueAttrGetData(MlirAttribute attr, MlirStringCallback callback,
-                           void *userData);
+/** Returns the raw data as a string reference. The data remains live as long as
+ * the context in which the attribute lives. */
+MlirStringRef mlirOpaqueAttrGetData(MlirAttribute attr);
 
 /*============================================================================*/
 /* String attribute.                                                          */
@@ -178,13 +175,9 @@ MlirAttribute mlirStringAttrGet(MlirContext ctx, intptr_t length,
 MlirAttribute mlirStringAttrTypedGet(MlirType type, intptr_t length,
                                      const char *data);
 
-/** Calls the provided callback with the string stored in the given string
- * attribute. The callback is invoked once, and the data it receives is not
- * necessarily null terminated. The data remains live as long as the context in
- * which the attribute lives. */
-/* TODO: consider exposing StringRef and using it instead of the callback. */
-void mlirStringAttrGetValue(MlirAttribute attr, MlirStringCallback callback,
-                            void *userData);
+/** Returns the attribute values as a string reference. The data remains live as
+ * long as the context in which the attribute lives. */
+MlirStringRef mlirStringAttrGetValue(MlirAttribute attr);
 
 /*============================================================================*/
 /* SymbolRef attribute.                                                       */
@@ -201,23 +194,13 @@ MlirAttribute mlirSymbolRefAttrGet(MlirContext ctx, intptr_t length,
                                    const char *symbol, intptr_t numReferences,
                                    MlirAttribute *references);
 
-/** Calls the provided callback with the string containing the root referenced
- * symbol. The callback is invoked once, and the data it receives is not
- * necessarily null terminated. The data remains live as long as the context in
- * which the attribute lives. */
-/* TODO: consider exposing StringRef and using it instead of the callback. */
-void mlirSymbolRefAttrGetRootReference(MlirAttribute attr,
-                                       MlirStringCallback callback,
-                                       void *userData);
-
-/** Calls the provided callback with the string containing the leaf referenced
- * symbol. The callback is invoked once, and the data it receives is not
- * necessarily null terminated. The data remains live as long as the context in
- * which the attribute lives. */
-/* TODO: consider exposing StringRef and using it instead of the callback. */
-void mlirSymbolRefAttrGetLeafReference(MlirAttribute attr,
-                                       MlirStringCallback callback,
-                                       void *userData);
+/** Returns the string reference to the root referenced symbol. The data remains
+ * live as long as the context in which the attribute lives. */
+MlirStringRef mlirSymbolRefAttrGetRootReference(MlirAttribute attr);
+
+/** Returns the stirng reference to the leaf referenced symbol. The data remains
+ * live as long as the context in which the attribute lives. */
+MlirStringRef mlirSymbolRefAttrGetLeafReference(MlirAttribute attr);
 
 /** Returns the number of references nested in the given symbol reference
  * attribute. */
@@ -240,14 +223,9 @@ int mlirAttributeIsAFlatSymbolRef(MlirAttribute attr);
 MlirAttribute mlirFlatSymbolRefAttrGet(MlirContext ctx, intptr_t length,
                                        const char *symbol);
 
-/** Calls the provided callback with the string containing the referenced
- * symbol. The callback is invoked once, and the data it receives is not
- * necessarily null terminated. The data remains live as long as the context in
- * which the attribute lives. */
-/* TODO: consider exposing StringRef and using it instead of the callback. */
-void mlirFloatSymbolRefAttrGetValue(MlirAttribute attr,
-                                    MlirStringCallback callback,
-                                    void *userData);
+/** Returns the referenced symbol as a string reference. The data remains live
+ * as long as the context in which the attribute lives. */
+MlirStringRef mlirFlatSymbolRefAttrGetValue(MlirAttribute attr);
 
 /*============================================================================*/
 /* Type attribute.                                                            */
@@ -383,10 +361,7 @@ int64_t mlirDenseElementsAttrGetInt64SplatValue(MlirAttribute attr);
 uint64_t mlirDenseElementsAttrGetUInt64SplatValue(MlirAttribute attr);
 float mlirDenseElementsAttrGetFloatSplatValue(MlirAttribute attr);
 double mlirDenseElementsAttrGetDoubleSplatValue(MlirAttribute attr);
-/* TODO: consider exposing StringRef and using it instead of the callback. */
-void mlirDenseElementsAttrGetStringSplatValue(MlirAttribute attr,
-                                              MlirStringCallback callback,
-                                              void *userData);
+MlirStringRef mlirDenseElementsAttrGetStringSplatValue(MlirAttribute attr);
 
 /** Returns the pos-th value (flat contiguous indexing) of a specific type
  * contained by the given dense elements attribute. */
@@ -397,10 +372,8 @@ int64_t mlirDenseElementsAttrGetInt64Value(MlirAttribute attr, intptr_t pos);
 uint64_t mlirDenseElementsAttrGetUInt64Value(MlirAttribute attr, intptr_t pos);
 float mlirDenseElementsAttrGetFloatValue(MlirAttribute attr, intptr_t pos);
 double mlirDenseElementsAttrGetDoubleValue(MlirAttribute attr, intptr_t pos);
-/* TODO: consider exposing StringRef and using it instead of the callback. */
-void mlirDenseElementsAttrGetStringValue(MlirAttribute attr, intptr_t pos,
-                                         MlirStringCallback callback,
-                                         void *userData);
+MlirStringRef mlirDenseElementsAttrGetStringValue(MlirAttribute attr,
+                                                  intptr_t pos);
 
 /*============================================================================*/
 /* Opaque elements attribute.                                                 */
diff --git a/mlir/include/mlir-c/Support.h b/mlir/include/mlir-c/Support.h
new file mode 100644 (file)
index 0000000..1039c68
--- /dev/null
@@ -0,0 +1,57 @@
+/*===-- mlir-c/Support.h - Helpers for C API to Core MLIR ---------*- C -*-===*\
+|*                                                                            *|
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM          *|
+|* Exceptions.                                                                *|
+|* See https://llvm.org/LICENSE.txt for license information.                  *|
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception                    *|
+|*                                                                            *|
+|*===----------------------------------------------------------------------===*|
+|*                                                                            *|
+|* This header declares the auxiliary data structures used in C APIs to core  *|
+|* MLIR functionality.                                                        *|
+|*                                                                            *|
+\*===----------------------------------------------------------------------===*/
+
+#ifndef MLIR_C_SUPPORT_H
+#define MLIR_C_SUPPORT_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*============================================================================*/
+/* MlirStringRef.                                                             */
+/*============================================================================*/
+
+/** A pointer to a sized fragment of a string, not necessarily null-terminated.
+ * Does not own the underlying string. This is equivalent to llvm::StringRef.
+ */
+struct MlirStringRef {
+  const char *data; /**< Pointer to the first symbol. */
+  size_t length;    /**< Length of the fragment. */
+};
+typedef struct MlirStringRef MlirStringRef;
+
+/** Constructs a string reference from the pointer and length. The pointer need
+ * not reference to a null-terminated string.
+ */
+inline MlirStringRef mlirStringRefCreate(const char *str, size_t length) {
+  MlirStringRef result;
+  result.data = str;
+  result.length = length;
+  return result;
+}
+
+/** Constructs a string reference from a null-terminated C string. Prefer
+ * mlirStringRefCreate if the length of the string is known.
+ */
+MlirStringRef mlirStringRefCreateFromCString(const char *str);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // MLIR_C_SUPPORT_H
diff --git a/mlir/include/mlir/CAPI/Support.h b/mlir/include/mlir/CAPI/Support.h
new file mode 100644 (file)
index 0000000..0c2b069
--- /dev/null
@@ -0,0 +1,31 @@
+//===- Support.h - C API Helpers Implementation -----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains definitions for converting MLIR C++ objects into helper
+// C structures for the purpose of C API. This file should not be included from
+// C++ code other than C API implementation nor from C code.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_CAPI_SUPPORT_H
+#define MLIR_CAPI_SUPPORT_H
+
+#include "mlir-c/Support.h"
+#include "llvm/ADT/StringRef.h"
+
+/// Converts a StringRef into its MLIR C API equivalent.
+inline MlirStringRef wrap(llvm::StringRef ref) {
+  return mlirStringRefCreate(ref.data(), ref.size());
+}
+
+/// Creates a StringRef out of its MLIR C API equivalent.
+inline llvm::StringRef unwrap(MlirStringRef ref) {
+  return llvm::StringRef(ref.data, ref.length);
+}
+
+#endif // MLIR_CAPI_SUPPORT_H
index bf1235a..527c530 100644 (file)
@@ -285,10 +285,8 @@ public:
     c.def_property_readonly(
         "value",
         [](PyStringAttribute &self) {
-          PySinglePartStringAccumulator accum;
-          mlirStringAttrGetValue(self.attr, accum.getCallback(),
-                                 accum.getUserData());
-          return accum.takeValue();
+          MlirStringRef stringRef = mlirStringAttrGetValue(self.attr);
+          return py::str(stringRef.data, stringRef.length);
         },
         "Returns the value of the string attribute");
   }
index 3e2e3d6..4158a4c 100644 (file)
@@ -4,6 +4,7 @@ add_mlir_library(MLIRCAPIIR
   IR.cpp
   StandardAttributes.cpp
   StandardTypes.cpp
+  Support.cpp
 
   EXCLUDE_FROM_LIBMLIR
 
index cade603..77d5fcb 100644 (file)
@@ -9,6 +9,7 @@
 #include "mlir-c/StandardAttributes.h"
 #include "mlir/CAPI/AffineMap.h"
 #include "mlir/CAPI/IR.h"
+#include "mlir/CAPI/Support.h"
 #include "mlir/IR/Attributes.h"
 #include "mlir/IR/StandardTypes.h"
 
@@ -165,10 +166,8 @@ const char *mlirOpaqueAttrGetDialectNamespace(MlirAttribute attr) {
   return unwrap(attr).cast<OpaqueAttr>().getDialectNamespace().c_str();
 }
 
-void mlirOpaqueAttrGetData(MlirAttribute attr, MlirStringCallback callback,
-                           void *userData) {
-  StringRef data = unwrap(attr).cast<OpaqueAttr>().getAttrData();
-  callback(data.data(), static_cast<intptr_t>(data.size()), userData);
+MlirStringRef mlirOpaqueAttrGetData(MlirAttribute attr) {
+  return wrap(unwrap(attr).cast<OpaqueAttr>().getAttrData());
 }
 
 /*============================================================================*/
@@ -189,10 +188,8 @@ MlirAttribute mlirStringAttrTypedGet(MlirType type, intptr_t length,
   return wrap(StringAttr::get(StringRef(data, length), unwrap(type)));
 }
 
-void mlirStringAttrGetValue(MlirAttribute attr, MlirStringCallback callback,
-                            void *userData) {
-  StringRef data = unwrap(attr).cast<StringAttr>().getValue();
-  callback(data.data(), static_cast<intptr_t>(data.size()), userData);
+MlirStringRef mlirStringAttrGetValue(MlirAttribute attr) {
+  return wrap(unwrap(attr).cast<StringAttr>().getValue());
 }
 
 /*============================================================================*/
@@ -213,18 +210,12 @@ MlirAttribute mlirSymbolRefAttrGet(MlirContext ctx, intptr_t length,
   return wrap(SymbolRefAttr::get(StringRef(symbol, length), refs, unwrap(ctx)));
 }
 
-void mlirSymbolRefAttrGetRootReference(MlirAttribute attr,
-                                       MlirStringCallback callback,
-                                       void *userData) {
-  StringRef ref = unwrap(attr).cast<SymbolRefAttr>().getRootReference();
-  callback(ref.data(), ref.size(), userData);
+MlirStringRef mlirSymbolRefAttrGetRootReference(MlirAttribute attr) {
+  return wrap(unwrap(attr).cast<SymbolRefAttr>().getRootReference());
 }
 
-void mlirSymbolRefAttrGetLeafReference(MlirAttribute attr,
-                                       MlirStringCallback callback,
-                                       void *userData) {
-  StringRef ref = unwrap(attr).cast<SymbolRefAttr>().getLeafReference();
-  callback(ref.data(), ref.size(), userData);
+MlirStringRef mlirSymbolRefAttrGetLeafReference(MlirAttribute attr) {
+  return wrap(unwrap(attr).cast<SymbolRefAttr>().getLeafReference());
 }
 
 intptr_t mlirSymbolRefAttrGetNumNestedReferences(MlirAttribute attr) {
@@ -250,11 +241,8 @@ MlirAttribute mlirFlatSymbolRefAttrGet(MlirContext ctx, intptr_t length,
   return wrap(FlatSymbolRefAttr::get(StringRef(symbol, length), unwrap(ctx)));
 }
 
-void mlirFloatSymbolRefAttrGetValue(MlirAttribute attr,
-                                    MlirStringCallback callback,
-                                    void *userData) {
-  StringRef symbol = unwrap(attr).cast<FlatSymbolRefAttr>().getValue();
-  callback(symbol.data(), symbol.size(), userData);
+MlirStringRef mlirFlatSymbolRefAttrGetValue(MlirAttribute attr) {
+  return wrap(unwrap(attr).cast<FlatSymbolRefAttr>().getValue());
 }
 
 /*============================================================================*/
@@ -477,12 +465,9 @@ float mlirDenseElementsAttrGetFloatSplatValue(MlirAttribute attr) {
 double mlirDenseElementsAttrGetDoubleSplatValue(MlirAttribute attr) {
   return unwrap(attr).cast<DenseElementsAttr>().getSplatValue<double>();
 }
-void mlirDenseElementsAttrGetStringSplatValue(MlirAttribute attr,
-                                              MlirStringCallback callback,
-                                              void *userData) {
-  StringRef str =
-      unwrap(attr).cast<DenseElementsAttr>().getSplatValue<StringRef>();
-  callback(str.data(), str.size(), userData);
+MlirStringRef mlirDenseElementsAttrGetStringSplatValue(MlirAttribute attr) {
+  return wrap(
+      unwrap(attr).cast<DenseElementsAttr>().getSplatValue<StringRef>());
 }
 
 //===----------------------------------------------------------------------===//
@@ -518,13 +503,11 @@ double mlirDenseElementsAttrGetDoubleValue(MlirAttribute attr, intptr_t pos) {
   return *(unwrap(attr).cast<DenseElementsAttr>().getValues<double>().begin() +
            pos);
 }
-void mlirDenseElementsAttrGetStringValue(MlirAttribute attr, intptr_t pos,
-                                         MlirStringCallback callback,
-                                         void *userData) {
-  StringRef str =
+MlirStringRef mlirDenseElementsAttrGetStringValue(MlirAttribute attr,
+                                                  intptr_t pos) {
+  return wrap(
       *(unwrap(attr).cast<DenseElementsAttr>().getValues<StringRef>().begin() +
-        pos);
-  callback(str.data(), str.size(), userData);
+        pos));
 }
 
 /*============================================================================*/
diff --git a/mlir/lib/CAPI/IR/Support.cpp b/mlir/lib/CAPI/IR/Support.cpp
new file mode 100644 (file)
index 0000000..e4b4099
--- /dev/null
@@ -0,0 +1,15 @@
+//===- Support.cpp - Helpers for C interface to MLIR API ------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir-c/Support.h"
+
+#include <cstring>
+
+MlirStringRef mlirStringRefCreateFromCString(const char *str) {
+  return mlirStringRefCreate(str, strlen(str));
+}
index 0a8ebae..ceb19ef 100644 (file)
@@ -408,31 +408,36 @@ int printStandardAttributes(MlirContext ctx) {
   mlirAttributeDump(boolean);
 
   const char data[] = "abcdefghijklmnopqestuvwxyz";
-  char buffer[10];
   MlirAttribute opaque =
       mlirOpaqueAttrGet(ctx, "std", 3, data, mlirNoneTypeGet(ctx));
   if (!mlirAttributeIsAOpaque(opaque) ||
       strcmp("std", mlirOpaqueAttrGetDialectNamespace(opaque)))
     return 4;
-  mlirOpaqueAttrGetData(opaque, callbackSetFixedLengthString, buffer);
-  if (buffer[0] != 'a' || buffer[1] != 'b' || buffer[2] != 'c')
+
+  MlirStringRef opaqueData = mlirOpaqueAttrGetData(opaque);
+  if (opaqueData.length != 3 ||
+      strncmp(data, opaqueData.data, opaqueData.length))
     return 5;
   mlirAttributeDump(opaque);
 
   MlirAttribute string = mlirStringAttrGet(ctx, 2, data + 3);
   if (!mlirAttributeIsAString(string))
     return 6;
-  mlirStringAttrGetValue(string, callbackSetFixedLengthString, buffer);
-  if (buffer[0] != 'd' || buffer[1] != 'e')
+
+  MlirStringRef stringValue = mlirStringAttrGetValue(string);
+  if (stringValue.length != 2 ||
+      strncmp(data + 3, stringValue.data, stringValue.length))
     return 7;
   mlirAttributeDump(string);
 
   MlirAttribute flatSymbolRef = mlirFlatSymbolRefAttrGet(ctx, 3, data + 5);
   if (!mlirAttributeIsAFlatSymbolRef(flatSymbolRef))
     return 8;
-  mlirFloatSymbolRefAttrGetValue(flatSymbolRef, callbackSetFixedLengthString,
-                                 buffer);
-  if (buffer[0] != 'f' || buffer[1] != 'g' || buffer[2] != 'h')
+
+  MlirStringRef flatSymbolRefValue =
+      mlirFlatSymbolRefAttrGetValue(flatSymbolRef);
+  if (flatSymbolRefValue.length != 3 ||
+      strncmp(data + 5, flatSymbolRefValue.data, flatSymbolRefValue.length))
     return 9;
   mlirAttributeDump(flatSymbolRef);
 
@@ -445,12 +450,13 @@ int printStandardAttributes(MlirContext ctx) {
       !mlirAttributeEqual(mlirSymbolRefAttrGetNestedReference(symbolRef, 1),
                           flatSymbolRef))
     return 10;
-  mlirSymbolRefAttrGetLeafReference(symbolRef, callbackSetFixedLengthString,
-                                    buffer);
-  mlirSymbolRefAttrGetRootReference(symbolRef, callbackSetFixedLengthString,
-                                    buffer + 3);
-  if (buffer[0] != 'f' || buffer[1] != 'g' || buffer[2] != 'h' ||
-      buffer[3] != 'i' || buffer[4] != 'j')
+
+  MlirStringRef symbolRefLeaf = mlirSymbolRefAttrGetLeafReference(symbolRef);
+  MlirStringRef symbolRefRoot = mlirSymbolRefAttrGetRootReference(symbolRef);
+  if (symbolRefLeaf.length != 3 ||
+      strncmp(data + 5, symbolRefLeaf.data, symbolRefLeaf.length) ||
+      symbolRefRoot.length != 2 ||
+      strncmp(data + 8, symbolRefRoot.data, symbolRefRoot.length))
     return 11;
   mlirAttributeDump(symbolRef);