# 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; }; ```
{}