30#include <mlir/Dialect/Arith/IR/Arith.h>
31#include <mlir/IR/AttrTypeSubElements.h>
33#include <llvm/ADT/TypeSwitch.h>
36#define DEBUG_TYPE "llzk-flatten"
51 SmallVector<pod::RecordAttr> records;
53 Type converted = converter.convertType(record.getType());
57 records.push_back(pod::RecordAttr::get(type.getContext(), record.getName(), converted));
64template <
typename Impl,
typename Op,
typename... HandledAttrs>
65class SymbolUserHelper :
public OpConversionPattern<Op> {
67 const DenseMap<Attribute, Attribute> ¶mNameToValue;
70 TypeConverter &converter, MLIRContext *ctx,
unsigned patternBenefit,
71 const DenseMap<Attribute, Attribute> ¶mNameToInstantiatedValue
73 : OpConversionPattern<Op>(converter, ctx, patternBenefit),
74 paramNameToValue(paramNameToInstantiatedValue) {}
77 using OpAdaptor =
typename mlir::OpConversionPattern<Op>::OpAdaptor;
79 virtual Attribute getNameAttr(Op)
const = 0;
81 virtual LogicalResult handleDefaultRewrite(
82 Attribute, Op op, OpAdaptor, ConversionPatternRewriter &, Attribute a
84 return op->emitOpError().append(
"expected value with type ", op.getType(),
" but found ", a);
88 matchAndRewrite(Op op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter)
const override {
89 LLVM_DEBUG(llvm::dbgs() <<
"[SymbolUserHelper] op: " << op <<
'\n');
90 auto res = this->paramNameToValue.find(getNameAttr(op));
91 if (res == this->paramNameToValue.end()) {
92 LLVM_DEBUG(llvm::dbgs() <<
"[SymbolUserHelper] no instantiation for " << op <<
'\n');
95 llvm::TypeSwitch<Attribute, LogicalResult> TS(res->second);
96 llvm::TypeSwitch<Attribute, LogicalResult> *ptr = &TS;
98 ((ptr = &(ptr->template Case<HandledAttrs>([&](HandledAttrs a) {
99 return static_cast<const Impl *
>(
this)->handleRewrite(res->first, op, adaptor, rewriter, a);
103 return TS.Default([&](Attribute a) {
104 return handleDefaultRewrite(res->first, op, adaptor, rewriter, a);
110class ClonedBodyConstReadOpPattern
111 :
public SymbolUserHelper<
112 ClonedBodyConstReadOpPattern, ConstReadOp, IntegerAttr, FeltConstAttr> {
113 SmallVector<Diagnostic> &diagnostics;
116 SymbolUserHelper<ClonedBodyConstReadOpPattern, ConstReadOp, IntegerAttr, FeltConstAttr>;
119 ClonedBodyConstReadOpPattern(
120 TypeConverter &converter, MLIRContext *ctx,
121 const DenseMap<Attribute, Attribute> ¶mNameToInstantiatedValue,
122 SmallVector<Diagnostic> &instantiationDiagnostics
125 : super(converter, ctx, 1, paramNameToInstantiatedValue),
126 diagnostics(instantiationDiagnostics) {}
128 Attribute getNameAttr(ConstReadOp op)
const override {
return op.
getConstNameAttr(); }
130 LogicalResult handleRewrite(
131 Attribute sym, ConstReadOp op, OpAdaptor, ConversionPatternRewriter &rewriter, IntegerAttr a
133 const APInt &attrValue = a.getValue();
134 Type origResTy = op.getType();
135 Type newResTy = getTypeConverter()->convertType(origResTy);
137 return op->emitOpError().append(
"could not convert result type ", origResTy);
140 if (FeltType ty = llvm::dyn_cast<FeltType>(newResTy)) {
147 if (llvm::isa<IndexType>(newResTy)) {
152 if (newResTy.isSignlessInteger(1)) {
154 if (attrValue.isZero()) {
158 if (!attrValue.isOne()) {
159 Location opLoc = op.getLoc();
160 Diagnostic diag(opLoc, DiagnosticSeverity::Warning);
162 if (getContext()->shouldPrintOpOnDiagnostic()) {
163 diag.attachNote(opLoc) <<
"see current operation: " << *op;
165 diag.attachNote(UnknownLoc::get(getContext()))
167 <<
"\" for this specialization";
168 diagnostics.push_back(std::move(diag));
173 return op->emitOpError().append(
"unexpected result type ", newResTy);
176 LogicalResult handleRewrite(
177 Attribute, ConstReadOp op, OpAdaptor, ConversionPatternRewriter &rewriter, FeltConstAttr a
184static inline bool tableOffsetIsntSymbol(
MemberReadOp op) {
185 return !llvm::isa_and_present<SymbolRefAttr>(op.
getTableOffset().value_or(
nullptr));
190class ClonedMemberReadOpPattern
191 :
public SymbolUserHelper<ClonedMemberReadOpPattern, MemberReadOp, IntegerAttr> {
192 using super = SymbolUserHelper<ClonedMemberReadOpPattern, MemberReadOp, IntegerAttr>;
195 ClonedMemberReadOpPattern(
196 TypeConverter &converter, MLIRContext *ctx,
197 const DenseMap<Attribute, Attribute> ¶mNameToInstantiatedValue
200 : super(converter, ctx, 1, paramNameToInstantiatedValue) {}
202 Attribute getNameAttr(MemberReadOp op)
const override {
206 LogicalResult handleRewrite(
207 Attribute, MemberReadOp op, OpAdaptor, ConversionPatternRewriter &rewriter, IntegerAttr a
209 rewriter.modifyOpInPlace(op, [&]() {
216 LogicalResult handleDefaultRewrite(
217 Attribute, MemberReadOp op, OpAdaptor, ConversionPatternRewriter &, Attribute a
219 return op->emitOpError().append(
220 "table offset requires an integer template value, but found ", a
224 LogicalResult matchAndRewrite(
225 MemberReadOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter
227 LLVM_DEBUG(llvm::dbgs() <<
"[ClonedMemberReadOpPattern] MemberReadOp: " << op <<
'\n';);
228 if (tableOffsetIsntSymbol(op)) {
232 return super::matchAndRewrite(op, adaptor, rewriter);
236class MappedTypeConverter :
public TypeConverter {
239 const DenseMap<Attribute, Attribute> ¶mNameToValue;
241 inline Attribute convertIfPossible(Attribute a)
const {
242 auto res = this->paramNameToValue.find(a);
243 return (res != this->paramNameToValue.end()) ? res->second : a;
248 StructType originalType, StructType newType,
250 const DenseMap<Attribute, Attribute> ¶mNameToInstantiatedValue
252 : TypeConverter(), origTy(originalType), newTy(newType),
253 paramNameToValue(paramNameToInstantiatedValue) {
255 addConversion([](Type inputTy) {
return inputTy; });
257 addConversion([
this](pod::PodType type) {
return convertPodType(type, *
this); });
259 addConversion([
this](StructType inputTy) {
260 LLVM_DEBUG(llvm::dbgs() <<
"[MappedTypeConverter] convert " << inputTy <<
'\n');
263 if (inputTy == this->origTy) {
267 if (ArrayAttr inputTyParams = inputTy.
getParams()) {
268 SmallVector<Attribute> updated;
269 for (Attribute a : inputTyParams) {
270 if (TypeAttr ta = dyn_cast<TypeAttr>(a)) {
271 updated.push_back(TypeAttr::get(this->convertType(ta.getValue())));
273 updated.push_back(convertIfPossible(a));
282 addConversion([
this](ArrayType inputTy) {
285 if (!dimSizes.empty()) {
286 SmallVector<Attribute> updated;
287 for (Attribute a : dimSizes) {
288 updated.push_back(convertIfPossible(a));
300 addConversion([
this](TypeVarType inputTy) -> Type {
302 if (TypeAttr tyAttr = llvm::dyn_cast<TypeAttr>(convertIfPossible(inputTy.
getNameRef()))) {
303 Type convertedType = tyAttr.getValue();
308 return convertedType;
318class ClonedBodyCreateArrayOpPattern final :
public OpConversionPattern<CreateArrayOp> {
320 using OpConversionPattern<CreateArrayOp>::OpConversionPattern;
322 LogicalResult matchAndRewrite(
323 CreateArrayOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter
328 auto newElemTy = dyn_cast_if_present<ArrayType>(
329 getTypeConverter()->convertType(op.getType().getElementType())
332 dyn_cast_if_present<ArrayType>(getTypeConverter()->convertType(op.getType()));
333 if (!newElemTy || !newResultTy) {
336 if (!op.getType().hasStaticShape()) {
337 return rewriter.notifyMatchFailure(op,
"initialized array requires a static outer shape");
339 for (Value element : adaptor.getElements()) {
340 if (element.getType() != newElemTy) {
341 return rewriter.notifyMatchFailure(op,
"converted initializer has unexpected type");
345 Location loc = op.getLoc();
349 for (
auto [index, element] : llvm::enumerate(adaptor.getElements())) {
351 assert(indices &&
"static array initializer index should delinearize");
354 rewriter.replaceOp(op, allocation.getResult());
361class ClonedBodyArrayReadOpPattern final :
public OpConversionPattern<ReadArrayOp> {
363 using OpConversionPattern<ReadArrayOp>::OpConversionPattern;
365 LogicalResult matchAndRewrite(
366 ReadArrayOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter
368 Type newResultTy = getTypeConverter()->convertType(op.
getResult().getType());
369 if (!llvm::isa<ArrayType>(newResultTy)) {
373 rewriter, op, newResultTy, adaptor.getArrRef(), adaptor.getIndices()
381class ClonedBodyArrayWriteOpPattern final :
public OpConversionPattern<WriteArrayOp> {
383 using OpConversionPattern<WriteArrayOp>::OpConversionPattern;
385 LogicalResult matchAndRewrite(
386 WriteArrayOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter
388 if (!llvm::isa<ArrayType>(adaptor.getRvalue().getType())) {
392 rewriter, op, adaptor.getArrRef(), adaptor.getIndices(), adaptor.getRvalue()
399convertCalleeSymRefs(SymbolRefAttr callee,
const DenseMap<Attribute, Attribute> ¶mNameToValue) {
400 auto it = paramNameToValue.find(FlatSymbolRefAttr::get(callee.getRootReference()));
401 if (it == paramNameToValue.end()) {
405 auto tyAttr = llvm::dyn_cast<TypeAttr>(it->second);
410 auto structTy = llvm::dyn_cast<StructType>(tyAttr.getValue());
415 SmallVector<FlatSymbolRefAttr> newPieces =
getPieces(structTy.getNameRef());
416 llvm::append_range(newPieces, callee.getNestedReferences());
424static std::optional<Attribute>
425evaluateExpr(
TemplateExprOp exprOp,
const DenseMap<Attribute, Attribute> ¶mNameToConcrete) {
427 DenseMap<Value, Attribute> valueMap;
429 if (
auto yieldOp = llvm::dyn_cast<YieldOp>(bodyOp)) {
430 auto it = valueMap.find(yieldOp.getVal());
431 return it != valueMap.end() ? std::make_optional(it->second) : std::nullopt;
434 if (
auto constReadOp = llvm::dyn_cast<ConstReadOp>(bodyOp)) {
435 auto it = paramNameToConcrete.find(constReadOp.getConstNameAttr());
436 if (it == paramNameToConcrete.end()) {
441 Attribute val = it->second;
442 if (
auto intAttr = llvm::dyn_cast<IntegerAttr>(val)) {
443 if (
auto feltTy = llvm::dyn_cast<FeltType>(constReadOp.getResult().getType())) {
447 valueMap[constReadOp.getResult()] = val;
452 SmallVector<Attribute> operandAttrs;
453 operandAttrs.reserve(bodyOp.getNumOperands());
454 for (Value operand : bodyOp.getOperands()) {
455 auto it = valueMap.find(operand);
456 if (it == valueMap.end()) {
459 operandAttrs.push_back(it->second);
463 SmallVector<OpFoldResult> foldResults;
464 if (succeeded(bodyOp.fold(operandAttrs, foldResults)) &&
465 foldResults.size() == bodyOp.getNumResults()) {
466 for (
auto [result, fr] : llvm::zip_equal(bodyOp.getResults(), foldResults)) {
467 if (Attribute a = llvm::dyn_cast<Attribute>(fr)) {
468 valueMap[result] = a;
483 DiagnosticEngine &engine = site->getContext()->getDiagEngine();
484 for (Diagnostic &diagnostic : diagnostics) {
485 for (Diagnostic ¬e : diagnostic.getNotes()) {
486 assert(note.getNotes().empty() &&
"notes cannot have notes attached");
487 if (isa<UnknownLoc>(note.getLocation())) {
488 note = std::move(Diagnostic(site->getLoc(), note.getSeverity()).append(note.str()));
491 engine.emit(std::move(diagnostic));
496 SymbolTableCollection &tables, ArrayAttr templateParams, Operation *lookupFrom,
497 ModuleOp destinationRoot, Operation *requestSite
499 if (!templateParams) {
500 return ArrayAttr::get(requestSite->getContext(), {});
502 AttrTypeReplacer rebaser;
503 rebaser.addReplacement(
504 [&tables, lookupFrom, destinationRoot,
505 requestSite](
StructType type) -> std::optional<std::pair<Type, WalkResult>> {
508 return std::make_pair(Type(type), WalkResult::interrupt());
510 if (found->viaInclude()) {
511 requestSite->emitError(
"inline includes before rebasing template parameters");
512 return std::make_pair(Type(type), WalkResult::interrupt());
515 return requestSite->emitError(
"struct type argument ") << type;
518 return std::make_pair(Type(type), WalkResult::interrupt());
522 if (failed(nested)) {
523 return std::make_pair(Type(type), WalkResult::interrupt());
526 return std::make_pair(Type(rebased), WalkResult::skip());
529 auto result = dyn_cast_if_present<ArrayAttr>(rebaser.replace(templateParams));
536Attribute TemplateTypeConverter::convertIfPossible(Attribute attr)
const {
537 auto it = paramNameToValue.find(attr);
538 return it == paramNameToValue.end() ? attr : it->second;
542 : paramNameToValue(std::move(bindings)) {
543 addConversion([](Type t) {
return t; });
545 addConversion([
this](
pod::PodType type) {
return convertPodType(type, *
this); });
547 addConversion([
this](
TypeVarType inputTy) -> Type {
548 if (TypeAttr tyAttr = llvm::dyn_cast<TypeAttr>(convertIfPossible(inputTy.
getNameRef()))) {
549 Type convertedType = tyAttr.getValue();
551 return convertedType;
557 addConversion([
this](
ArrayType inputTy) {
558 SmallVector<Attribute> updated;
559 bool changed =
false;
560 for (Attribute a : inputTy.getDimensionSizes()) {
561 Attribute converted = convertIfPossible(a);
562 updated.push_back(converted);
563 if (converted != a) {
567 Type newElemTy = this->convertType(inputTy.getElementType());
568 if (!changed && newElemTy == inputTy.getElementType()) {
575 if (ArrayAttr params = inputTy.getParams()) {
576 SmallVector<Attribute> updated;
577 bool changed =
false;
578 for (Attribute a : params) {
579 if (TypeAttr ta = dyn_cast<TypeAttr>(a)) {
580 Type newTy = this->convertType(ta.getValue());
581 if (newTy != ta.getValue()) {
582 updated.push_back(TypeAttr::get(newTy));
587 Attribute converted = convertIfPossible(a);
588 if (converted != a) {
589 updated.push_back(converted);
594 updated.push_back(a);
605 if (TypeAttr tyAttr = llvm::dyn_cast<TypeAttr>(attr)) {
606 Type convertedTy = convertType(tyAttr.getValue());
607 if (convertedTy != tyAttr.getValue()) {
608 return TypeAttr::get(convertedTy);
611 return convertIfPossible(attr);
615 op->walk([¶mNameToValue](
CallOp callOp) {
624 TemplateOp templateOp, DenseMap<Attribute, Attribute> ¶mNameToConcrete
627 llvm::dbgs() <<
"[evaluateTemplateExprs] before: " <<
debug::toStringList(paramNameToConcrete)
631 std::optional<Attribute> result = evaluateExpr(exprOp, paramNameToConcrete);
632 if (result.has_value()) {
633 auto exprNameAttr = FlatSymbolRefAttr::get(exprOp.
getSymNameAttr());
634 paramNameToConcrete.try_emplace(exprNameAttr, *result);
636 llvm::dbgs() <<
"[evaluateTemplateExprs] expr @" << exprOp.
getSymName()
637 <<
" evaluated to " << *result <<
'\n'
642 llvm::dbgs() <<
"[evaluateTemplateExprs] after: " <<
debug::toStringList(paramNameToConcrete)
648std::optional<Attribute>
650 auto it = unifyResult.find({paramName,
Side::RHS});
651 return (it == unifyResult.end()) ? std::nullopt : std::make_optional(it->second);
656 const DenseMap<Attribute, Attribute> ¶mNameToConcrete, SmallVector<Diagnostic> &diagnostics
658 MLIRContext *ctx = newStruct.getContext();
659 MappedTypeConverter tyConv(typeAtDef, newStruct.
getType(), paramNameToConcrete);
660 ConversionTarget target =
664 return !paramNameToConcrete.contains(op.getConstNameAttr());
668 patterns.add<ClonedBodyConstReadOpPattern>(tyConv, ctx, paramNameToConcrete, diagnostics);
669 patterns.add<ClonedBodyCreateArrayOpPattern>(tyConv, ctx);
670 patterns.add<ClonedBodyArrayReadOpPattern, ClonedBodyArrayWriteOpPattern>(tyConv, ctx);
671 patterns.add<ClonedMemberReadOpPattern>(tyConv, ctx, paramNameToConcrete);
672 return applyFullConversion(newStruct, target, std::move(patterns));
676 FuncDefOp newFunc,
const DenseMap<Attribute, Attribute> ¶mNameToConcrete,
677 SmallVector<Diagnostic> &delayedDiagnostics
679 MLIRContext *ctx = newFunc.getContext();
687 bodyPatterns.add<ClonedBodyConstReadOpPattern>(
688 tyConv, ctx, tyConv.
getParamMap(), delayedDiagnostics
690 bodyPatterns.add<ClonedBodyArrayReadOpPattern, ClonedBodyArrayWriteOpPattern>(tyConv, ctx);
691 bodyPatterns.add<ClonedBodyCreateArrayOpPattern>(tyConv, ctx);
692 bodyPatterns.add<ClonedMemberReadOpPattern>(tyConv, ctx, paramNameToConcrete);
693 return applyFullConversion(newFunc, target, std::move(bodyPatterns));
Common private implementation for poly dialect passes.
Private parameter substitution helpers shared by polymorphic transformations.
static ArrayIndexGen from(ArrayType)
Construct new ArrayIndexGen. Will assert if hasStaticShape() is false.
std::optional< llvm::SmallVector< mlir::Value > > delinearize(int64_t, mlir::Location, mlir::OpBuilder &) const
ArrayType cloneWith(std::optional<::llvm::ArrayRef< int64_t > > shape, ::mlir::Type elementType) const
Clone this type with the given shape and element type.
::mlir::Type getElementType() const
::llvm::ArrayRef<::mlir::Attribute > getDimensionSizes() const
static CreateArrayOp create(::mlir::OpBuilder &builder, ::mlir::Location location, ::llzk::array::ArrayType result, ::mlir::ValueRange elements={})
::mlir::Operation::operand_range getElements()
static InsertArrayOp create(::mlir::OpBuilder &builder, ::mlir::Location location, ::mlir::Value arr_ref, ::mlir::ValueRange indices, ::mlir::Value rvalue)
::mlir::TypedValue<::mlir::Type > getResult()
::std::optional<::mlir::Attribute > getTableOffset()
void setTableOffsetAttr(::mlir::Attribute attr)
StructType getType(::std::optional<::mlir::ArrayAttr > constParams={})
Gets the StructType representing this struct.
static constexpr ::llvm::StringLiteral getOperationName()
::mlir::SymbolRefAttr getNameRef() const
::mlir::FailureOr< SymbolLookupResult< StructDefOp > > getDefinition(::mlir::SymbolTableCollection &symbolTable, ::mlir::Operation *op, bool reportMissing=true) const
Gets the struct op that defines this struct.
::mlir::ArrayAttr getParams() const
::mlir::SymbolRefAttr getCalleeAttr()
void setCalleeAttr(::mlir::SymbolRefAttr attr)
static PodType get(::mlir::MLIRContext *context, ::llvm::ArrayRef<::llzk::pod::RecordAttr > records)
::llvm::ArrayRef<::llzk::pod::RecordAttr > getRecords() const
::mlir::FlatSymbolRefAttr getConstNameAttr()
::mlir::StringAttr getSymNameAttr()
::mlir::Region & getInitializerRegion()
::llvm::StringRef getSymName()
inline ::llvm::iterator_range<::mlir::Region::op_iterator< OpT > > getConstOps()
Return ops of type OpT within the body region.
::mlir::FlatSymbolRefAttr getNameRef() const
Substitute known template bindings in function types and inference candidates.
const llvm::DenseMap< mlir::Attribute, mlir::Attribute > & getParamMap() const
Return the bindings used by body substitution patterns.
bool containsParam(mlir::Attribute name) const
Return whether the parameter has a supplied binding.
mlir::Attribute convertAttr(mlir::Attribute attr) const
Substitute a bound attribute or the type contained in a TypeAttr.
TemplateTypeConverter(llvm::DenseMap< mlir::Attribute, mlir::Attribute > bindings)
std::string toStringList(InputIt begin, InputIt end)
Generate a comma-separated string representation by traversing elements from begin to end where the e...
Common interface for constant parameter-like symbol operations that can be defined within a TemplateO...
component::StructType getStructTypeWithParams(mlir::SymbolRefAttr nameRef, mlir::ArrayAttr params)
Build a struct type while representing an empty parameter list as absent.
FailureOr< ArrayAttr > rebaseTemplateParams(SymbolTableCollection &tables, ArrayAttr templateParams, Operation *lookupFrom, ModuleOp destinationRoot, Operation *requestSite)
mlir::ConversionTarget newConverterDefinedTarget(mlir::TypeConverter &tyConv, mlir::MLIRContext *ctx, AdditionalChecks &&...checks)
Return a new ConversionTarget allowing all LLZK-required dialects and defining Op legality based on t...
std::optional< Attribute > inferUnifiedParam(const UnificationMap &unifyResult, SymbolRefAttr paramName)
Return the callee-side unification-derived value for a template parameter, if any.
LogicalResult substituteStructBody(StructDefOp newStruct, StructType typeAtDef, const DenseMap< Attribute, Attribute > ¶mNameToConcrete, SmallVector< Diagnostic > &diagnostics)
LogicalResult substituteFunctionBody(FuncDefOp newFunc, const DenseMap< Attribute, Attribute > ¶mNameToConcrete, SmallVector< Diagnostic > &delayedDiagnostics)
void evaluateTemplateExprs(TemplateOp templateOp, DenseMap< Attribute, Attribute > ¶mNameToConcrete)
Evaluate all TemplateExprOps in templateOp that can be computed from the currently-known concrete par...
void convertCalleesInPlace(Operation *op, const DenseMap< Attribute, Attribute > ¶mNameToValue)
void reportDelayedDiagnostics(Operation *site, SmallVector< Diagnostic > &&diagnostics)
OpClass replaceOpWithNewOp(Rewriter &rewriter, mlir::Operation *op, Args &&...args)
Wrapper for RewriterBase::replaceOpWithNewOp() that automatically copies discardable attributes (i....
bool isConcreteType(Type type, bool allowStructParams)
mlir::DenseMap< std::pair< mlir::SymbolRefAttr, Side >, mlir::Attribute > UnificationMap
Optional result from type unifications.
std::string stringWithoutType(mlir::Attribute a)
constexpr T checkedCast(U u) noexcept
OpTy preserveDiscardableAttrs(mlir::Operation *src, OpTy dst)
Copy discardable attributes from src to dst.
ArrayType flattenArrayElementType(ArrayType outerArrTy, Type elementType)
mlir::RewritePatternSet newGeneralRewritePatternSet(mlir::TypeConverter &tyConv, mlir::MLIRContext *ctx, mlir::ConversionTarget &target)
Return a new RewritePatternSet covering all LLZK op types that may contain a StructType.
mlir::SymbolRefAttr asSymbolRefAttr(mlir::StringAttr root, mlir::SymbolRefAttr tail)
Build a SymbolRefAttr that prepends tail with root, i.e., root::tail.
int64_t fromAPInt(const llvm::APInt &i)
Extract a verified MLIR index value; malformed internal IR is a fatal error.
FailureOr< SymbolRefAttr > getPathRelativeToAncestor(SymbolOpInterface symbol, ModuleOp ancestor, llvm::function_ref< InFlightDiagnostic()> emitError)
llvm::SmallVector< FlatSymbolRefAttr > getPieces(SymbolRefAttr ref)
llvm::DynamicAPInt integerAttrToDynamicAPInt(mlir::IntegerAttr attr)
Decode an MLIR integer using its signedness; signless i1 denotes a boolean.