MLIR 24.0.0git
Interfaces.cpp
Go to the documentation of this file.
1
2
3//===- Interfaces.cpp - C Interface for MLIR Interfaces -------------------===//
4//
5// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
6// See https://llvm.org/LICENSE.txt for license information.
7// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8//
9//===----------------------------------------------------------------------===//
10
11#include "mlir-c/Interfaces.h"
12
13#include "mlir/CAPI/IR.h"
15#include "mlir/CAPI/Support.h"
16#include "mlir/CAPI/Wrap.h"
17#include "mlir/IR/ValueRange.h"
19#include "llvm/ADT/ScopeExit.h"
20#include <optional>
21
22using namespace mlir;
23
24namespace {
25
26std::optional<RegisteredOperationName>
27getRegisteredOperationName(MlirContext context, MlirStringRef opName) {
28 StringRef name(opName.data, opName.length);
29 std::optional<RegisteredOperationName> info =
31 return info;
32}
33
34std::optional<Location> maybeGetLocation(MlirLocation location) {
35 std::optional<Location> maybeLocation;
36 if (!mlirLocationIsNull(location))
37 maybeLocation = unwrap(location);
38 return maybeLocation;
39}
40
41SmallVector<Value> unwrapOperands(intptr_t nOperands, MlirValue *operands) {
42 SmallVector<Value> unwrappedOperands;
43 (void)unwrapList(nOperands, operands, unwrappedOperands);
44 return unwrappedOperands;
45}
46
47DictionaryAttr unwrapAttributes(MlirAttribute attributes) {
48 DictionaryAttr attributeDict;
49 if (!mlirAttributeIsNull(attributes))
50 attributeDict = llvm::cast<DictionaryAttr>(unwrap(attributes));
51 return attributeDict;
52}
53
54SmallVector<std::unique_ptr<Region>> unwrapRegions(intptr_t nRegions,
55 MlirRegion *regions) {
56 // Create a vector of unique pointers to regions and make sure they are not
57 // deleted when exiting the scope. This is a hack caused by C++ API expecting
58 // an list of unique pointers to regions (without ownership transfer
59 // semantics) and C API making ownership transfer explicit.
61 unwrappedRegions.reserve(nRegions);
62 for (intptr_t i = 0; i < nRegions; ++i)
63 unwrappedRegions.emplace_back(unwrap(*(regions + i)));
64 llvm::scope_exit cleaner([&]() {
65 for (auto &region : unwrappedRegions)
66 region.release();
67 });
68 return unwrappedRegions;
69}
70
71} // namespace
72
73bool mlirOperationImplementsInterface(MlirOperation operation,
74 MlirTypeID interfaceTypeID) {
75 std::optional<RegisteredOperationName> info =
76 unwrap(operation)->getRegisteredInfo();
77 return info && info->hasInterface(unwrap(interfaceTypeID));
78}
79
81 MlirContext context,
82 MlirTypeID interfaceTypeID) {
83 std::optional<RegisteredOperationName> info = RegisteredOperationName::lookup(
84 StringRef(operationName.data, operationName.length), unwrap(context));
85 return info && info->hasInterface(unwrap(interfaceTypeID));
86}
87
89 return wrap(InferTypeOpInterface::getInterfaceID());
90}
91
93 MlirStringRef opName, MlirContext context, MlirLocation location,
94 intptr_t nOperands, MlirValue *operands, MlirAttribute attributes,
95 void *properties, intptr_t nRegions, MlirRegion *regions,
96 MlirTypesCallback callback, void *userData) {
97 StringRef name(opName.data, opName.length);
98 std::optional<RegisteredOperationName> info =
99 getRegisteredOperationName(context, opName);
100 if (!info)
102
103 std::optional<Location> maybeLocation = maybeGetLocation(location);
104 SmallVector<Value> unwrappedOperands = unwrapOperands(nOperands, operands);
105 DictionaryAttr attributeDict = unwrapAttributes(attributes);
106 SmallVector<std::unique_ptr<Region>> unwrappedRegions =
107 unwrapRegions(nRegions, regions);
108
109 SmallVector<Type> inferredTypes;
110 // The C API passes an opaque void*; we trust the caller to pass the correct
111 // properties type for this operation.
112 // TODO: Create a C API that's more type-safe.
113 PropertyRef propertyRef =
114 properties ? PropertyRef(info->getOpPropertiesTypeID(), properties)
115 : PropertyRef();
116 if (failed(info->getInterface<InferTypeOpInterface>()->inferReturnTypes(
117 unwrap(context), maybeLocation, unwrappedOperands, attributeDict,
118 propertyRef, unwrappedRegions, inferredTypes)))
120
121 SmallVector<MlirType> wrappedInferredTypes;
122 wrappedInferredTypes.reserve(inferredTypes.size());
123 for (Type t : inferredTypes)
124 wrappedInferredTypes.push_back(wrap(t));
125 callback(wrappedInferredTypes.size(), wrappedInferredTypes.data(), userData);
127}
128
130 return wrap(InferShapedTypeOpInterface::getInterfaceID());
131}
132
134 MlirStringRef opName, MlirContext context, MlirLocation location,
135 intptr_t nOperands, MlirValue *operands, MlirAttribute attributes,
136 void *properties, intptr_t nRegions, MlirRegion *regions,
137 MlirShapedTypeComponentsCallback callback, void *userData) {
138 std::optional<RegisteredOperationName> info =
139 getRegisteredOperationName(context, opName);
140 if (!info)
142
143 std::optional<Location> maybeLocation = maybeGetLocation(location);
144 SmallVector<Value> unwrappedOperands = unwrapOperands(nOperands, operands);
145 DictionaryAttr attributeDict = unwrapAttributes(attributes);
146 SmallVector<std::unique_ptr<Region>> unwrappedRegions =
147 unwrapRegions(nRegions, regions);
148
149 SmallVector<ShapedTypeComponents> inferredTypeComponents;
150 // The C API passes an opaque void*; we trust the caller to pass the correct
151 // properties type for this operation.
152 PropertyRef propertyRef =
153 properties ? PropertyRef(info->getOpPropertiesTypeID(), properties)
154 : PropertyRef();
155 if (failed(info->getInterface<InferShapedTypeOpInterface>()
156 ->inferReturnTypeComponents(
157 unwrap(context), maybeLocation,
158 mlir::ValueRange(llvm::ArrayRef(unwrappedOperands)),
159 attributeDict, propertyRef, unwrappedRegions,
160 inferredTypeComponents)))
162
163 bool hasRank;
164 intptr_t rank;
165 const int64_t *shapeData;
166 for (const ShapedTypeComponents &t : inferredTypeComponents) {
167 if (t.hasRank()) {
168 hasRank = true;
169 rank = t.getDims().size();
170 shapeData = t.getDims().data();
171 } else {
172 hasRank = false;
173 rank = 0;
174 shapeData = nullptr;
175 }
176 callback(hasRank, rank, shapeData, wrap(t.getElementType()),
177 wrap(t.getAttribute()), userData);
178 }
180}
181
182//===---------------------------------------------------------------------===//
183// ConditionallySpeculatable
184//===---------------------------------------------------------------------===//
185
187 return wrap(ConditionallySpeculatable::getInterfaceID());
188}
189
190/// Fallback model for the ConditionallySpeculatable interface that uses C API
191/// callbacks.
194 ConditionallySpeculatableOpInterfaceFallbackModel> {
195public:
196 /// Sets the callbacks that this FallbackModel will use.
197 /// NB: the callbacks can only be set through this method as the
198 /// RegisteredOperationName::attachInterface mechanism default-constructs
199 /// the FallbackModel without being able to provide arguments.
200 void
202 this->callbacks = callbacks;
203 }
204
206 if (callbacks.destruct)
207 callbacks.destruct(callbacks.userData);
208 }
209
211 return ConditionallySpeculatable::getInterfaceID();
212 }
213
214 static bool classof(const mlir::ConditionallySpeculatable::Concept *op) {
215 // Enable casting back to the FallbackModel from the Interface. This is
216 // necessary as attachInterface(...) default-constructs the FallbackModel
217 // without being able to pass in the callbacks and returns just the Concept.
218 return true;
219 }
220
222 assert(callbacks.getSpeculatability &&
223 "getSpeculatability callback not set");
224
225 switch (callbacks.getSpeculatability(wrap(op), callbacks.userData)) {
232 }
233 llvm_unreachable("unknown speculatability");
234 }
235
236private:
238};
239
240/// Attach a ConditionallySpeculatable FallbackModel to the given named op.
241/// The FallbackModel uses the provided callbacks to implement the interface.
243 MlirContext ctx, MlirStringRef opName,
245 // Look up the operation definition in the context.
246 std::optional<RegisteredOperationName> opInfo =
248
249 assert(opInfo.has_value() && "operation not found in context");
250
251 // NB: the following default-constructs the FallbackModel _without_ being able
252 // to provide arguments.
253 opInfo->attachInterface<ConditionallySpeculatableOpInterfaceFallbackModel>();
254 // Cast to get the underlying FallbackModel and set the callbacks.
255 auto *model = cast<ConditionallySpeculatableOpInterfaceFallbackModel>(
256 opInfo
257 ->getInterface<ConditionallySpeculatableOpInterfaceFallbackModel>());
258 assert(model &&
259 "Failed to get ConditionallySpeculatableOpInterfaceFallbackModel");
260 model->setCallbacks(callbacks);
261}
262
264 MlirOperation operation) {
265 auto iface = dyn_cast<ConditionallySpeculatable>(unwrap(operation));
266 assert(iface && "operation does not implement ConditionallySpeculatable");
267
268 switch (iface.getSpeculatability()) {
275 }
276 llvm_unreachable("unknown speculatability");
277}
278
279//===---------------------------------------------------------------------===//
280// MemoryEffectOpInterface
281//===---------------------------------------------------------------------===//
282
284 return wrap(
286}
287
288MlirMemoryEffect mlirMemoryEffectsFreeGet() {
289 return wrap(static_cast<MemoryEffects::Effect *>(MemoryEffects::Free::get()));
290}
291
292MlirMemoryEffect mlirMemoryEffectsReadGet() {
293 return wrap(static_cast<MemoryEffects::Effect *>(MemoryEffects::Read::get()));
294}
295
296MlirMemoryEffect mlirMemoryEffectsWriteGet() {
297 return wrap(
299}
300
301MlirSideEffectResource mlirSideEffectsDefaultResourceGet() {
302 return wrap(static_cast<SideEffects::Resource *>(
304}
305
306MlirMemoryEffectInstance mlirMemoryEffectInstanceCreate(
307 MlirMemoryEffect effect, MlirAttribute parameters, int stage,
308 bool effectOnFullRegion, MlirSideEffectResource resource) {
310 unwrap(effect), unwrap(parameters), stage, effectOnFullRegion,
311 unwrap(resource)));
312}
313
315 MlirMemoryEffect effect, MlirOpOperand opOperand, MlirAttribute parameters,
316 int stage, bool effectOnFullRegion, MlirSideEffectResource resource) {
318 unwrap(effect), unwrap(opOperand), unwrap(parameters), stage,
319 effectOnFullRegion, unwrap(resource)));
320}
321
323 MlirMemoryEffect effect, MlirValue result, MlirAttribute parameters,
324 int stage, bool effectOnFullRegion, MlirSideEffectResource resource) {
326 unwrap(effect), cast<OpResult>(unwrap(result)), unwrap(parameters), stage,
327 effectOnFullRegion, unwrap(resource)));
328}
329
331 MlirMemoryEffect effect, MlirValue blockArgument, MlirAttribute parameters,
332 int stage, bool effectOnFullRegion, MlirSideEffectResource resource) {
334 unwrap(effect), cast<BlockArgument>(unwrap(blockArgument)),
335 unwrap(parameters), stage, effectOnFullRegion, unwrap(resource)));
336}
337
339 MlirMemoryEffect effect, MlirAttribute symbol, MlirAttribute parameters,
340 int stage, bool effectOnFullRegion, MlirSideEffectResource resource) {
342 unwrap(effect), cast<SymbolRefAttr>(unwrap(symbol)), unwrap(parameters),
343 stage, effectOnFullRegion, unwrap(resource)));
344}
345
346void mlirMemoryEffectInstanceDestroy(MlirMemoryEffectInstance instance) {
347 delete unwrap(instance);
348}
349
350void mlirMemoryEffectInstancesListAppend(MlirMemoryEffectInstancesList list,
351 MlirMemoryEffectInstance instance) {
352 unwrap(list)->push_back(*unwrap(instance));
353}
354
356 return wrap(MemoryEffectOpInterface::getInterfaceID());
357}
358
359/// Fallback model for the MemoryEffectsOpInterface that uses C API callbacks.
362 MemoryEffectOpInterfaceFallbackModel> {
363public:
364 /// Sets the callbacks that this FallbackModel will use.
365 /// NB: the callbacks can only be set through this method as the
366 /// RegisteredOperationName::attachInterface mechanism default-constructs
367 /// the FallbackModel without being able to provide arguments.
369 this->callbacks = callbacks;
370 }
371
373 if (callbacks.destruct)
374 callbacks.destruct(callbacks.userData);
375 }
376
378 return MemoryEffectOpInterface::getInterfaceID();
379 }
380
381 static bool classof(const mlir::MemoryEffectOpInterface::Concept *op) {
382 // Enable casting back to the FallbackModel from the Interface. This is
383 // necessary as attachInterface(...) default-constructs the FallbackModel
384 // without being able to pass in the callbacks and returns just the Concept.
385 return true;
386 }
387
388 void
391 assert(callbacks.getEffects && "getEffects callback not set");
392 MlirMemoryEffectInstancesList cEffects = wrap(&effects);
393 callbacks.getEffects(wrap(op), cEffects, callbacks.userData);
394 }
395
396private:
398};
399
400/// Attach a MemoryEffectsOpInterface FallbackModel to the given named op.
401/// The FallbackModel uses the provided callbacks to implement the interface.
403 MlirContext ctx, MlirStringRef opName,
405 // Look up the operation definition in the context
406 std::optional<RegisteredOperationName> opInfo =
408
409 assert(opInfo.has_value() && "operation not found in context");
410
411 // NB: the following default-constructs the FallbackModel _without_ being able
412 // to provide arguments.
413 opInfo->attachInterface<MemoryEffectOpInterfaceFallbackModel>();
414 // Cast to get the underlying FallbackModel and set the callbacks.
415 auto *model = cast<MemoryEffectOpInterfaceFallbackModel>(
416 opInfo->getInterface<MemoryEffectOpInterfaceFallbackModel>());
417 assert(model && "Failed to get MemoryEffectOpInterfaceFallbackModel");
418 model->setCallbacks(callbacks);
419}
MlirMemoryEffectInstance mlirMemoryEffectInstanceCreateForOpOperand(MlirMemoryEffect effect, MlirOpOperand opOperand, MlirAttribute parameters, int stage, bool effectOnFullRegion, MlirSideEffectResource resource)
Creates a memory effect instance associated with an operation operand.
MlirLogicalResult mlirInferShapedTypeOpInterfaceInferReturnTypes(MlirStringRef opName, MlirContext context, MlirLocation location, intptr_t nOperands, MlirValue *operands, MlirAttribute attributes, void *properties, intptr_t nRegions, MlirRegion *regions, MlirShapedTypeComponentsCallback callback, void *userData)
Infers the return shaped type components of the operation.
MlirMemoryEffectInstance mlirMemoryEffectInstanceCreateForBlockArgument(MlirMemoryEffect effect, MlirValue blockArgument, MlirAttribute parameters, int stage, bool effectOnFullRegion, MlirSideEffectResource resource)
Creates a memory effect instance associated with a block argument.
MlirMemoryEffectInstance mlirMemoryEffectInstanceCreateForSymbol(MlirMemoryEffect effect, MlirAttribute symbol, MlirAttribute parameters, int stage, bool effectOnFullRegion, MlirSideEffectResource resource)
Creates a memory effect instance associated with a symbol.
MlirSideEffectResource mlirSideEffectsDefaultResourceGet()
Returns the borrowed singleton instance of the default side effect resource.
MlirTypeID mlirConditionallySpeculatableOpInterfaceTypeID()
Returns the interface TypeID of the ConditionallySpeculatable interface.
void mlirMemoryEffectInstanceDestroy(MlirMemoryEffectInstance instance)
Destroys a memory effect instance created by one of the functions above.
MlirMemoryEffect mlirMemoryEffectsFreeGet()
Returns the borrowed singleton instance of the free memory effect.
void mlirMemoryEffectInstancesListAppend(MlirMemoryEffectInstancesList list, MlirMemoryEffectInstance instance)
Appends a copy of instance to the given list.
MlirSpeculatability mlirConditionallySpeculatableOpInterfaceGetSpeculatability(MlirOperation operation)
Returns the speculatability of the given operation.
MlirMemoryEffect mlirMemoryEffectsReadGet()
Returns the borrowed singleton instance of the read memory effect.
bool mlirOperationImplementsInterface(MlirOperation operation, MlirTypeID interfaceTypeID)
Returns true if the given operation implements an interface identified by its TypeID.
MlirTypeID mlirMemoryEffectsOpInterfaceTypeID()
Returns the interface TypeID of the MemoryEffectsOpInterface.
MlirMemoryEffectInstance mlirMemoryEffectInstanceCreateForOpResult(MlirMemoryEffect effect, MlirValue result, MlirAttribute parameters, int stage, bool effectOnFullRegion, MlirSideEffectResource resource)
Creates a memory effect instance associated with an operation result.
bool mlirOperationImplementsInterfaceStatic(MlirStringRef operationName, MlirContext context, MlirTypeID interfaceTypeID)
Returns true if the operation identified by its canonical string name implements the interface identi...
void mlirConditionallySpeculatableOpInterfaceAttachFallbackModel(MlirContext ctx, MlirStringRef opName, MlirConditionallySpeculatableOpInterfaceCallbacks callbacks)
Attach a ConditionallySpeculatable FallbackModel to the given named op.
void mlirMemoryEffectsOpInterfaceAttachFallbackModel(MlirContext ctx, MlirStringRef opName, MlirMemoryEffectsOpInterfaceCallbacks callbacks)
Attach a MemoryEffectsOpInterface FallbackModel to the given named op.
MlirTypeID mlirInferTypeOpInterfaceTypeID()
Returns the interface TypeID of the InferTypeOpInterface.
MlirMemoryEffect mlirMemoryEffectsWriteGet()
Returns the borrowed singleton instance of the write memory effect.
MlirLogicalResult mlirInferTypeOpInterfaceInferReturnTypes(MlirStringRef opName, MlirContext context, MlirLocation location, intptr_t nOperands, MlirValue *operands, MlirAttribute attributes, void *properties, intptr_t nRegions, MlirRegion *regions, MlirTypesCallback callback, void *userData)
Infers the return types of the operation identified by its canonical given the arguments that will be...
MlirMemoryEffect mlirMemoryEffectsAllocateGet()
Returns the borrowed singleton instance of the allocate memory effect.
MlirTypeID mlirInferShapedTypeOpInterfaceTypeID()
Returns the interface TypeID of the InferShapedTypeOpInterface.
MlirMemoryEffectInstance mlirMemoryEffectInstanceCreate(MlirMemoryEffect effect, MlirAttribute parameters, int stage, bool effectOnFullRegion, MlirSideEffectResource resource)
Creates a memory effect instance without an associated IR entity.
static llvm::ArrayRef< CppTy > unwrapList(size_t size, CTy *first, llvm::SmallVectorImpl< CppTy > &storage)
Definition Wrap.h:40
Fallback model for the ConditionallySpeculatable interface that uses C API callbacks.
static bool classof(const mlir::ConditionallySpeculatable::Concept *op)
Speculation::Speculatability getSpeculatability(Operation *op) const
void setCallbacks(MlirConditionallySpeculatableOpInterfaceCallbacks callbacks)
Sets the callbacks that this FallbackModel will use.
Fallback model for the MemoryEffectsOpInterface that uses C API callbacks.
void setCallbacks(MlirMemoryEffectsOpInterfaceCallbacks callbacks)
Sets the callbacks that this FallbackModel will use.
static bool classof(const mlir::MemoryEffectOpInterface::Concept *op)
void getEffects(Operation *op, SmallVectorImpl< MemoryEffects::EffectInstance > &effects) const
Operation is the basic unit of execution within MLIR.
Definition Operation.h:87
Type-safe wrapper around a void* for passing properties, including the properties structs of operatio...
static std::optional< RegisteredOperationName > lookup(StringRef name, MLIRContext *ctx)
Lookup the registered operation information for the given operation.
ShapedTypeComponents that represents the components of a ShapedType.
This class represents a specific resource that an effect applies to.
This class provides an efficient unique identifier for a specific C++ type.
Definition TypeID.h:107
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition Types.h:74
This class provides an abstraction over the different types of ranges over Values.
Definition ValueRange.h:389
MlirDiagnostic wrap(mlir::Diagnostic &diagnostic)
Definition Diagnostics.h:24
mlir::Diagnostic & unwrap(MlirDiagnostic diagnostic)
Definition Diagnostics.h:19
static bool mlirLocationIsNull(MlirLocation location)
Checks if the location is null.
Definition IR.h:384
MlirSpeculatability
Enum representing the speculatability of an operation.
Definition Interfaces.h:108
@ MlirSpeculatabilityRecursivelySpeculatable
The operation is speculatable if all nested operations are speculatable.
Definition Interfaces.h:114
@ MlirSpeculatabilitySpeculatable
The operation is speculatable.
Definition Interfaces.h:112
@ MlirSpeculatabilityNotSpeculatable
The operation is not speculatable.
Definition Interfaces.h:110
void(* MlirShapedTypeComponentsCallback)(bool, intptr_t, const int64_t *, MlirType, MlirAttribute, void *)
These callbacks are used to return multiple shaped type components from functions while transferring ...
Definition Interfaces.h:90
void(* MlirTypesCallback)(intptr_t, MlirType *, void *)
These callbacks are used to return multiple types from functions while transferring ownership to the ...
Definition Interfaces.h:64
static MlirLogicalResult mlirLogicalResultFailure(void)
Creates a logical result representing a failure.
Definition Support.h:143
static MlirLogicalResult mlirLogicalResultSuccess(void)
Creates a logical result representing a success.
Definition Support.h:137
SideEffects::EffectInstance< Effect > EffectInstance
constexpr auto RecursivelySpeculatable
Speculatability
This enum is returned from the getSpeculatability method in the ConditionallySpeculatable op interfac...
constexpr auto Speculatable
constexpr auto NotSpeculatable
Include the generated interface declarations.
Callbacks for implementing ConditionallySpeculatable from external code.
Definition Interfaces.h:122
A logical result value, essentially a boolean with named states.
Definition Support.h:121
Callbacks for implementing MemoryEffectsOpInterface from external code.
Definition Interfaces.h:229
A pointer to a sized fragment of a string, not necessarily null-terminated.
Definition Support.h:78
const char * data
Pointer to the first symbol.
Definition Support.h:79
size_t length
Length of the fragment.
Definition Support.h:80
This class represents the base class used for memory effects.