blob: ca0ba39059cf33667feb3544b2266665b2552228 [file] [log] [blame]
// Copyright 2019 The IREE Authors
//
// Licensed 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
#ifndef IREE_DIALECT_UTIL_IR_UTIL_BASE
#define IREE_DIALECT_UTIL_IR_UTIL_BASE
include "mlir/IR/OpBase.td"
//===----------------------------------------------------------------------===//
// IREE base dialect used for types common across IREE subdialects.
//===----------------------------------------------------------------------===//
def Util_Dialect : Dialect {
let name = "util";
let cppNamespace = "::mlir::iree_compiler::IREE::Util";
let summary = [{
A dialect used for types common across IREE subdialects.
}];
}
//===----------------------------------------------------------------------===//
// General types and helpers
//===----------------------------------------------------------------------===//
def Util_Bool :
AnyTypeOf<[I1, I8], "boolean-storing type (1 or 8 -bit integer)">;
def Util_Element : AnyTypeOf<[AnySignlessInteger, AnyFloat]>;
def Util_MemRef : MemRefOf<[Util_Element]>;
def Util_Tensor : TensorOf<[Util_Element]>;
def Util_Offset : AnyTypeOf<[Index, AnyInteger]>;
class Util_IndexAttrBase<string descr> :
TypedAttrBase<
Index, "IntegerAttr",
And<[
CPred<"$_self.isa<IntegerAttr>()">,
CPred<"$_self.cast<IntegerAttr>().getType().isIndex()">,
]>,
descr> {
let returnType = [{ APInt }];
}
def Util_IndexAttr : Util_IndexAttrBase<"size_t">;
def Util_TiedOpStorageAttr :
TypedArrayAttrBase<Util_IndexAttr, "64-bit integer array attribute"> {
let constBuilderCall = "$_builder.getI64ArrayAttr($0)";
}
//===----------------------------------------------------------------------===//
// Status codes
//===----------------------------------------------------------------------===//
def Util_Status : I<32>;
//===----------------------------------------------------------------------===//
// Attribute constraints
//===----------------------------------------------------------------------===//
def FuncTypeAttr : TypeAttrBase<"FunctionType", "function type">;
class IntegerAttrInRange<int min, int max> : AttrConstraint<
CPred<"$_self.cast<IntegerAttr>().getInt() >= " # min # " && "
"$_self.cast<IntegerAttr>().getInt() <= " # max>,
"within the range [" # min # ", " # max # "] inclusive">;
class AliasedSymbolRefAttr : Attr<CPred<"$_self.isa<FlatSymbolRefAttr>()">,
"symbol reference attribute"> {
let storageType = [{ FlatSymbolRefAttr }];
let returnType = [{ StringRef }];
let valueType = NoneType;
let constBuilderCall = "mlir::SymbolRefAttr::get($_builder.getContext(), $0)";
}
//===----------------------------------------------------------------------===//
// Util_NamedTuple type constraint
//===----------------------------------------------------------------------===//
class Util_NamedTupleElement<int thisOrdinal, string thisName, Type thisType> {
int ordinal = thisOrdinal;
string name = thisName;
Type type = thisType;
}
// Check if all of the tuple elements are buildable.
class Util_AreTupleElementsBuildable<list<Util_NamedTupleElement> lst> {
bit ret = !foldl(1, lst, lhs, y, !and(lhs, !ne(y.type.builderCall, "")));
}
class Util_NamedTupleOf<list<Util_NamedTupleElement> elements, string descr> :
Type<And<[
IsTupleTypePred,
CPred<"$_self.cast<TupleType>().size() == " # !size(elements)>,
And<!foreach(element, elements,
SubstLeaves<
"$_self",
"$_self.cast<TupleType>().getType(" # element.ordinal # ")",
element.type.predicate>)>
]>, descr> {
// Generate a builder call if all of the elements are buildable.
let builderCall = !if(!eq(Util_AreTupleElementsBuildable<elements>.ret, 0),
"", "$_builder.getTupleType({" #
!interleave(!foreach(t, elements, t.type.builderCall), ", ") # "})"
);
}
//===----------------------------------------------------------------------===//
// Util_StructAttr
//===----------------------------------------------------------------------===//
// This has a custom tablegen generator in StructAttrGen.cpp to create the
// attribute and storage types. It differs from the core MLIR StructAttr
// by more closely matching what handwritten C++ would have (better typing
// and ergonomics and custom parser/printer).
class Util_StructFieldAttr<string thisName, Attr thisType> {
string name = thisName;
Attr type = thisType;
}
class Util_StructAttr<string thisKind, string name, Dialect dialect,
list<Util_StructFieldAttr> attributes>
: Attr<CPred<"$_self.isa<" # name # ">()">,
"structured attribute of " # name> {
string kind = thisKind;
string className = name;
string cppNamespace = ?;
let storageType = name;
let returnType = name;
let convertFromStorage = "$_self";
Dialect structDialect = dialect;
list<Util_StructFieldAttr> fields = attributes;
}
//===----------------------------------------------------------------------===//
// util.ptr<T> types
//===----------------------------------------------------------------------===//
def Util_AnyPtr : DialectType<
Util_Dialect,
CPred<"$_self.isa<IREE::Util::PtrType>()">,
"ptr"> {
let description = [{
Pointer to a typed value.
}];
}
class Util_PtrOf<Type type> :
Type<And<[
CPred<"$_self.isa<IREE::Util::PtrType>()">,
SubstLeaves<"$_self", "$_self.cast<IREE::Util::PtrType>().getTargetType()",
type.predicate>
]>, "ptr<" # type.summary # ">"> {
// Set the builder call if the base type has a builder call.
string builderCall = !if(!empty(type.builderCall),
"", "IREE::Util::PtrType::get(" # type.builderCall # ")");
}
class Util_AnyPtrOf<list<Type> types> :
Type<And<[
CPred<"$_self.isa<IREE::Util::PtrType>()">,
Or<!foreach(type, types,
SubstLeaves<
"$_self",
"$_self.cast<IREE::Util::PtrType>().getTargetType()",
type.predicate>)>,
]>, !interleave(!foreach(type, types, type.summary), " or ")> {
string builderCall = "";
}
//===----------------------------------------------------------------------===//
// Global types
//===----------------------------------------------------------------------===//
def Util_GlobalRefAttr : Confined<FlatSymbolRefAttr, [
ReferToOp<"IREE::Util::GlobalOp">,
]>;
def Util_AnyGlobalPtr : TypeAlias<Util_AnyPtr>;
// TODO(benvanik): actually implement Util_GlobalPtrOf.
class Util_GlobalPtrOf<list<Type> types> : TypeAlias<Util_AnyPtr> {
// Suppress unused template argument warning.
int unused = !size(types);
}
//===----------------------------------------------------------------------===//
// Buffer types
//===----------------------------------------------------------------------===//
def Util_AnySerializableAttr : Attr<Or<[
CPred<"$_self.isa<mlir::DenseElementsAttr>()">,
CPred<"$_self.isa<IREE::Util::SerializableAttrInterface>()">,
]>, "buffer-like constant attribute values"> {
let storageType = [{ ::mlir::Attribute }];
let returnType = [{ ::mlir::Attribute }];
let convertFromStorage = "$_self";
}
// TODO(benvanik): rework these as a single type with an access mode attr.
def ByteBufferType : DialectType<
Util_Dialect,
CPred<"$_self.isa<IREE::Util::ByteBufferType>()">,
"byte_buffer"> {
let description = [{
A constant buffer of mapped host memory.
}];
}
def ByteBufferRefAttr : AliasedSymbolRefAttr;
def MutableByteBufferType : DialectType<
Util_Dialect,
CPred<"$_self.isa<IREE::Util::MutableByteBufferType>()">,
"mutable_byte_buffer"> {
let description = [{
A buffer of read-write host memory.
}];
}
//===----------------------------------------------------------------------===//
// List types
//===----------------------------------------------------------------------===//
def Util_AnyList : DialectType<
Util_Dialect,
CPred<"$_self.isa<IREE::Util::ListType>()">,
"list"> {
let description = [{
A resizable list of some type.
}];
}
class Util_ListOf<Type type> :
Type<And<[
CPred<"$_self.isa<IREE::Util::ListType>()">,
SubstLeaves<"$_self",
"$_self.cast<IREE::Util::ListType>().getElementType()",
type.predicate>
]>, "list<" # type.summary # ">"> {
// Set the builder call if the base type has a builder call.
string builderCall = !if(!empty(type.builderCall),
"", "IREE::Util::ListType::get(" # type.builderCall # ")");
}
//===----------------------------------------------------------------------===//
// Common traits
//===----------------------------------------------------------------------===//
// TODO(b/143184519): add descriptions to other types.
// Operations with this trait indicate that they may yield execution of the
// current fiber. Invokers of the op must be yield-safe and assume that there
// may be a significant delay between when the operation is invoked and when it
// completes.
//
// TODO(benvanik): implement yield semantics.
// Need to add a new call type and function attr for 'async', then can validate
// entire parts of the call tree are either async-compatible or async-hostile.
// Only vm.call_async callees may contain an operation with YieldPoint.
def YieldPoint : NativeOpTrait<"IREE::Util::YieldPoint">;
// Denotes that an operation is potentially "unsafe" if used.
// Untrusted modules containing ops marked as unsafe will fail to verify at
// runtime if loaded for dynamic execution.
def Unsafe : NativeOpTrait<"IREE::Util::Unsafe">;
#endif // IREE_DIALECT_UTIL_IR_UTIL_BASE