20#include <llvm/ADT/TypeSwitch.h>
35 inline ResultType
match(Type type) {
36 return llvm::TypeSwitch<Type, ResultType>(type)
37 .template Case<IndexType>([
this](
auto t) {
38 return static_cast<Derived *
>(
this)->caseIndex(t);
40 .
template Case<FeltType>([
this](
auto t) {
41 return static_cast<Derived *
>(
this)->caseFelt(t);
43 .
template Case<StringType>([
this](
auto t) {
44 return static_cast<Derived *
>(
this)->caseString(t);
46 .
template Case<TypeVarType>([
this](
auto t) {
47 return static_cast<Derived *
>(
this)->caseTypeVar(t);
49 .
template Case<ArrayType>([
this](
auto t) {
50 return static_cast<Derived *
>(
this)->caseArray(t);
52 .
template Case<StructType>([
this](
auto t) {
53 return static_cast<Derived *
>(
this)->caseStruct(t);
54 }).
template Default([
this](Type t) {
55 if (t.isSignlessInteger(1)) {
58 return static_cast<Derived *
>(
this)->caseInvalid(t);
64void BuildShortTypeString::appendSymName(StringRef str) {
72void BuildShortTypeString::appendSymRef(SymbolRefAttr sa) {
73 appendSymName(sa.getRootReference().getValue());
74 for (FlatSymbolRefAttr nestedRef : sa.getNestedReferences()) {
76 appendSymName(nestedRef.getValue());
81 size_t position = ret.size();
83 struct Impl : LLZKTypeSwitch<Impl, void> {
84 BuildShortTypeString &outer;
85 Impl(BuildShortTypeString &outerRef) : outer(outerRef) {}
87 void caseInvalid(Type _) { outer.ss <<
"!INVALID"; }
88 void caseBool(IntegerType _) { outer.ss <<
'b'; }
89 void caseIndex(IndexType _) { outer.ss <<
'i'; }
90 void caseFelt(FeltType _) { outer.ss <<
'f'; }
91 void caseString(StringType _) { outer.ss <<
's'; }
92 void caseTypeVar(TypeVarType t) {
94 outer.appendSymName(llvm::cast<TypeVarType>(t).getRefName());
97 void caseArray(ArrayType t) {
99 outer.append(t.getElementType());
101 outer.append(t.getDimensionSizes());
104 void caseStruct(StructType t) {
106 outer.appendSymRef(t.getNameRef());
107 if (ArrayAttr params = t.getParams()) {
109 outer.append(params.getValue());
114 Impl(*this).match(type);
117 ret.find(PLACEHOLDER, position) == std::string::npos &&
118 "formatting a Type should not produce the 'PLACEHOLDER' char"
130 size_t position = ret.size();
132 if (llvm::isa<IntegerAttr>(a)) {
133 IntegerAttr ia = llvm::cast<IntegerAttr>(a);
134 Type ty = ia.getType();
135 bool isUnsigned = ty.isUnsignedInteger() || ty.isSignlessInteger(1);
136 ia.getValue().print(ss, !isUnsigned);
137 }
else if (llvm::isa<SymbolRefAttr>(a)) {
138 appendSymRef(llvm::cast<SymbolRefAttr>(a));
139 }
else if (llvm::isa<TypeAttr>(a)) {
140 append(llvm::cast<TypeAttr>(a).getValue());
141 }
else if (llvm::isa<AffineMapAttr>(a)) {
144 filtered_raw_ostream fs(ss, [](
char c) {
return c ==
' '; });
145 llvm::cast<AffineMapAttr>(a).getValue().print(fs);
148 }
else if (llvm::isa<ArrayAttr>(a)) {
149 append(llvm::cast<ArrayAttr>(a).getValue());
155 ret.find(PLACEHOLDER, position) == std::string::npos &&
156 "formatting a non-null Attribute should not produce the 'PLACEHOLDER' char"
162 llvm::interleave(attrs, ss, [
this](Attribute a) { append(a); },
"_");
167 BuildShortTypeString bldr;
169 bldr.ret.reserve(base.size() + attrs.size());
172 auto END = attrs.end();
173 auto IT = attrs.begin();
176 for (
size_t pos; (pos = base.find(PLACEHOLDER, start)) != std::string::npos; start = pos + 1) {
178 bldr.ret.append(base, start, pos - start);
180 assert(IT != END &&
"must have an Attribute for every 'PLACEHOLDER' char");
184 bldr.ret.append(base, start, base.size() - start);
190 bldr.append(ArrayRef(IT, END));
198template <
typename... Types>
class TypeList {
201 template <
typename StreamType>
struct Appender {
204 template <
typename Ty>
static inline void append(StreamType &stream) {
205 stream <<
'\'' << Ty::name <<
'\'';
209 template <
typename First,
typename Second,
typename... Rest>
210 static void append(StreamType &stream) {
211 append<First>(stream);
213 append<Second, Rest...>(stream);
217 static inline void append(StreamType &stream) {
219 append<Types...>(stream);
226 template <
typename T>
static inline bool matches(
const T &value) {
227 return llvm::isa_and_present<Types...>(value);
230 static void reportInvalid(
EmitErrorFn emitError,
const Twine &foundName,
const char *aspect) {
231 InFlightDiagnostic diag = emitError().append(aspect,
" must be one of ");
232 Appender<InFlightDiagnostic>::append(diag);
233 diag.append(
" but found '", foundName,
'\'').report();
236 static inline void reportInvalid(
EmitErrorFn emitError, Attribute found,
const char *aspect) {
238 reportInvalid(emitError, found ? found.getAbstractAttribute().getName() :
"nullptr", aspect);
243 static inline std::string
getNames() {
250template <
class... Ts>
struct make_unique {
251 using type = TypeList<Ts...>;
254template <
class... Ts>
struct make_unique<TypeList<>, Ts...> : make_unique<Ts...> {};
256template <
class U,
class... Us,
class... Ts>
257struct make_unique<TypeList<U, Us...>, Ts...>
258 : std::conditional_t<
259 (std::is_same_v<U, Us> || ...) || (std::is_same_v<U, Ts> || ...),
260 make_unique<TypeList<Us...>, Ts...>, make_unique<TypeList<Us...>, Ts..., U>> {};
262template <
class... Ts>
using TypeListUnion =
typename make_unique<Ts...>::type;
268using ArrayDimensionTypes = TypeList<IntegerAttr, SymbolRefAttr, AffineMapAttr>;
275using StructParamTypes = TypeList<IntegerAttr, SymbolRefAttr, TypeAttr, AffineMapAttr>;
278 struct ColumnCheckData {
279 SymbolTableCollection *symbolTable =
nullptr;
280 Operation *op =
nullptr;
283 bool no_felt : 1 =
false;
284 bool no_string : 1 =
false;
285 bool no_non_signal_struct : 1 =
false;
286 bool no_signal_struct : 1 =
false;
287 bool no_array : 1 =
false;
288 bool no_var : 1 =
false;
289 bool no_int : 1 =
false;
290 bool no_struct_params : 1 =
false;
291 bool must_be_column : 1 =
false;
293 ColumnCheckData columnCheck;
298 bool validColumns(StructType s) {
299 if (!must_be_column) {
302 assert(columnCheck.symbolTable);
303 assert(columnCheck.op);
304 return succeeded(s.hasColumns(*columnCheck.symbolTable, columnCheck.op));
308 constexpr AllowedTypes &noFelt() {
313 constexpr AllowedTypes &noString() {
318 constexpr AllowedTypes &noStruct() {
319 no_non_signal_struct =
true;
320 no_signal_struct =
true;
324 constexpr AllowedTypes &noStructExceptSignal() {
325 no_non_signal_struct =
true;
326 no_signal_struct =
false;
330 constexpr AllowedTypes &noArray() {
335 constexpr AllowedTypes &noVar() {
340 constexpr AllowedTypes &noInt() {
345 constexpr AllowedTypes &noStructParams(
bool noStructParams =
true) {
346 no_struct_params = noStructParams;
350 constexpr AllowedTypes &onlyInt() {
352 return noFelt().noString().noStruct().noArray().noVar();
355 constexpr AllowedTypes &mustBeColumn(SymbolTableCollection &symbolTable, Operation *op) {
356 must_be_column =
true;
357 columnCheck.symbolTable = &symbolTable;
363 bool isValidTypeImpl(Type type);
365 bool areValidArrayDimSizes(ArrayRef<Attribute> dimensionSizes,
EmitErrorFn emitError =
nullptr) {
367 if (dimensionSizes.empty()) {
369 emitError().append(
"array must have at least one dimension").report();
376 for (Attribute a : dimensionSizes) {
377 if (!ArrayDimensionTypes::matches(a)) {
378 ArrayDimensionTypes::reportInvalid(emitError, a,
"Array dimension");
380 }
else if (no_var && !llvm::isa_and_present<IntegerAttr>(a)) {
381 TypeList<IntegerAttr>::reportInvalid(emitError, a,
"Concrete array dimension");
392 bool isValidArrayElemTypeImpl(Type type) {
394 return !llvm::isa<ArrayType>(type) && isValidTypeImpl(type);
397 bool isValidArrayTypeImpl(
398 Type elementType, ArrayRef<Attribute> dimensionSizes,
EmitErrorFn emitError =
nullptr
400 if (!areValidArrayDimSizes(dimensionSizes, emitError)) {
405 if (!isValidArrayElemTypeImpl(elementType)) {
413 elementType.getAbstractType().getName(),
'\''
423 bool isValidArrayTypeImpl(Type type) {
424 if (ArrayType arrTy = llvm::dyn_cast<ArrayType>(type)) {
425 return isValidArrayTypeImpl(arrTy.getElementType(), arrTy.getDimensionSizes());
432 bool areValidStructTypeParams(ArrayAttr params,
EmitErrorFn emitError =
nullptr) {
436 if (no_struct_params) {
440 for (Attribute p : params) {
441 if (!StructParamTypes::matches(p)) {
442 StructParamTypes::reportInvalid(emitError, p,
"Struct parameter");
444 }
else if (TypeAttr tyAttr = llvm::dyn_cast<TypeAttr>(p)) {
445 if (!isValidTypeImpl(tyAttr.getValue())) {
447 emitError().append(
"expected a valid LLZK type but found ", tyAttr.getValue()).report();
451 }
else if (no_var && !llvm::isa<IntegerAttr>(p)) {
452 TypeList<IntegerAttr>::reportInvalid(emitError, p,
"Concrete struct parameter");
465bool AllowedTypes::isValidTypeImpl(Type type) {
467 !(no_int && no_felt && no_string && no_var && no_non_signal_struct && no_signal_struct &&
469 "All types have been deactivated"
471 struct Impl : LLZKTypeSwitch<Impl, bool> {
473 Impl(AllowedTypes &outerRef) : outer(outerRef) {}
475 bool caseBool(IntegerType t) {
return !outer.no_int && t.isSignlessInteger(1); }
476 bool caseIndex(IndexType _) {
return !outer.no_int; }
477 bool caseFelt(FeltType _) {
return !outer.no_felt; }
478 bool caseString(StringType _) {
return !outer.no_string; }
479 bool caseTypeVar(TypeVarType _) {
return !outer.no_var; }
480 bool caseArray(ArrayType t) {
481 return !outer.no_array &&
482 outer.isValidArrayTypeImpl(t.getElementType(), t.getDimensionSizes());
484 bool caseStruct(StructType t) {
486 if ((outer.no_signal_struct && outer.no_non_signal_struct) || !outer.validColumns(t)) {
490 (!outer.no_non_signal_struct && outer.areValidStructTypeParams(t.getParams()));
492 bool caseInvalid(Type _) {
return false; }
494 return Impl(*this).match(type);
499bool isValidType(Type type) {
return AllowedTypes().isValidTypeImpl(type); }
502 return AllowedTypes().noString().noInt().mustBeColumn(symbolTable, op).isValidTypeImpl(type);
508 return AllowedTypes().noString().noStructExceptSignal().isValidTypeImpl(type);
513 return AllowedTypes().noString().noStruct().noArray().isValidTypeImpl(type);
521 return AllowedTypes().noVar().noStructParams(!allowStructParams).isValidTypeImpl(type);
525 if (
auto structParamTy = llvm::dyn_cast<StructType>(type)) {
539 bool encountered =
false;
540 type.walk([&](AffineMapAttr a) {
542 return WalkResult::interrupt();
551 uint64_t caseBool(IntegerType _) {
return 1; }
552 uint64_t caseIndex(IndexType _) {
return 1; }
553 uint64_t caseFelt(
FeltType _) {
return 1; }
555 int64_t n = t.getNumElements();
557 return static_cast<uint64_t
>(n);
563 llvm_unreachable(
"not a valid EmitEq type");
565 uint64_t caseString(
StringType _) { llvm_unreachable(
"not a valid EmitEq type"); }
566 uint64_t caseTypeVar(
TypeVarType _) { llvm_unreachable(
"tvar has unknown cardinality"); }
567 uint64_t caseInvalid(Type _) { llvm_unreachable(
"not a valid LLZK type"); }
569 return Impl().match(type);
582using AffineInstantiations = DenseMap<std::pair<AffineMapAttr, Side>, IntegerAttr>;
585 ArrayRef<StringRef> rhsRevPrefix;
586 UnificationMap *unifications;
587 AffineInstantiations *affineToIntTracker;
590 llvm::function_ref<bool(Type oldTy, Type newTy)> overrideSuccess;
592 UnifierImpl(UnificationMap *unificationMap, ArrayRef<StringRef> rhsReversePrefix = {})
593 : rhsRevPrefix(rhsReversePrefix), unifications(unificationMap), affineToIntTracker(nullptr),
594 overrideSuccess(nullptr) {}
597 const ArrayRef<Attribute> &lhsParams,
const ArrayRef<Attribute> &rhsParams,
598 bool unifyDynamicSize =
false
600 auto pred = [
this, unifyDynamicSize](
auto lhsAttr,
auto rhsAttr) {
601 return paramAttrUnify(lhsAttr, rhsAttr, unifyDynamicSize);
603 return (lhsParams.size() == rhsParams.size()) &&
604 std::equal(lhsParams.begin(), lhsParams.end(), rhsParams.begin(), pred);
607 UnifierImpl &trackAffineToInt(AffineInstantiations *tracker) {
608 this->affineToIntTracker = tracker;
612 UnifierImpl &withOverrides(llvm::function_ref<
bool(Type oldTy, Type newTy)> overrides) {
613 this->overrideSuccess = overrides;
620 const ArrayAttr &lhsParams,
const ArrayAttr &rhsParams,
bool unifyDynamicSize =
false
622 if (lhsParams && rhsParams) {
623 return typeParamsUnify(lhsParams.getValue(), rhsParams.getValue(), unifyDynamicSize);
626 return !lhsParams && !rhsParams;
631 if (!
typesUnify(lhs.getElementType(), rhs.getElementType())) {
636 lhs.getDimensionSizes(), rhs.getDimensionSizes(),
true
642 SmallVector<StringRef> rhsNames =
getNames(rhs.getNameRef());
643 rhsNames.insert(rhsNames.begin(), rhsRevPrefix.rbegin(), rhsRevPrefix.rend());
644 if (rhsNames !=
getNames(lhs.getNameRef())) {
655 if (overrideSuccess && overrideSuccess(lhs, rhs)) {
659 if (TypeVarType lhsTvar = llvm::dyn_cast<TypeVarType>(lhs)) {
660 track(Side::LHS, lhsTvar.getNameRef(), rhs);
663 if (TypeVarType rhsTvar = llvm::dyn_cast<TypeVarType>(rhs)) {
664 track(Side::RHS, rhsTvar.getNameRef(), lhs);
667 if (llvm::isa<StructType>(lhs) && llvm::isa<StructType>(rhs)) {
668 return structTypesUnify(llvm::cast<StructType>(lhs), llvm::cast<StructType>(rhs));
670 if (llvm::isa<ArrayType>(lhs) && llvm::isa<ArrayType>(rhs)) {
671 return arrayTypesUnify(llvm::cast<ArrayType>(lhs), llvm::cast<ArrayType>(rhs));
677 template <
typename Tracker,
typename Key,
typename Val>
678 inline void track(Tracker &tracker, Side side, Key keyHead, Val val) {
679 auto key = std::make_pair(keyHead, side);
680 auto it = tracker.find(key);
681 if (it == tracker.end()) {
682 tracker.try_emplace(key, val);
683 }
else if (it->getSecond() != val) {
684 it->second =
nullptr;
688 void track(Side side, SymbolRefAttr symRef, Type ty) {
691 if (TypeVarType tvar = dyn_cast<TypeVarType>(ty)) {
693 attr = tvar.getNameRef();
696 attr = TypeAttr::get(ty);
700 track(*unifications, side, symRef, attr);
704 void track(Side side, SymbolRefAttr symRef, Attribute attr) {
707 if (TypeAttr tyAttr = dyn_cast<TypeAttr>(attr)) {
708 if (TypeVarType tvar = dyn_cast<TypeVarType>(tyAttr.getValue())) {
709 attr = tvar.getNameRef();
718 if (SymbolRefAttr otherSymAttr = dyn_cast<SymbolRefAttr>(attr)) {
719 track(*unifications,
reverse(side), otherSymAttr, symRef);
721 track(*unifications, side, symRef, attr);
725 void track(Side side, AffineMapAttr affineAttr, IntegerAttr intAttr) {
726 if (affineToIntTracker) {
730 track(*affineToIntTracker, side, affineAttr, intAttr);
734 bool paramAttrUnify(Attribute lhsAttr, Attribute rhsAttr,
bool unifyDynamicSize =
false) {
738 if (lhsAttr == rhsAttr) {
743 if (AffineMapAttr lhsAffine = llvm::dyn_cast<AffineMapAttr>(lhsAttr)) {
744 if (IntegerAttr rhsInt = llvm::dyn_cast<IntegerAttr>(rhsAttr)) {
746 track(Side::LHS, lhsAffine, rhsInt);
751 if (AffineMapAttr rhsAffine = llvm::dyn_cast<AffineMapAttr>(rhsAttr)) {
752 if (IntegerAttr lhsInt = llvm::dyn_cast<IntegerAttr>(lhsAttr)) {
754 track(Side::RHS, rhsAffine, lhsInt);
761 if (SymbolRefAttr lhsSymRef = llvm::dyn_cast<SymbolRefAttr>(lhsAttr)) {
762 track(Side::LHS, lhsSymRef, rhsAttr);
765 if (SymbolRefAttr rhsSymRef = llvm::dyn_cast<SymbolRefAttr>(rhsAttr)) {
766 track(Side::RHS, rhsSymRef, lhsAttr);
770 auto dyn_cast_if_dynamic = [](Attribute attr) -> IntegerAttr {
771 if (
auto intAttr = llvm::dyn_cast<IntegerAttr>(attr)) {
778 auto isa_const = [](Attribute attr) {
779 return llvm::isa_and_present<IntegerAttr, SymbolRefAttr, AffineMapAttr>(attr);
781 if (
auto lhsIntAttr = dyn_cast_if_dynamic(lhsAttr)) {
782 if (isa_const(rhsAttr)) {
786 if (
auto rhsIntAttr = dyn_cast_if_dynamic(rhsAttr)) {
787 if (isa_const(lhsAttr)) {
792 if (TypeAttr lhsTy = llvm::dyn_cast<TypeAttr>(lhsAttr)) {
793 if (TypeAttr rhsTy = llvm::dyn_cast<TypeAttr>(rhsAttr)) {
794 return typesUnify(lhsTy.getValue(), rhsTy.getValue());
805 const ArrayRef<Attribute> &lhsParams,
const ArrayRef<Attribute> &rhsParams,
808 return UnifierImpl(unifications).typeParamsUnify(lhsParams, rhsParams);
814 const ArrayAttr &lhsParams,
const ArrayAttr &rhsParams,
UnificationMap *unifications
816 return UnifierImpl(unifications).typeParamsUnify(lhsParams, rhsParams);
822 return UnifierImpl(unifications, rhsReversePrefix).arrayTypesUnify(lhs, rhs);
829 return UnifierImpl(unifications, rhsReversePrefix).structTypesUnify(lhs, rhs);
833 Type lhs, Type rhs, ArrayRef<StringRef> rhsReversePrefix,
UnificationMap *unifications
835 return UnifierImpl(unifications, rhsReversePrefix).typesUnify(lhs, rhs);
839 Type oldTy, Type newTy, llvm::function_ref<
bool(Type oldTy, Type newTy)> knownOldToNew
842 AffineInstantiations affineInstantiations;
844 if (!UnifierImpl(&unifications)
845 .trackAffineToInt(&affineInstantiations)
846 .withOverrides(knownOldToNew)
856 auto entryIsRHS = [](
const auto &entry) {
return entry.first.second ==
Side::RHS; };
857 return !llvm::any_of(unifications, entryIsRHS) && !llvm::any_of(affineInstantiations, entryIsRHS);
861 if (AllowedTypes().onlyInt().isValidTypeImpl(attr.getType())) {
864 return IntegerAttr::get(IndexType::get(attr.getContext()), attr.getValue());
868 if (IntegerAttr intAttr = llvm::dyn_cast_if_present<IntegerAttr>(attr)) {
879 if (IntegerAttr intAttr = llvm::dyn_cast_if_present<IntegerAttr>(in)) {
880 Type attrTy = intAttr.getType();
881 if (!AllowedTypes().onlyInt().isValidTypeImpl(attrTy)) {
884 .append(
"IntegerAttr must have type 'index' or 'i1' but found '", attrTy,
'\'')
894 if (AffineMapAttr affineAttr = llvm::dyn_cast_if_present<AffineMapAttr>(in)) {
895 AffineMap map = affineAttr.getValue();
896 if (map.getNumResults() != 1) {
900 "AffineMapAttr must yield a single result, but found ", map.getNumResults(),
912 return success(AllowedTypes().areValidStructTypeParams(params, emitError));
916 return success(AllowedTypes().areValidArrayDimSizes(dimensionSizes, emitError));
921 return success(AllowedTypes().isValidArrayTypeImpl(elementType, dimensionSizes, emitError));
926 using TypeVarAttrs = TypeList<SymbolRefAttr>;
927 if (!TypeListUnion<ArrayDimensionTypes, StructParamTypes, TypeVarAttrs>::matches(attr)) {
928 llvm::report_fatal_error(
929 "Legal type parameters are inconsistent. Encountered " +
930 attr.getAbstractAttribute().getName()
Note: If any symbol refs in an input Type/Attribute use any of the special characters that this class...
static std::string from(mlir::Type type)
Return a brief string representation of the given LLZK type.
static constexpr ::llvm::StringLiteral name
::mlir::SymbolRefAttr getNameRef() const
LogicalResult verifyAffineMapAttrType(EmitErrorFn emitError, Attribute in)
void assertValidAttrForParamOfType(Attribute attr)
uint64_t computeEmitEqCardinality(Type type)
bool isValidArrayType(Type type)
LogicalResult verifyIntAttrType(EmitErrorFn emitError, Attribute in)
bool isConcreteType(Type type, bool allowStructParams)
bool isValidArrayElemType(Type type)
llvm::SmallVector< StringRef > getNames(SymbolRefAttr ref)
llvm::function_ref< mlir::InFlightDiagnostic()> EmitErrorFn
bool isValidGlobalType(Type type)
bool structTypesUnify(StructType lhs, StructType rhs, ArrayRef< StringRef > rhsReversePrefix, UnificationMap *unifications)
SmallVector< Attribute > forceIntAttrTypes(ArrayRef< Attribute > attrList)
LogicalResult verifyArrayType(EmitErrorFn emitError, Type elementType, ArrayRef< Attribute > dimensionSizes)
bool isValidColumnType(Type type, SymbolTableCollection &symbolTable, Operation *op)
mlir::DenseMap< std::pair< mlir::SymbolRefAttr, Side >, mlir::Attribute > UnificationMap
Optional result from type unifications.
bool isNullOrEmpty(mlir::ArrayAttr a)
bool isValidEmitEqType(Type type)
bool isValidType(Type type)
bool arrayTypesUnify(ArrayType lhs, ArrayType rhs, ArrayRef< StringRef > rhsReversePrefix, UnificationMap *unifications)
bool isDynamic(IntegerAttr intAttr)
bool isSignalType(Type type)
constexpr char COMPONENT_NAME_SIGNAL[]
Symbol name for the struct/component representing a signal.
bool typesUnify(Type lhs, Type rhs, ArrayRef< StringRef > rhsReversePrefix, UnificationMap *unifications)
bool typeParamsUnify(const ArrayRef< Attribute > &lhsParams, const ArrayRef< Attribute > &rhsParams, UnificationMap *unifications)
bool isMoreConcreteUnification(Type oldTy, Type newTy, llvm::function_ref< bool(Type oldTy, Type newTy)> knownOldToNew)
LogicalResult verifyStructTypeParams(EmitErrorFn emitError, ArrayAttr params)
Attribute forceIntAttrType(Attribute attr)
std::string buildStringViaCallback(Func &&appendFn, Args &&...args)
Generate a string by calling the given appendFn with an llvm::raw_ostream & as the first argument fol...
IntegerAttr forceIntType(IntegerAttr attr)
bool hasAffineMapAttr(Type type)
int64_t fromAPInt(llvm::APInt i)
mlir::LogicalResult checkValidType(EmitErrorFn emitError, mlir::Type type)
bool isValidConstReadType(Type type)
LogicalResult verifyArrayDimSizes(EmitErrorFn emitError, ArrayRef< Attribute > dimensionSizes)
Template pattern for performing some operation by cases based on a given LLZK type.
ResultType match(Type type)