29#include <mlir/AsmParser/AsmParser.h>
30#include <mlir/IR/BuiltinOps.h>
31#include <mlir/IR/BuiltinTypes.h>
32#include <mlir/IR/Operation.h>
34#include <llvm/ADT/TypeSwitch.h>
35#include <llvm/Support/Debug.h>
39#define DEBUG_TYPE "llzk-symbol-helpers"
46using namespace component;
48using namespace function;
49using namespace global;
50using namespace polymorphic;
53 SmallVector<ModuleOp> emptyModules;
54 rootModule.walk<WalkOrder::PostOrder>([&](ModuleOp module) {
55 if (module == rootModule) {
58 Region ®ion =
module.getBodyRegion();
59 if (region.empty() || region.front().empty()) {
60 emptyModules.push_back(module);
64 for (ModuleOp module : emptyModules) {
65 LLVM_DEBUG(llvm::dbgs() <<
"Removing empty module " << module.getName() <<
'\n');
76constexpr char POSITION_IS_ROOT_INDICATOR[] =
"<<symbol lookup root>>";
77constexpr char UNNAMED_SYMBOL_INDICATOR[] =
"<<unnamed symbol>>";
79enum RootSelector : std::uint8_t { CLOSEST, FURTHEST };
81class RootPathBuilder {
82 RootSelector _whichRoot;
87 RootPathBuilder(RootSelector whichRoot, Operation *origin, ModuleOp *foundRoot)
88 : _whichRoot(whichRoot), _origin(origin), _foundRoot(foundRoot) {}
96 FailureOr<ModuleOp> collectPathToRoot(Operation *
from, std::vector<FlatSymbolRefAttr> &path) {
98 ModuleOp currRoot =
nullptr;
100 if (ModuleOp m = llvm::dyn_cast_if_present<ModuleOp>(
check)) {
104 if (_whichRoot == RootSelector::CLOSEST) {
109 if (StringAttr modName = m.getSymNameAttr()) {
110 path.push_back(FlatSymbolRefAttr::get(modName));
111 }
else if (!currRoot) {
112 return _origin->emitOpError()
114 "has ancestor '", ModuleOp::getOperationName(),
"' without \"",
LANG_ATTR_NAME,
115 "\" attribute or a name"
117 .attachNote(m.getLoc())
118 .append(
"unnamed '", ModuleOp::getOperationName(),
"' here");
120 }
else if (TemplateOp t = llvm::dyn_cast_if_present<TemplateOp>(
check)) {
121 StringAttr name = t.getSymNameAttr();
122 assert(name &&
"per ODS");
123 path.push_back(FlatSymbolRefAttr::get(name));
127 if (_whichRoot == RootSelector::FURTHEST && currRoot) {
131 return _origin->emitOpError().append(
132 "has no ancestor '", ModuleOp::getOperationName(),
"' with \"",
LANG_ATTR_NAME,
139 FailureOr<SymbolRefAttr>
140 buildPathFromRootToAnyOp(Operation *position, std::vector<FlatSymbolRefAttr> &&path) {
142 FailureOr<ModuleOp> rootMod = collectPathToRoot(position, path);
143 if (failed(rootMod)) {
147 *_foundRoot = rootMod.value();
153 assert(position == rootMod.value().getOperation() &&
"empty path only at root itself");
157 std::vector<FlatSymbolRefAttr> reversedVec(path.rbegin(), path.rend());
162 FailureOr<SymbolRefAttr> getPathFromRootToAnyOp(Operation *op) {
163 std::vector<FlatSymbolRefAttr> path;
164 return buildPathFromRootToAnyOp(op, std::move(path));
169 FailureOr<SymbolRefAttr>
170 buildPathFromRootToStruct(StructDefOp to, std::vector<FlatSymbolRefAttr> &&path) {
172 path.push_back(FlatSymbolRefAttr::get(to.getSymNameAttr()));
173 return buildPathFromRootToAnyOp(to, std::move(path));
176 FailureOr<SymbolRefAttr> getPathFromRootToStruct(StructDefOp to) {
177 std::vector<FlatSymbolRefAttr> path;
178 return buildPathFromRootToStruct(to, std::move(path));
181 FailureOr<SymbolRefAttr> getPathFromRootToMember(MemberDefOp to) {
182 std::vector<FlatSymbolRefAttr> path;
184 path.push_back(FlatSymbolRefAttr::get(to.getSymNameAttr()));
186 return buildPathFromRootToStruct(to.getParentOp<StructDefOp>(), std::move(path));
189 FailureOr<SymbolRefAttr> getPathFromRootToFunc(FuncDefOp to) {
190 std::vector<FlatSymbolRefAttr> path;
192 path.push_back(FlatSymbolRefAttr::get(to.getSymNameAttr()));
195 Operation *current = to.getOperation();
196 Operation *parent = current->getParentOp();
197 if (StructDefOp parentStruct = llvm::dyn_cast_if_present<StructDefOp>(parent)) {
198 return buildPathFromRootToStruct(parentStruct, std::move(path));
199 }
else if (ModuleOp parentMod = llvm::dyn_cast_if_present<ModuleOp>(parent)) {
200 return buildPathFromRootToAnyOp(parentMod, std::move(path));
201 }
else if (TemplateOp parentTemplate = llvm::dyn_cast_if_present<TemplateOp>(parent)) {
202 return buildPathFromRootToAnyOp(parentTemplate, std::move(path));
210 FailureOr<SymbolRefAttr> getPathFromRootToAnySymbol(SymbolOpInterface to) {
212 return TypeSwitch<Operation *, FailureOr<SymbolRefAttr>>(to.getOperation())
214 .Case<FuncDefOp>([
this](
auto toOp) {
return getPathFromRootToFunc(toOp); })
215 .Case<MemberDefOp>([
this](
auto toOp) {
return getPathFromRootToMember(toOp); })
216 .Case<StructDefOp>([
this](
auto toOp) {
return getPathFromRootToStruct(toOp); })
217 .Case<TemplateOp>([
this](
auto toOp) {
return getPathFromRootToAnyOp(toOp); })
218 .Case<ModuleOp>([
this](
auto toOp) {
return getPathFromRootToAnyOp(toOp); })
222 .Default([
this, &to](
auto) {
223 std::vector<FlatSymbolRefAttr> path;
225 path.push_back(FlatSymbolRefAttr::get(name));
228 assert(to.isOptionalSymbol());
229 path.push_back(FlatSymbolRefAttr::get(to.getContext(), UNNAMED_SYMBOL_INDICATOR));
231 return buildPathFromRootToAnyOp(to, std::move(path));
237LogicalResult verifyTemplateSymbolType(
239 Operation *origin, std::optional<Type> requiredParamType
241 if (requiredParamType) {
242 std::optional<Type> actualType = binding.getTypeOpt();
244 return origin->emitError().append(
245 "ref \"", param,
"\" in type ", parameterizedType,
" refers to a '", binding->getName(),
246 "' that must have type ", *requiredParamType
249 if (*actualType != *requiredParamType) {
250 return origin->emitError().append(
251 "ref \"", param,
"\" in type ", parameterizedType,
" refers to a '", binding->getName(),
252 "' with type ", *actualType,
" but expected ", *requiredParamType
261llvm::SmallVector<StringRef>
getNames(SymbolRefAttr ref) {
262 llvm::SmallVector<StringRef>
names;
263 names.push_back(ref.getRootReference().getValue());
264 for (
const FlatSymbolRefAttr &r : ref.getNestedReferences()) {
265 names.push_back(r.getValue());
270llvm::SmallVector<FlatSymbolRefAttr>
getPieces(SymbolRefAttr ref) {
271 llvm::SmallVector<FlatSymbolRefAttr> pieces;
272 pieces.push_back(FlatSymbolRefAttr::get(ref.getRootReference()));
273 for (
const FlatSymbolRefAttr &r : ref.getNestedReferences()) {
281SymbolRefAttr changeLeafImpl(
282 StringAttr origRoot, ArrayRef<FlatSymbolRefAttr> origTail, FlatSymbolRefAttr newLeaf,
285 llvm::SmallVector<FlatSymbolRefAttr> newTail;
286 newTail.append(origTail.begin(), origTail.drop_back(drop).end());
287 newTail.push_back(newLeaf);
288 return SymbolRefAttr::get(origRoot, newTail);
293SymbolRefAttr
replaceLeaf(SymbolRefAttr orig, FlatSymbolRefAttr newLeaf) {
294 ArrayRef<FlatSymbolRefAttr> origTail = orig.getNestedReferences();
295 if (origTail.empty()) {
299 return changeLeafImpl(orig.getRootReference(), origTail, newLeaf);
303SymbolRefAttr
appendLeaf(SymbolRefAttr orig, FlatSymbolRefAttr newLeaf) {
304 return changeLeafImpl(orig.getRootReference(), orig.getNestedReferences(), newLeaf, 0);
308 ArrayRef<FlatSymbolRefAttr> origTail = orig.getNestedReferences();
309 if (origTail.empty()) {
312 orig.getContext(), orig.getRootReference().getValue() + newLeafSuffix
315 return changeLeafImpl(
316 orig.getRootReference(), origTail,
323 SymbolOpInterface symbol, ModuleOp ancestor, llvm::function_ref<InFlightDiagnostic()> emitError
325 Operation *
definition = symbol.getOperation();
328 auto diagnostic = emitError();
330 diagnostic <<
" cannot be named relative to itself; a strict descendant is required";
331 diagnostic.attachNote(ancestor.getLoc())
332 <<
"symbol and supplied module are the same operation";
334 diagnostic <<
" is not visible from module \""
335 << ancestor.getSymName().value_or(
"<unnamed>") <<
'"';
337 <<
"symbol is defined outside the supplied module";
338 diagnostic.attachNote(ancestor.getLoc()) <<
"symbol path must start from this module";
343 SmallVector<FlatSymbolRefAttr> path;
344 for (Operation *current =
definition; current != ancestor; current = current->getParentOp()) {
345 if (current !=
definition && !current->hasTrait<OpTrait::SymbolTable>()) {
351 auto diagnostic = emitError();
352 diagnostic <<
" cannot be named relative to module \""
353 << ancestor.getSymName().value_or(
"<unnamed>")
354 <<
"\" because an intervening symbol table is unnamed";
355 diagnostic.attachNote(current->getLoc())
356 <<
"unnamed symbol table prevents forming a symbol path";
357 diagnostic.attachNote(ancestor.getLoc()) <<
"symbol path must start from this module";
361 path.push_back(FlatSymbolRefAttr::get(name));
363 std::reverse(path.begin(), path.end());
368 std::vector<FlatSymbolRefAttr> path;
369 return RootPathBuilder(RootSelector::CLOSEST,
from,
nullptr).collectPathToRoot(
from, path);
373 return RootPathBuilder(RootSelector::CLOSEST, to, foundRoot).getPathFromRootToAnySymbol(to);
377 return RootPathBuilder(RootSelector::CLOSEST, to, foundRoot).getPathFromRootToAnyOp(to);
381 return RootPathBuilder(RootSelector::CLOSEST, to, foundRoot).getPathFromRootToStruct(to);
385 return RootPathBuilder(RootSelector::CLOSEST, to, foundRoot).getPathFromRootToMember(to);
389 return RootPathBuilder(RootSelector::CLOSEST, to, foundRoot).getPathFromRootToFunc(to);
393 std::vector<FlatSymbolRefAttr> path;
394 return RootPathBuilder(RootSelector::FURTHEST,
from,
nullptr).collectPathToRoot(
from, path);
398 return RootPathBuilder(RootSelector::FURTHEST, to, foundRoot).getPathFromRootToAnySymbol(to);
402 return RootPathBuilder(RootSelector::FURTHEST, to, foundRoot).getPathFromRootToAnyOp(to);
406 return RootPathBuilder(RootSelector::FURTHEST, to, foundRoot).getPathFromRootToStruct(to);
410 return RootPathBuilder(RootSelector::FURTHEST, to, foundRoot).getPathFromRootToMember(to);
414 return RootPathBuilder(RootSelector::FURTHEST, to, foundRoot).getPathFromRootToFunc(to);
419 if (failed(rootOpt)) {
422 ModuleOp root = rootOpt.value();
427 return success(
nullptr);
430FailureOr<SymbolLookupResult<StructDefOp>>
433 if (failed(mainStructTypeOpt)) {
436 if (
StructType st = mainStructTypeOpt.value()) {
437 return st.getDefinition(symbolTable, lookupFrom);
439 return success(
nullptr);
443FailureOr<SymbolLookupResult<StructDefOp>>
444getRootStructDef(SymbolTableCollection &tables, Operation *lookupFrom, StringRef symbolPath) {
445 symbolPath = symbolPath.trim();
446 if (symbolPath.empty()) {
449 std::string symbolText = symbolPath.str();
450 if (symbolText.front() !=
'@') {
451 symbolText.insert(symbolText.begin(),
'@');
453 SymbolRefAttr symbol;
454 std::string parseError;
457 ScopedDiagnosticHandler handler(lookupFrom->getContext(), [&](Diagnostic &diagnostic) {
458 if (diagnostic.getSeverity() == DiagnosticSeverity::Error) {
459 parseError = diagnostic.str();
463 symbol = dyn_cast_or_null<SymbolRefAttr>(parseAttribute(symbolText, lookupFrom->getContext()));
466 auto diagnostic = lookupFrom->emitError();
467 diagnostic <<
"invalid root struct symbol path '" << symbolPath <<
'\'';
468 if (!parseError.empty()) {
469 diagnostic <<
": " << parseError;
475 return lookupFrom->emitError()
476 <<
"root struct symbol path '" << symbolPath <<
"' does not resolve to a symbol";
481 return lookupFrom->emitError()
482 <<
"root struct symbol path '" << symbolPath <<
"' references a '"
483 <<
definition->getName() <<
"'; expected a 'struct.def'";
490 FailureOr<SymbolLookupResultUntyped> targetRes =
492 if (failed(targetRes)) {
497 return targetTemplate;
506 if (symbol.getNestedReferences().empty()) {
508 if (failed(parent)) {
518 if (failed(lookupRes)) {
521 auto global = llvm::dyn_cast<GlobalDefOp>(lookupRes->get());
523 return origin->emitOpError() <<
"template argument '" << symbol <<
"' refers to a '"
524 << lookupRes->get()->getName() <<
"' which is not allowed";
526 if (!
global.isConstant()) {
527 return origin->emitOpError() <<
"template argument '" << symbol
528 <<
"' refers to a global that is not marked as 'const'";
536 std::optional<Type> declaredType = targetParam.
getTypeOpt();
538 if (
auto intAttr = llvm::dyn_cast<IntegerAttr>(value); intAttr &&
isDynamic(intAttr)) {
539 if (!declaredType || !llvm::isa<TypeVarType>(*declaredType)) {
540 auto diag = origin->emitOpError().append(
541 "wildcard `?` can only be used for template parameters with `!poly.tvar` "
542 "type restriction, but parameter \"@",
543 targetParam.getName(),
"\" has "
546 diag.append(
"type restriction ", *declaredType);
548 diag.append(
"no type restriction");
555 if (
auto symbol = llvm::dyn_cast<SymbolRefAttr>(value)) {
556 SymbolTableCollection tables;
563 bool resolvedLocal =
false;
564 bool compatible =
false;
565 if (symbol.getNestedReferences().empty()) {
567 if (failed(parentTemplate)) {
570 if (*parentTemplate) {
572 symbol.getRootReference()
575 resolvedLocal =
true;
576 compatible = !binding.getTypeOpt() ||
typesUnify(*binding.getTypeOpt(), *declaredType);
583 if (!resolvedLocal) {
585 if (failed(lookupRes)) {
588 auto global = llvm::cast<GlobalDefOp>(lookupRes->get());
589 assert(
global.isConstant() &&
"already verified by verifyTemplateParamSymbol");
593 return origin->emitOpError().append(
594 "instantiation value '", value,
"' is not compatible with parameter \"@",
595 targetParam.getName(),
"\" type restriction ", *declaredType
604 bool compatible =
false;
605 if (llvm::isa<TypeVarType>(*declaredType)) {
606 compatible = llvm::isa<TypeAttr>(value);
607 }
else if (llvm::isa<FeltType>(*declaredType)) {
608 compatible = llvm::isa<FeltConstAttr, IntegerAttr>(value) &&
610 }
else if (llvm::isa<IndexType, IntegerType>(*declaredType)) {
611 compatible = llvm::isa<IntegerAttr>(value) &&
614 llvm_unreachable(
"inconsistent with `isValidConstReadType()`");
617 return origin->emitOpError().append(
618 "instantiation value '", value,
"' is not compatible with parameter \"@",
619 targetParam.getName(),
"\" type restriction ", *declaredType
626 Operation *origin, ArrayAttr explicitParams,
627 llvm::iterator_range<Region::op_iterator<TemplateParamOp>> targetParamDefs
630 assert(explicitParams.size() == llvm::range_size(targetParamDefs) &&
"pre-condition");
631 for (
auto [targetParam, value] : llvm::zip_equal(targetParamDefs, explicitParams.getValue())) {
640 Operation *origin, ArrayAttr explicitParams,
641 llvm::iterator_range<Region::op_iterator<TemplateParamOp>> targetParamDefs,
645 assert((explicitParams.size() == llvm::range_size(targetParamDefs)) &&
"pre-condition");
647 for (
auto [paramOp, attr] : llvm::zip_equal(targetParamDefs, explicitParams.getValue())) {
649 if (
auto intAttr = llvm::dyn_cast<IntegerAttr>(attr)) {
654 auto it = unifications.find({FlatSymbolRefAttr::get(paramOp.getNameAttr()),
Side::RHS});
657 if (it != unifications.end() && it->second && !
typeParamsUnify({attr}, {it->second})) {
658 return origin->emitOpError().append(
659 "template instantiation value '", attr,
"' for parameter \"@", paramOp.getName(),
660 "\" conflicts with value '", it->second,
"' inferred from function type signature"
668 SymbolTableCollection &tables, SymbolRefAttr param, Type parameterizedType, Operation *origin,
669 std::optional<Type> requiredParamType
674 if (param.getNestedReferences().empty()) {
676 if (failed(parent)) {
683 return verifyTemplateSymbolType(b, param, parameterizedType, origin, requiredParamType);
689 if (failed(lookupRes)) {
692 auto global = llvm::dyn_cast<GlobalDefOp>(lookupRes->get());
694 return origin->emitError() <<
"ref \"" << param <<
"\" in type " << parameterizedType
695 <<
" refers to a '" << lookupRes->get()->getName()
696 <<
"' which is not allowed";
698 if (!
global.isConstant()) {
699 return origin->emitError() <<
"ref \"" << param <<
"\" in type " << parameterizedType
700 <<
" refers to a global that is not marked as 'const'";
706 SymbolTableCollection &tables, ArrayRef<Attribute> tyParams, Type parameterizedType,
707 Operation *origin, std::optional<Type> requiredParamType
711 LogicalResult paramCheckResult = success();
713 llvm::dbgs() <<
"[verifyParamOfType] parameterizedType = " << parameterizedType <<
'\n';
715 for (Attribute attr : tyParams) {
716 LLVM_DEBUG({ llvm::dbgs() <<
"[verifyParamOfType] checking attribute " << attr <<
'\n'; });
718 if (SymbolRefAttr symRefParam = llvm::dyn_cast<SymbolRefAttr>(attr)) {
719 auto r =
verifyParamOfType(tables, symRefParam, parameterizedType, origin, requiredParamType);
722 llvm::dbgs() <<
"[verifyParamOfType] failed to verify symbol attribute\n";
724 paramCheckResult = failure();
726 }
else if (TypeAttr typeParam = llvm::dyn_cast<TypeAttr>(attr)) {
729 llvm::dbgs() <<
"[verifyParamOfType] failed to verify type attribute\n";
731 paramCheckResult = failure();
734 LLVM_DEBUG({ llvm::dbgs() <<
"[verifyParamOfType] verified attribute\n"; });
737 return paramCheckResult;
740FailureOr<StructDefOp>
748 return origin->emitError()
750 "Cannot unify parameters of type ", ty,
" with parameters of '",
753 .attachNote(defForType.getLoc())
754 .append(
"type parameters must unify with parameters defined here");
757 if (ArrayAttr tyParams = ty.
getParams()) {
766 if (
StructType sTy = llvm::dyn_cast<StructType>(ty)) {
768 }
else if (
ArrayType aTy = llvm::dyn_cast<ArrayType>(ty)) {
770 tables, aTy.getDimensionSizes(), aTy, origin, IndexType::get(aTy.getContext())
776 }
else if (
TypeVarType vTy = llvm::dyn_cast<TypeVarType>(ty)) {
780 if (failed(parent)) {
787 return origin->emitError() <<
"type variable " << vTy
788 <<
" must reference a parameter of its enclosing " <<
'\''
Apache License January AND DISTRIBUTION Definitions License shall mean the terms and conditions for and distribution as defined by Sections through of this document Licensor shall mean the copyright owner or entity authorized by the copyright owner that is granting the License Legal Entity shall mean the union of the acting entity and all other entities that control are controlled by or are under common control with that entity For the purposes of this definition control direct or to cause the direction or management of such whether by contract or including but not limited to software source documentation and configuration files Object form shall mean any form resulting from mechanical transformation or translation of a Source including but not limited to compiled object generated and conversions to other media types Work shall mean the work of whether in Source or Object made available under the as indicated by a copyright notice that is included in or attached to the whether in Source or Object that is based or other modifications as a an original work of authorship For the purposes of this Derivative Works shall not include works that remain separable or merely the Work and Derivative Works thereof Contribution shall mean any work of including the original version of the Work and any modifications or additions to that Work or Derivative Works that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner For the purposes of this definition
within a display generated by the Derivative if and wherever such third party notices normally appear The contents of the NOTICE file are for informational purposes only and do not modify the License You may add Your own attribution notices within Derivative Works that You alongside or as an addendum to the NOTICE text from the provided that such additional attribution notices cannot be construed as modifying the License You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for or distribution of Your or for any such Derivative Works as a provided Your and distribution of the Work otherwise complies with the conditions stated in this License Submission of Contributions Unless You explicitly state any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this without any additional terms or conditions Notwithstanding the nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions Trademarks This License does not grant permission to use the trade names
Apache License January AND DISTRIBUTION Definitions License shall mean the terms and conditions for and distribution as defined by Sections through of this document Licensor shall mean the copyright owner or entity authorized by the copyright owner that is granting the License Legal Entity shall mean the union of the acting entity and all other entities that control are controlled by or are under common control with that entity For the purposes of this definition control direct or to cause the direction or management of such whether by contract or including but not limited to software source documentation and configuration files Object form shall mean any form resulting from mechanical transformation or translation of a Source including but not limited to compiled object generated and conversions to other media types Work shall mean the work of whether in Source or Object made available under the as indicated by a copyright notice that is included in or attached to the whether in Source or Object that is based or other modifications as a an original work of authorship For the purposes of this Derivative Works shall not include works that remain separable from
This file defines methods symbol lookup across LLZK operations and included files.
StructType getType(::std::optional<::mlir::ArrayAttr > constParams={})
Gets the StructType representing this struct.
static constexpr ::llvm::StringLiteral getOperationName()
::std::string getHeaderString()
Generate header string, in the same format as the assemblyFormat.
::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
static constexpr ::llvm::StringLiteral getOperationName()
OpT getConstNamed(::mlir::StringRef find)
Return the op of type OpT with the given name within the body region if it exists,...
static constexpr ::llvm::StringLiteral getOperationName()
::std::optional<::mlir::Type > getTypeOpt()
void assertValidAttrForParamOfType(Attribute attr)
SymbolRefAttr appendLeafName(SymbolRefAttr orig, const Twine &newLeafSuffix)
constexpr char LANG_ATTR_NAME[]
Name of the attribute on the top-level ModuleOp that identifies the ModuleOp as the root module and s...
mlir::FlatSymbolRefAttr getFlatSymbolRefAttr(mlir::MLIRContext *context, const mlir::Twine &twine)
Construct a FlatSymbolRefAttr with the given content.
mlir::FailureOr< SymbolLookupResultUntyped > lookupTopLevelSymbol(mlir::SymbolTableCollection &tables, mlir::SymbolRefAttr symbol, mlir::Operation *origin, bool reportMissing=true)
FailureOr< StructType > getMainInstanceType(Operation *lookupFrom)
llvm::SmallVector< StringRef > getNames(SymbolRefAttr ref)
mlir::StringAttr getSymbolName(mlir::Operation *symbol)
Returns the name of the given symbol operation, or nullptr if no symbol is present.
bool structTypesUnify(StructType lhs, StructType rhs, ArrayRef< StringRef > rhsReversePrefix, UnificationMap *unifications)
FailureOr< ModuleOp > getRootModule(Operation *from)
FailureOr< TemplateOp > getConstResolutionTemplate(SymbolTableCollection &tables, Operation *origin)
LogicalResult verifyTemplateParamsMatchInferred(Operation *origin, ArrayAttr explicitParams, llvm::iterator_range< Region::op_iterator< TemplateParamOp > > targetParamDefs, const UnificationMap &unifications)
mlir::DenseMap< std::pair< mlir::SymbolRefAttr, Side >, mlir::Attribute > UnificationMap
Optional result from type unifications.
bool isNullOrEmpty(mlir::ArrayAttr a)
SymbolRefAttr appendLeaf(SymbolRefAttr orig, FlatSymbolRefAttr newLeaf)
OpClass getParentOfType(mlir::Operation *op)
Return the closest surrounding parent/ancestor operation that is of type 'OpClass'.
SymbolRefAttr replaceLeaf(SymbolRefAttr orig, FlatSymbolRefAttr newLeaf)
FailureOr< StructDefOp > verifyStructTypeResolution(SymbolTableCollection &tables, StructType ty, Operation *origin)
FailureOr< ModuleOp > getTopRootModule(Operation *from)
LogicalResult verifyParamsOfType(SymbolTableCollection &tables, ArrayRef< Attribute > tyParams, Type parameterizedType, Operation *origin, std::optional< Type > requiredParamType)
LogicalResult verifyTypeResolution(SymbolTableCollection &tables, Operation *origin, Type ty)
LogicalResult verifyTemplateParamValueCompatibility(Operation *origin, Attribute value, TemplateParamOp targetParam)
LogicalResult verifyTemplateParamValuesCompatibility(Operation *origin, ArrayAttr explicitParams, llvm::iterator_range< Region::op_iterator< TemplateParamOp > > targetParamDefs)
bool isDynamic(IntegerAttr intAttr)
FailureOr< StructType > getTypeFromLlzkMainAttr(ModuleOp op, Attribute attr)
mlir::SymbolRefAttr asSymbolRefAttr(mlir::StringAttr root, mlir::SymbolRefAttr tail)
Build a SymbolRefAttr that prepends tail with root, i.e., root::tail.
bool typesUnify(Type lhs, Type rhs, ArrayRef< StringRef > rhsReversePrefix, UnificationMap *unifications)
void eraseEmptyNestedModules(ModuleOp rootModule)
FailureOr< SymbolLookupResult< StructDefOp > > getMainInstanceDef(SymbolTableCollection &symbolTable, Operation *lookupFrom)
bool typeParamsUnify(const ArrayRef< Attribute > &lhsParams, const ArrayRef< Attribute > &rhsParams, UnificationMap *unifications)
FailureOr< SymbolRefAttr > getPathFromTopRoot(SymbolOpInterface to, ModuleOp *foundRoot)
FailureOr< SymbolRefAttr > getPathRelativeToAncestor(SymbolOpInterface symbol, ModuleOp ancestor, llvm::function_ref< InFlightDiagnostic()> emitError)
LogicalResult verifyTemplateParamSymbol(SymbolTableCollection &tables, SymbolRefAttr symbol, Operation *origin)
llvm::SmallVector< FlatSymbolRefAttr > getPieces(SymbolRefAttr ref)
FailureOr< SymbolLookupResult< StructDefOp > > getRootStructDef(SymbolTableCollection &tables, Operation *lookupFrom, StringRef symbolPath)
FailureOr< SymbolRefAttr > getPathFromRoot(SymbolOpInterface to, ModuleOp *foundRoot)
constexpr char MAIN_ATTR_NAME[]
Name of the attribute on the top-level ModuleOp that specifies the type of the main struct.
LogicalResult verifyParamOfType(SymbolTableCollection &tables, SymbolRefAttr param, Type parameterizedType, Operation *origin, std::optional< Type > requiredParamType)
bool isValidConstReadType(Type type)