# Clift
## types and attributes
---
Note that as useful as the textual assembly is for visualising MLIR, it does not always accurately represent the in-memory MLIR data structure.
---
```mlir
// Type alias for a signed 1-byte Clift primitive type.
!int8_t = !clift.primitive<signed 1>
// !int8_t and !mytype name the same type.
!mytype = !clift.primitive<signed 1>
```
* MLIR types have no intrinsic identity. `int8_t` and `mytype` name exactly the same type.
* The aliases exist only in assembly and have no in-memory representation.
---
```cpp
auto T = clift::PrimitiveType::get(Context,
PrimitiveKind::SignedKind,
/*Size=*/1);
auto U = clift::PrimitiveType::get(Context,
PrimitiveKind::SignedKind,
/*Size=*/1);
```
* `TypeKind::get` constructs an MLIR type.
* `Context` is the `MLIRContext *`.
* Once again, `T` and `U` name the same type.
* `getChecked` verifies arguments but has issues.
---
`mlir::Type` (and derivatives) are cheap pointer-like types.
```cpp
mlir::Type T = clift::PrimitiveType::get(...);
mlir::Type U = T;
revng_assert(T); // Not null
revng_assert(T == U); // Equivalent
```
---
### Clift type related files
* `CliftTypes.td` - tablegen declarations
* `CliftTypes.h` - C++ header; includes helpers
* `CliftTypes.cpp` - C++ implementation
---
### `clift::LabelType`
```cpp
struct LabelType {
};
```
* Has only a single type.
* No model equivalent.
---
### Type interfaces, `clift::ValueType`
* Type kinds can implement interfaces.
* The simplest of these is `ValueType`.
```cpp
struct ValueType {
uint64_t getByteSize();
bool isConst();
ValueType addConst();
ValueType removeConst();
};
```
---
### `clift::PrimitiveType`
```cpp
struct PrimitiveType : ValueType {
clift::PrimitiveKind Kind;
uint64_t Size;
bool IsConst;
};
```
```mlir
!generic64_t = !clift.primitive<generic 8>
```
* Maps directly to the model equivalent.
---
### `!clift.const`
The Clift in-memory representation contains bool parameters on each concrete value type.
However, constness is represented differently in the Clift assembly:
```mlir
!const_uint8_t = !clift.const< !uint8_t >
```
---
### `clift::PointerType`
```cpp
struct PointerType : ValueType {
ValueType PointeeType;
uint64_t PointerSize;
bool IsConst;
};
```
```mlir
!ptr64_uint8_t = !clift.ptr< 8 to !uint8_t >
```
* Maps directly to the model equivalent.
---
### `clift::ArrayType`
```cpp
struct ArrayType : ValueType {
ValueType ElementType;
uint64_t ElementsCount;
};
```
* Has no const of its own.
* Maps directly to the model equivalent.
---
### Interface: `clift::DefinedType`
```cpp
struct DefinedType : ValueType {
llvm::StringRef getHandle();
MutableStringAttr getMutableName();
llvm::StringRef getName();
};
```
* Similar to `DefinedType`; not a separate entity.
* Base of all concrete defined type kinds.
---
### `clift::EnumType`
```cpp
struct EnumType : DefinedType {
EnumAttr Definition;
bool IsConst;
};
```
```mlir
!E = !clift.enum<
"/type-definition/1-EnumDefinition" as "E" : !int32_t {
"/enum-entry/1-EnumDefinition/0" as "A" : 42
}
>
```
* Maps directly to the model equivalent.
* Implemented using a helper attribute.
---
### Attributes primer
* Attributes behave very much like types.
* Used as building blocks of type kinds.
* Can also be attached to operations.
```mlir
// Introduces an alias for an attribute value.
//
// Please excuse the overloaded terminology;
// clift.attribute is currently the only
// assembly-visible Clift attribute.
#rax_attr = #clift.attribute<"_REG"("rax_x86_64")>
```
---
```cpp
struct EnumFieldAttr {
llvm::StringRef Handle;
MutableStringAttr Name;
uint64_t RawValue;
};
struct EnumAttr {
llvm::StringRef Handle;
MutableStringAttr Name;
ValueType UnderlyingType;
llvm::ArrayRef<EnumFieldAttr> Fields;
};
```
---
### `clift::TypedefType`
```cpp
struct TypedefType : DefinedType {
TypedefAttr Definition;
bool IsConst;
};
```
```mlir
!U = !clift.typedef<
"/type-definition/1-TypedefDefinition" as "U" : !uint32_t
>
```
* Maps directly to the model equivalent.
* In contrast to C, treated as a distinct type.
---
```cpp
struct TypedefAttr {
llvm::StringRef Handle;
MutableStringAttr Name;
ValueType UnderlyingType;
};
```
---
### `clift::FunctionType`
```cpp
struct FunctionType : DefinedType {
llvm::StringRef Handle;
mlir::Type ReturnType;
llvm::ArrayRef<mlir::Type> ArgumentTypes;
};
```
```mlir
!F = !clift.func<
"/type-definition/1-CABIFunctionDefinition" as "F"
: !int32_t(!int32_t, !int32_t)
>
```
* No mapping to a single a model type kind.
* No need for const; no need for an attribute.
---
### Interface: `clift::ClassType`
```cpp
struct ClassType : DefinedType {
bool isComplete();
llvm::ArrayRef<FieldAttr> getFields();
};
```
* Base of struct and union type kinds.
---
### `clift::StructType`
```cpp
struct StructType : ClassType {
StructAttr Definition;
bool IsConst;
};
```
```mlir
!S = !clift.struct<
"/type-definition/1-StructDefinition" as "S" : size(8) {
"/struct-field/.../0" as "x" : offset(0) !int32_t,
"/struct-field/.../4" as "y" : offset(4) !int32_t
}
>
```
* Maps directly to the model equivalent.
* Definition attribute implemented in C++.
---
```cpp
struct FieldAttr {
llvm::StringRef Handle;
MutableStringAttr Name;
uint64_t Offset;
ValueType Type;
};
struct StructAttr {
llvm::StringRef Handle;
uint64_t Size;
llvm::ArrayRef<FieldAttr> Fields;
};
```
---
### `clift::UnionAttr`
```cpp
struct UnionType : ClassType {
UnionAttr Definition;
bool IsConst;
};
```
```mlir
!U = !clift.union<
"/type-definition/1-UnionDefinition" as "U" : size(4) {
"/union-field/.../0" as "x" : !int32_t,
"/union-field/.../1" as "y" : !int32_t
}
>
```
* Maps directly to the model equivalent.
* Definition attribute implemented in C++.
---
```cpp
struct UnionAttr {
llvm::StringRef Handle;
uint64_t Size;
llvm::ArrayRef<FieldAttr> Fields;
};
```
* All fields have offset zero.
---
# Clift
## operations
---
### `mlir::ModuleOp`
```mlir
module {
// Has a single region containing other operations.
}
```
---
### Operation attributes
* Attributes can be attached to all operations.
* All attributes of an operation have names.
* *Inherent* attributes are part of op definition.
* *Discardable* attributes are attached by user.
---
### `clift.module`
```mlir
module attributes { clift.module } {
}
```
* `clift.module` is a discardable attribute.
* Has type `UnitAttr` (a monostate value).
* Causes the module operation to be verified.
---
### Clift operation related files
* `Clift.td` - tablegen declarations
* `Clift.h` - C++ header
* `Clift.cpp` - C++ implementation
* `CliftOpHelpers.h` - C++ helpers
---
### Interface: `GlobalOpInterface`
```cpp
struct GlobalOpInterface {
virtual ValueType getType() = 0;
virtual llvm::StringRef getHandle() = 0;
};
```
* Base of all module-level operations
---
### `clift::FunctionOp`
```cpp
struct FunctionOp : GlobalOpInterface {
llvm::StringRef SymName;
FunctionType Type;
DictArrayAttr ArgAttrs;
DictArrayAttr ResAttrs;
llvm::StringRef Handle;
mlir::Region Body;
};
```
---
### `clift::GlobalVariableOp`
```cpp
struct GlobalVariableOp : GlobalOpInterface {
llvm::StringRef SymName;
llvm::StringRef Handle;
ValueType Type;
mlir::Region Initializer;
};
```