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.
#include "mlir-c/AffineMap.h"
#include "mlir-c/IR.h"
+#include "mlir-c/Support.h"
#ifdef __cplusplus
extern "C" {
* 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. */
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. */
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. */
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. */
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. */
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. */
--- /dev/null
+/*===-- 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
--- /dev/null
+//===- 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
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");
}
IR.cpp
StandardAttributes.cpp
StandardTypes.cpp
+ Support.cpp
EXCLUDE_FROM_LIBMLIR
#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"
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());
}
/*============================================================================*/
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());
}
/*============================================================================*/
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) {
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());
}
/*============================================================================*/
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>());
}
//===----------------------------------------------------------------------===//
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));
}
/*============================================================================*/
--- /dev/null
+//===- 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));
+}
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);
!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);