llvm/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td

//===- EmitCTypes.td - EmitC types -------------------------*- tablegen -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// Defines the MLIR EmitC types.
//
//===----------------------------------------------------------------------===//


#ifndef MLIR_DIALECT_EMITC_IR_EMITCTYPES
#define MLIR_DIALECT_EMITC_IR_EMITCTYPES

include "mlir/IR/AttrTypeBase.td"
include "mlir/Dialect/EmitC/IR/EmitCBase.td"
include "mlir/IR/BuiltinTypeInterfaces.td"

//===----------------------------------------------------------------------===//
// EmitC type definitions
//===----------------------------------------------------------------------===//

def EmitCType : Type<CPred<"emitc::isSupportedEmitCType($_self)">,
    "type supported by EmitC">;

def EmitCIntegerType : Type<CPred<"emitc::isSupportedIntegerType($_self)">,
    "integer type supported by EmitC">;

def EmitCFloatType : Type<CPred<"emitc::isSupportedFloatType($_self)">,
    "floating-point type supported by EmitC">;

class EmitC_Type<string name, string typeMnemonic, list<Trait> traits = []>
    : TypeDef<EmitC_Dialect, name, traits> {
  let mnemonic = typeMnemonic;
}

def EmitC_ArrayType : EmitC_Type<"Array", "array", [ShapedTypeInterface]> {
  let summary = "EmitC array type";

  let description = [{
    An array data type.

    Example:

    ```mlir
    // Array emitted as `int32_t[10]`
    !emitc.array<10xi32>
    // Array emitted as `float[10][20]`
    !emitc.array<10x20xf32>
    ```
  }];

  let parameters = (ins
    ArrayRefParameter<"int64_t">:$shape,
    "Type":$elementType
  );

  let builders = [
    TypeBuilderWithInferredContext<(ins
      "ArrayRef<int64_t>":$shape,
      "Type":$elementType
    ), [{
      return $_get(elementType.getContext(), shape, elementType);
    }]>
  ];
  let extraClassDeclaration = [{
    /// Returns if this type is ranked (always true).
    bool hasRank() const { return true; }

    /// Clone this array type with the given shape and element type. If the
    /// provided shape is `std::nullopt`, the current shape of the type is used.
    ArrayType cloneWith(std::optional<ArrayRef<int64_t>> shape,
                        Type elementType) const;

    static bool isValidElementType(Type type) {
      return emitc::isSupportedFloatType(type) ||
         emitc::isIntegerIndexOrOpaqueType(type) ||
         llvm::isa<PointerType>(type);
    }
  }];
  let genVerifyDecl = 1;
  let hasCustomAssemblyFormat = 1;
}

def EmitC_LValueType : EmitC_Type<"LValue", "lvalue"> {
  let summary = "EmitC lvalue type";

  let description = [{
    Values of this type can be assigned to and their address can be taken.
  }];

  let parameters = (ins "Type":$valueType);
  let builders = [
    TypeBuilderWithInferredContext<(ins "Type":$valueType), [{
      return $_get(valueType.getContext(), valueType);
    }]>
  ];
  let assemblyFormat = "`<` qualified($valueType) `>`";
  let genVerifyDecl = 1;
}

def EmitC_OpaqueType : EmitC_Type<"Opaque", "opaque"> {
  let summary = "EmitC opaque type";

  let description = [{
    An opaque data type of which the value gets emitted as is.

    Example:

    ```mlir
    !emitc.opaque<"int">
    !emitc.opaque<"mytype">
    !emitc.opaque<"std::vector<std::string>">
    ```
  }];

  let parameters = (ins StringRefParameter<"the opaque value">:$value);
  let assemblyFormat = "`<` $value `>`";
  let genVerifyDecl = 1;
}

def EmitC_PointerType : EmitC_Type<"Pointer", "ptr"> {
  let summary = "EmitC pointer type";

  let description = [{
    A pointer data type.

    Example:

    ```mlir
    // Pointer emitted as `int32_t*`
    !emitc.ptr<i32>
    // Pointer emitted as `float*`
    !emitc.ptr<f32>
    // Pointer emitted as `int*`
    !emitc.ptr<!emitc.opaque<"int">>
    ```
  }];

  let parameters = (ins "Type":$pointee);
  let builders = [
    TypeBuilderWithInferredContext<(ins "Type":$pointee), [{
      return $_get(pointee.getContext(), pointee);
    }]>
  ];
  let assemblyFormat = "`<` qualified($pointee) `>`";
  let genVerifyDecl = 1;
}

def EmitC_SignedSizeT : EmitC_Type<"SignedSizeT", "ssize_t"> {
  let summary = "EmitC signed size type";
  let description = [{
    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.
  }];
}

def EmitC_PtrDiffT : EmitC_Type<"PtrDiffT", "ptrdiff_t"> {
  let summary = "EmitC signed pointer diff type";
  let description = [{
    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>`.
  }];
}

def EmitC_SizeT : EmitC_Type<"SizeT", "size_t"> {
  let summary = "EmitC unsigned size type";
  let description = [{
    Unsigned data type as wide as platform-specific pointer types.
    It corresponds to `size_t` found in `<stddef.h>`.
  }];
}

class EmitC_LValueOf<list<Type> allowedTypes> : 
  ContainerType<
    AnyTypeOf<allowedTypes>,
    CPred<"::llvm::isa<::mlir::emitc::LValueType>($_self)">,
    "::llvm::cast<::mlir::emitc::LValueType>($_self).getValueType()",
    "emitc.lvalue",
    "::mlir::emitc::LValueType"
  >;

#endif // MLIR_DIALECT_EMITC_IR_EMITCTYPES