Skip to content

Emitc

emitc

Dialect to generate C/C++ from MLIR.

The EmitC dialect allows to convert operations from other MLIR dialects to EmitC ops. Those can be translated to C/C++ via the Cpp emitter.

See external documentation.

EmitCIntegerType = IntegerType[Literal[1, 8, 16, 32, 64]] module-attribute

Type for integer types supported by EmitC. See external documentation.

EmitCIntegerTypeConstr = irdl_to_attr_constraint(EmitCIntegerType) module-attribute

Constraint for integer types supported by EmitC. See external documentation.

EmitCFloatType = Float16Type | BFloat16Type | Float32Type | Float64Type module-attribute

EmitCFloatTypeConstr = irdl_to_attr_constraint(EmitCFloatType) module-attribute

Supported floating-point type in EmitC. See external documentation

EmitCPointerWideType = EmitC_PtrDiffT | EmitC_SignedSizeT | EmitC_SizeT module-attribute

EmitCPointerWideTypeConstr = irdl_to_attr_constraint(EmitCPointerWideType) module-attribute

Constraint for pointer-wide types supported by EmitC. These types have the same width as platform-specific pointer types.

EmitCIntegerIndexOpaqueType = EmitCIntegerType | IndexType | EmitC_OpaqueType module-attribute

EmitCIntegerIndexOpaqueTypeConstr = irdl_to_attr_constraint(EmitCIntegerIndexOpaqueType) module-attribute

Constraint for integer, index, or opaque types supported by EmitC.

EmitCArrayElementType = EmitCIntegerIndexOpaqueType | EmitCFloatType | EmitCPointerWideType module-attribute

EmitCArrayElementTypeConstr = irdl_to_attr_constraint(EmitCArrayElementType) module-attribute

Constraint for valid element types in EmitC arrays.

EmitCArrayElementTypeCovT = TypeVar('EmitCArrayElementTypeCovT', bound=EmitCArrayElementType, covariant=True, default=EmitCArrayElementType) module-attribute

EmitCTypeConstr = EmitCTypeConstraint() module-attribute

EmitC = Dialect('emitc', [EmitC_AddOp, EmitC_ApplyOp, EmitC_CallOpaqueOp], [EmitC_ArrayType, EmitC_LValueType, EmitC_OpaqueAttr, EmitC_OpaqueType, EmitC_PointerType, EmitC_PtrDiffT, EmitC_SignedSizeT, EmitC_SizeT]) module-attribute

EmitC_OpaqueType dataclass

Bases: ParametrizedAttribute, TypeAttribute

EmitC opaque type

Source code in xdsl/dialects/emitc.py
65
66
67
68
69
70
71
72
73
74
75
76
77
78
@irdl_attr_definition
class EmitC_OpaqueType(ParametrizedAttribute, TypeAttribute):
    """EmitC opaque type"""

    name = "emitc.opaque"
    value: StringAttr

    def verify(self) -> None:
        if not self.value.data:
            raise VerifyException("expected non empty string in !emitc.opaque type")
        if self.value.data[-1] == "*":
            raise VerifyException(
                "pointer not allowed as outer type with !emitc.opaque, use !emitc.ptr instead"
            )

name = 'emitc.opaque' class-attribute instance-attribute

value: StringAttr instance-attribute

verify() -> None

Source code in xdsl/dialects/emitc.py
72
73
74
75
76
77
78
def verify(self) -> None:
    if not self.value.data:
        raise VerifyException("expected non empty string in !emitc.opaque type")
    if self.value.data[-1] == "*":
        raise VerifyException(
            "pointer not allowed as outer type with !emitc.opaque, use !emitc.ptr instead"
        )

EmitC_PtrDiffT dataclass

Bases: ParametrizedAttribute, TypeAttribute

EmitC signed pointer diff type. Signed data type as wide as platform-specific pointer types. In particular, it is as wide as emitc.size_t. It corresponds to ptrdiff_t found in .

Source code in xdsl/dialects/emitc.py
81
82
83
84
85
86
87
88
89
@irdl_attr_definition
class EmitC_PtrDiffT(ParametrizedAttribute, TypeAttribute):
    """
    EmitC signed pointer diff type.
    Signed data type as wide as platform-specific pointer types. In particular, it is as wide as emitc.size_t.
    It corresponds to ptrdiff_t found in <stddef.h>.
    """

    name = "emitc.ptrdiff_t"

name = 'emitc.ptrdiff_t' class-attribute instance-attribute

EmitC_SignedSizeT dataclass

Bases: ParametrizedAttribute, TypeAttribute

EmitC signed size type. Data type representing all values of emitc.size_t, plus -1. It corresponds to ssize_t found in . Use of this type causes the code to be non-C99 compliant.

Source code in xdsl/dialects/emitc.py
 92
 93
 94
 95
 96
 97
 98
 99
100
@irdl_attr_definition
class EmitC_SignedSizeT(ParametrizedAttribute, TypeAttribute):
    """
    EmitC signed size type.
    Data type representing all values of emitc.size_t, plus -1. It corresponds to ssize_t found in <sys/types.h>.
    Use of this type causes the code to be non-C99 compliant.
    """

    name = "emitc.ssize_t"

name = 'emitc.ssize_t' class-attribute instance-attribute

EmitC_SizeT dataclass

Bases: ParametrizedAttribute, TypeAttribute

EmitC unsigned size type. Unsigned data type as wide as platform-specific pointer types. It corresponds to size_t found in .

Source code in xdsl/dialects/emitc.py
103
104
105
106
107
108
109
110
@irdl_attr_definition
class EmitC_SizeT(ParametrizedAttribute, TypeAttribute):
    """
    EmitC unsigned size type.
    Unsigned data type as wide as platform-specific pointer types. It corresponds to size_t found in <stddef.h>.
    """

    name = "emitc.size_t"

name = 'emitc.size_t' class-attribute instance-attribute

EmitC_OpaqueAttr dataclass

Bases: ParametrizedAttribute

An opaque attribute of which the value gets emitted as is.

Source code in xdsl/dialects/emitc.py
154
155
156
157
158
159
160
161
@irdl_attr_definition
class EmitC_OpaqueAttr(ParametrizedAttribute):
    """
    An opaque attribute of which the value gets emitted as is.
    """

    name = "emitc.opaque"
    value: StringAttr

name = 'emitc.opaque' class-attribute instance-attribute

value: StringAttr instance-attribute

EmitC_ArrayType

Bases: ParametrizedAttribute, TypeAttribute, ShapedType, ContainerType[EmitCArrayElementTypeCovT], Generic[EmitCArrayElementTypeCovT]

EmitC array type

Source code in xdsl/dialects/emitc.py
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
@irdl_attr_definition
class EmitC_ArrayType(
    ParametrizedAttribute,
    TypeAttribute,
    ShapedType,
    ContainerType[EmitCArrayElementTypeCovT],
    Generic[EmitCArrayElementTypeCovT],
):
    """EmitC array type"""

    name = "emitc.array"

    shape: ArrayAttr[IntAttr] = param_def(StaticShapeArrayConstr)
    element_type: EmitCArrayElementTypeCovT

    def __init__(
        self,
        shape: Iterable[int | IntAttr],
        element_type: EmitCArrayElementType,
    ):
        shape = ArrayAttr(
            [IntAttr(dim) if isinstance(dim, int) else dim for dim in shape]
        )
        super().__init__(shape, element_type)

    def verify(self) -> None:
        if not self.shape.data:
            raise VerifyException("EmitC array shape must not be empty")

        if isinstance(self.element_type, EmitC_ArrayType):
            raise VerifyException("nested EmitC arrays are not allowed")

        for dim_attr in self.shape.data:
            if dim_attr.data < 0:
                raise VerifyException(
                    "EmitC array dimensions must have non-negative size"
                )

    def get_num_dims(self) -> int:
        return len(self.shape.data)

    def get_shape(self) -> tuple[int, ...]:
        return tuple(i.data for i in self.shape.data)

    def get_element_type(self) -> EmitCArrayElementTypeCovT:
        return self.element_type

    @classmethod
    def parse_parameters(cls, parser: AttrParser):
        with parser.in_angle_brackets():
            shape, type = parser.parse_ranked_shape()
            return ArrayAttr(IntAttr(dim) for dim in shape), type

    def print_parameters(self, printer: Printer) -> None:
        with printer.in_angle_brackets():
            printer.print_list(
                self.shape, lambda dim: printer.print_string(f"{dim.data}"), "x"
            )
            printer.print_string("x")
            printer.print_attribute(self.element_type)

name = 'emitc.array' class-attribute instance-attribute

shape: ArrayAttr[IntAttr] = param_def(StaticShapeArrayConstr) class-attribute instance-attribute

element_type: EmitCArrayElementTypeCovT instance-attribute

__init__(shape: Iterable[int | IntAttr], element_type: EmitCArrayElementType)

Source code in xdsl/dialects/emitc.py
187
188
189
190
191
192
193
194
195
def __init__(
    self,
    shape: Iterable[int | IntAttr],
    element_type: EmitCArrayElementType,
):
    shape = ArrayAttr(
        [IntAttr(dim) if isinstance(dim, int) else dim for dim in shape]
    )
    super().__init__(shape, element_type)

verify() -> None

Source code in xdsl/dialects/emitc.py
197
198
199
200
201
202
203
204
205
206
207
208
def verify(self) -> None:
    if not self.shape.data:
        raise VerifyException("EmitC array shape must not be empty")

    if isinstance(self.element_type, EmitC_ArrayType):
        raise VerifyException("nested EmitC arrays are not allowed")

    for dim_attr in self.shape.data:
        if dim_attr.data < 0:
            raise VerifyException(
                "EmitC array dimensions must have non-negative size"
            )

get_num_dims() -> int

Source code in xdsl/dialects/emitc.py
210
211
def get_num_dims(self) -> int:
    return len(self.shape.data)

get_shape() -> tuple[int, ...]

Source code in xdsl/dialects/emitc.py
213
214
def get_shape(self) -> tuple[int, ...]:
    return tuple(i.data for i in self.shape.data)

get_element_type() -> EmitCArrayElementTypeCovT

Source code in xdsl/dialects/emitc.py
216
217
def get_element_type(self) -> EmitCArrayElementTypeCovT:
    return self.element_type

parse_parameters(parser: AttrParser) classmethod

Source code in xdsl/dialects/emitc.py
219
220
221
222
223
@classmethod
def parse_parameters(cls, parser: AttrParser):
    with parser.in_angle_brackets():
        shape, type = parser.parse_ranked_shape()
        return ArrayAttr(IntAttr(dim) for dim in shape), type

print_parameters(printer: Printer) -> None

Source code in xdsl/dialects/emitc.py
225
226
227
228
229
230
231
def print_parameters(self, printer: Printer) -> None:
    with printer.in_angle_brackets():
        printer.print_list(
            self.shape, lambda dim: printer.print_string(f"{dim.data}"), "x"
        )
        printer.print_string("x")
        printer.print_attribute(self.element_type)

EmitCTypeConstraint dataclass

Bases: AttrConstraint

Check if a type is supported by EmitC. See MLIR implementation.

Source code in xdsl/dialects/emitc.py
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
class EmitCTypeConstraint(AttrConstraint):
    """
    Check if a type is supported by EmitC.
    See [MLIR implementation](https://github.com/llvm/llvm-project/blob/main/mlir/lib/Dialect/EmitC/IR/EmitC.cpp#L62).
    """

    def verify(self, attr: Attribute, constraint_context: ConstraintContext) -> None:
        if isa(attr, TensorType):
            # EmitC only supports tensors with static shapes
            if not attr.has_static_shape():
                raise VerifyException(f"Type {attr} is not a supported EmitC type")
            elem_type = attr.get_element_type()
            if isinstance(elem_type, EmitC_ArrayType):
                raise VerifyException("EmitC type cannot be a tensor of EmitC arrays")
            self.verify(elem_type, constraint_context)
            return

        if isa(attr, EmitC_ArrayType):
            elem_type = attr.get_element_type()
            self.verify(elem_type, constraint_context)
            return

        if isinstance(attr, EmitC_PointerType):
            self.verify(attr.pointee_type, constraint_context)
            return

        if isinstance(attr, TupleType):
            for t in attr.types:
                if isinstance(t, EmitC_ArrayType):
                    raise VerifyException(
                        "EmitC type cannot be a tuple of EmitC arrays"
                    )
                self.verify(t, constraint_context)
            return

        EmitCArrayElementTypeConstr.verify(attr, constraint_context)

    def mapping_type_vars(
        self, type_var_mapping: Mapping[TypeVar, AttrConstraint | IntConstraint]
    ) -> AttrConstraint:
        # No type variables to map in this constraint
        return self

verify(attr: Attribute, constraint_context: ConstraintContext) -> None

Source code in xdsl/dialects/emitc.py
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
def verify(self, attr: Attribute, constraint_context: ConstraintContext) -> None:
    if isa(attr, TensorType):
        # EmitC only supports tensors with static shapes
        if not attr.has_static_shape():
            raise VerifyException(f"Type {attr} is not a supported EmitC type")
        elem_type = attr.get_element_type()
        if isinstance(elem_type, EmitC_ArrayType):
            raise VerifyException("EmitC type cannot be a tensor of EmitC arrays")
        self.verify(elem_type, constraint_context)
        return

    if isa(attr, EmitC_ArrayType):
        elem_type = attr.get_element_type()
        self.verify(elem_type, constraint_context)
        return

    if isinstance(attr, EmitC_PointerType):
        self.verify(attr.pointee_type, constraint_context)
        return

    if isinstance(attr, TupleType):
        for t in attr.types:
            if isinstance(t, EmitC_ArrayType):
                raise VerifyException(
                    "EmitC type cannot be a tuple of EmitC arrays"
                )
            self.verify(t, constraint_context)
        return

    EmitCArrayElementTypeConstr.verify(attr, constraint_context)

mapping_type_vars(type_var_mapping: Mapping[TypeVar, AttrConstraint | IntConstraint]) -> AttrConstraint

Source code in xdsl/dialects/emitc.py
271
272
273
274
275
def mapping_type_vars(
    self, type_var_mapping: Mapping[TypeVar, AttrConstraint | IntConstraint]
) -> AttrConstraint:
    # No type variables to map in this constraint
    return self

EmitC_LValueType dataclass

Bases: ParametrizedAttribute, TypeAttribute

EmitC lvalue type. Values of this type can be assigned to and their address can be taken. See tablegen definition

Source code in xdsl/dialects/emitc.py
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
@irdl_attr_definition
class EmitC_LValueType(ParametrizedAttribute, TypeAttribute):
    """
    EmitC lvalue type.
    Values of this type can be assigned to and their address can be taken.
    See [tablegen definition](https://github.com/llvm/llvm-project/blob/main/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td#L87)
    """

    name = "emitc.lvalue"
    value_type: Attribute = param_def(EmitCTypeConstr)

    def verify(self) -> None:
        """
        Verify the LValueType.
        See [MLIR implementation](https://github.com/llvm/llvm-project/blob/main/mlir/lib/Dialect/EmitC/IR/EmitC.cpp#L1095)
        """
        if isinstance(self.value_type, EmitC_ArrayType):
            raise VerifyException("!emitc.lvalue cannot wrap !emitc.array type")

name = 'emitc.lvalue' class-attribute instance-attribute

value_type: Attribute = param_def(EmitCTypeConstr) class-attribute instance-attribute

verify() -> None

Verify the LValueType. See MLIR implementation

Source code in xdsl/dialects/emitc.py
292
293
294
295
296
297
298
def verify(self) -> None:
    """
    Verify the LValueType.
    See [MLIR implementation](https://github.com/llvm/llvm-project/blob/main/mlir/lib/Dialect/EmitC/IR/EmitC.cpp#L1095)
    """
    if isinstance(self.value_type, EmitC_ArrayType):
        raise VerifyException("!emitc.lvalue cannot wrap !emitc.array type")

EmitC_PointerType dataclass

Bases: ParametrizedAttribute, TypeAttribute

EmitC pointer type

Source code in xdsl/dialects/emitc.py
301
302
303
304
305
306
307
308
309
310
@irdl_attr_definition
class EmitC_PointerType(ParametrizedAttribute, TypeAttribute):
    """EmitC pointer type"""

    name = "emitc.ptr"
    pointee_type: TypeAttribute

    def verify(self) -> None:
        if isinstance(self.pointee_type, EmitC_LValueType):
            raise VerifyException("pointers to lvalues are not allowed")

name = 'emitc.ptr' class-attribute instance-attribute

pointee_type: TypeAttribute instance-attribute

verify() -> None

Source code in xdsl/dialects/emitc.py
308
309
310
def verify(self) -> None:
    if isinstance(self.pointee_type, EmitC_LValueType):
        raise VerifyException("pointers to lvalues are not allowed")

EmitC_BinaryOperation

Bases: IRDLOperation, ABC

Base class for EmitC binary operations.

Source code in xdsl/dialects/emitc.py
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
class EmitC_BinaryOperation(IRDLOperation, abc.ABC):
    """Base class for EmitC binary operations."""

    lhs = operand_def(EmitCTypeConstr)
    rhs = operand_def(EmitCTypeConstr)
    result = result_def(EmitCTypeConstr)

    assembly_format = "operands attr-dict `:` functional-type(operands, results)"

    def __init__(
        self,
        lhs: SSAValue,
        rhs: SSAValue,
        result_type: Attribute,
    ):
        super().__init__(
            operands=[lhs, rhs],
            result_types=[result_type],
        )

lhs = operand_def(EmitCTypeConstr) class-attribute instance-attribute

rhs = operand_def(EmitCTypeConstr) class-attribute instance-attribute

result = result_def(EmitCTypeConstr) class-attribute instance-attribute

assembly_format = 'operands attr-dict `:` functional-type(operands, results)' class-attribute instance-attribute

__init__(lhs: SSAValue, rhs: SSAValue, result_type: Attribute)

Source code in xdsl/dialects/emitc.py
322
323
324
325
326
327
328
329
330
331
def __init__(
    self,
    lhs: SSAValue,
    rhs: SSAValue,
    result_type: Attribute,
):
    super().__init__(
        operands=[lhs, rhs],
        result_types=[result_type],
    )

EmitC_AddOp dataclass

Bases: EmitC_BinaryOperation

Addition operation.

With the emitc.add operation the arithmetic operator + (addition) can be applied. Supports pointer arithmetic where one operand is a pointer and the other is an integer or opaque type.

Example:

// Custom form of the addition operation.
%0 = emitc.add %arg0, %arg1 : (i32, i32) -> i32
%1 = emitc.add %arg2, %arg3 : (!emitc.ptr<f32>, i32) -> !emitc.ptr<f32>
// Code emitted for the operations above.
int32_t v5 = v1 + v2;
float* v6 = v3 + v4;
Source code in xdsl/dialects/emitc.py
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
@irdl_op_definition
class EmitC_AddOp(EmitC_BinaryOperation):
    """
    Addition operation.

    With the `emitc.add` operation the arithmetic operator + (addition) can
    be applied. Supports pointer arithmetic where one operand is a pointer
    and the other is an integer or opaque type.

    Example:

    ```mlir
    // Custom form of the addition operation.
    %0 = emitc.add %arg0, %arg1 : (i32, i32) -> i32
    %1 = emitc.add %arg2, %arg3 : (!emitc.ptr<f32>, i32) -> !emitc.ptr<f32>
    ```
    ```c++
    // Code emitted for the operations above.
    int32_t v5 = v1 + v2;
    float* v6 = v3 + v4;
    ```
    """

    name = "emitc.add"

    def verify_(self) -> None:
        lhs_type = self.lhs.type
        rhs_type = self.rhs.type

        if isa(lhs_type, EmitC_PointerType) and isa(rhs_type, EmitC_PointerType):
            raise VerifyException(
                "emitc.add requires that at most one operand is a pointer"
            )

        if (
            isa(lhs_type, EmitC_PointerType)
            and not isa(rhs_type, IntegerType | EmitC_OpaqueType)
        ) or (
            isa(rhs_type, EmitC_PointerType)
            and not isa(lhs_type, IntegerType | EmitC_OpaqueType)
        ):
            raise VerifyException(
                "emitc.add requires that one operand is an integer or of opaque "
                "type if the other is a pointer"
            )

name = 'emitc.add' class-attribute instance-attribute

verify_() -> None

Source code in xdsl/dialects/emitc.py
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
def verify_(self) -> None:
    lhs_type = self.lhs.type
    rhs_type = self.rhs.type

    if isa(lhs_type, EmitC_PointerType) and isa(rhs_type, EmitC_PointerType):
        raise VerifyException(
            "emitc.add requires that at most one operand is a pointer"
        )

    if (
        isa(lhs_type, EmitC_PointerType)
        and not isa(rhs_type, IntegerType | EmitC_OpaqueType)
    ) or (
        isa(rhs_type, EmitC_PointerType)
        and not isa(lhs_type, IntegerType | EmitC_OpaqueType)
    ):
        raise VerifyException(
            "emitc.add requires that one operand is an integer or of opaque "
            "type if the other is a pointer"
        )

EmitC_ApplyOp dataclass

Bases: IRDLOperation

Apply operation

Source code in xdsl/dialects/emitc.py
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
@irdl_op_definition
class EmitC_ApplyOp(IRDLOperation):
    """Apply operation"""

    name = "emitc.apply"

    assembly_format = """
        $applicableOperator `(` $operand `)` attr-dict `:` functional-type($operand, results)
      """

    applicableOperator = prop_def(StringAttr)

    operand = operand_def(AnyAttr())

    result = result_def(EmitCTypeConstr)

    def verify_(self) -> None:
        applicable_operator = self.applicableOperator.data

        # Applicable operator must not be empty
        if not applicable_operator:
            raise VerifyException("applicable operator must not be empty")

        if applicable_operator not in ("&", "*"):
            raise VerifyException("applicable operator is illegal")

        operand_type = self.operand.type
        result_type = self.result.type

        if applicable_operator == "&":
            if not isinstance(operand_type, EmitC_LValueType):
                raise VerifyException(
                    "operand type must be an lvalue when applying `&`"
                )
            if not isinstance(result_type, EmitC_PointerType):
                raise VerifyException("result type must be a pointer when applying `&`")
        else:  # applicable_operator == "*"
            if not isinstance(operand_type, EmitC_PointerType):
                raise VerifyException(
                    "operand type must be a pointer when applying `*`"
                )

    def has_side_effects(self) -> bool:
        """Return True if the operation has side effects."""
        return self.applicableOperator.data == "*"

name = 'emitc.apply' class-attribute instance-attribute

assembly_format = '\n $applicableOperator `(` $operand `)` attr-dict `:` functional-type($operand, results)\n ' class-attribute instance-attribute

applicableOperator = prop_def(StringAttr) class-attribute instance-attribute

operand = operand_def(AnyAttr()) class-attribute instance-attribute

result = result_def(EmitCTypeConstr) class-attribute instance-attribute

verify_() -> None

Source code in xdsl/dialects/emitc.py
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
def verify_(self) -> None:
    applicable_operator = self.applicableOperator.data

    # Applicable operator must not be empty
    if not applicable_operator:
        raise VerifyException("applicable operator must not be empty")

    if applicable_operator not in ("&", "*"):
        raise VerifyException("applicable operator is illegal")

    operand_type = self.operand.type
    result_type = self.result.type

    if applicable_operator == "&":
        if not isinstance(operand_type, EmitC_LValueType):
            raise VerifyException(
                "operand type must be an lvalue when applying `&`"
            )
        if not isinstance(result_type, EmitC_PointerType):
            raise VerifyException("result type must be a pointer when applying `&`")
    else:  # applicable_operator == "*"
        if not isinstance(operand_type, EmitC_PointerType):
            raise VerifyException(
                "operand type must be a pointer when applying `*`"
            )

has_side_effects() -> bool

Return True if the operation has side effects.

Source code in xdsl/dialects/emitc.py
423
424
425
def has_side_effects(self) -> bool:
    """Return True if the operation has side effects."""
    return self.applicableOperator.data == "*"

EmitC_CallOpaqueOp

Bases: IRDLOperation

The emitc.call_opaque operation represents a C++ function call. The callee can be an arbitrary non-empty string. The call allows specifying order of operands and attributes in the call as follows:

- integer value of index type refers to an operand;
- attribute which will get lowered to constant value in call;
Source code in xdsl/dialects/emitc.py
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
@irdl_op_definition
class EmitC_CallOpaqueOp(IRDLOperation):
    """
    The `emitc.call_opaque` operation represents a C++ function call. The callee can be an arbitrary non-empty string.
    The call allows specifying order of operands and attributes in the call as follows:

        - integer value of index type refers to an operand;
        - attribute which will get lowered to constant value in call;
    """

    name = "emitc.call_opaque"

    callee = prop_def(StringAttr)
    args = opt_prop_def(ArrayAttr)
    template_args = opt_prop_def(ArrayAttr)
    # The SSA‐value operands of the call
    call_args = var_operand_def()
    res = var_result_def()

    irdl_options = (ParsePropInAttrDict(),)
    assembly_format = (
        "$callee `(` $call_args `)` attr-dict `:` functional-type(operands, results)"
    )

    def __init__(
        self,
        callee: StringAttr | str,
        call_args: Sequence[SSAValue],
        result_types: Sequence[Attribute],
        args: ArrayAttr[Attribute] | None = None,
        template_args: ArrayAttr[Attribute] | None = None,
        attributes: dict[str, Attribute] | None = None,
    ):
        if isinstance(callee, str):
            callee = StringAttr(callee)
        super().__init__(
            properties={
                "callee": callee,
                "args": args,
                "template_args": template_args,
            },
            operands=[call_args],
            result_types=[result_types],
            attributes=attributes,
        )

    def verify_(self) -> None:
        if not self.callee.data:
            raise VerifyException("callee must not be empty")

        if self.args is not None:
            for arg in self.args.data:
                if isa(arg, IntegerAttr[IndexType]):
                    index = arg.value.data
                    if not (0 <= index < len(self.call_args)):
                        raise VerifyException("index argument is out of range")
                elif isinstance(arg, ArrayAttr):
                    # see https://github.com/llvm/llvm-project/blob/2eb733b5a6ab17a3ae812bb55c1c7c64569cadcd/mlir/lib/Dialect/EmitC/IR/EmitC.cpp#L342
                    # This part is referenced as a FIXME there.
                    raise VerifyException("array argument has no type")

        if self.template_args is not None:
            for t_arg in self.template_args.data:
                if not isa(
                    t_arg,
                    TypeAttribute | IntegerAttr | FloatAttr | EmitC_OpaqueAttr,
                ):
                    raise VerifyException("template argument has invalid type")

        for res_type in self.res.types:
            if isinstance(res_type, EmitC_ArrayType):
                raise VerifyException("cannot return array type")

name = 'emitc.call_opaque' class-attribute instance-attribute

callee = prop_def(StringAttr) class-attribute instance-attribute

args = opt_prop_def(ArrayAttr) class-attribute instance-attribute

template_args = opt_prop_def(ArrayAttr) class-attribute instance-attribute

call_args = var_operand_def() class-attribute instance-attribute

res = var_result_def() class-attribute instance-attribute

irdl_options = (ParsePropInAttrDict(),) class-attribute instance-attribute

assembly_format = '$callee `(` $call_args `)` attr-dict `:` functional-type(operands, results)' class-attribute instance-attribute

__init__(callee: StringAttr | str, call_args: Sequence[SSAValue], result_types: Sequence[Attribute], args: ArrayAttr[Attribute] | None = None, template_args: ArrayAttr[Attribute] | None = None, attributes: dict[str, Attribute] | None = None)

Source code in xdsl/dialects/emitc.py
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
def __init__(
    self,
    callee: StringAttr | str,
    call_args: Sequence[SSAValue],
    result_types: Sequence[Attribute],
    args: ArrayAttr[Attribute] | None = None,
    template_args: ArrayAttr[Attribute] | None = None,
    attributes: dict[str, Attribute] | None = None,
):
    if isinstance(callee, str):
        callee = StringAttr(callee)
    super().__init__(
        properties={
            "callee": callee,
            "args": args,
            "template_args": template_args,
        },
        operands=[call_args],
        result_types=[result_types],
        attributes=attributes,
    )

verify_() -> None

Source code in xdsl/dialects/emitc.py
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
def verify_(self) -> None:
    if not self.callee.data:
        raise VerifyException("callee must not be empty")

    if self.args is not None:
        for arg in self.args.data:
            if isa(arg, IntegerAttr[IndexType]):
                index = arg.value.data
                if not (0 <= index < len(self.call_args)):
                    raise VerifyException("index argument is out of range")
            elif isinstance(arg, ArrayAttr):
                # see https://github.com/llvm/llvm-project/blob/2eb733b5a6ab17a3ae812bb55c1c7c64569cadcd/mlir/lib/Dialect/EmitC/IR/EmitC.cpp#L342
                # This part is referenced as a FIXME there.
                raise VerifyException("array argument has no type")

    if self.template_args is not None:
        for t_arg in self.template_args.data:
            if not isa(
                t_arg,
                TypeAttribute | IntegerAttr | FloatAttr | EmitC_OpaqueAttr,
            ):
                raise VerifyException("template argument has invalid type")

    for res_type in self.res.types:
        if isinstance(res_type, EmitC_ArrayType):
            raise VerifyException("cannot return array type")