22#include <mlir/IR/BuiltinOps.h>
23#include <mlir/IR/Operation.h>
25#include <llvm/Support/Debug.h>
27#define DEBUG_TYPE "llzk-symbol-helpers"
34using namespace component;
35using namespace function;
36using namespace global;
37using namespace polymorphic;
41enum RootSelector { CLOSEST, FURTHEST };
48FailureOr<ModuleOp> collectPathToRoot(
49 Operation *
from, Operation *origin, std::vector<FlatSymbolRefAttr> &path, RootSelector whichRoot
51 Operation *check =
from;
52 ModuleOp currRoot =
nullptr;
54 if (ModuleOp m = llvm::dyn_cast_if_present<ModuleOp>(check)) {
59 if (whichRoot == RootSelector::CLOSEST) {
64 if (StringAttr modName = m.getSymNameAttr()) {
65 path.push_back(FlatSymbolRefAttr::get(modName));
66 }
else if (!currRoot) {
67 return origin->emitOpError()
69 "has ancestor '", ModuleOp::getOperationName(),
"' without \"",
LANG_ATTR_NAME,
70 "\" attribute or a name"
72 .attachNote(m.getLoc())
73 .append(
"unnamed '", ModuleOp::getOperationName(),
"' here");
76 }
while ((check = check->getParentOp()));
78 if (whichRoot == RootSelector::FURTHEST && currRoot) {
82 return origin->emitOpError().append(
83 "has no ancestor '", ModuleOp::getOperationName(),
"' with \"",
LANG_ATTR_NAME,
"\" attribute"
89FailureOr<SymbolRefAttr> buildPathFromRoot(
90 Operation *position, Operation *origin, std::vector<FlatSymbolRefAttr> &&path,
91 RootSelector whichRoot
94 if (failed(collectPathToRoot(position, origin, path, whichRoot))) {
98 std::vector<FlatSymbolRefAttr> reversedVec(path.rbegin(), path.rend());
104FailureOr<SymbolRefAttr> buildPathFromRoot(
105 StructDefOp &to, Operation *origin, std::vector<FlatSymbolRefAttr> &&path,
106 RootSelector whichRoot
109 path.push_back(FlatSymbolRefAttr::get(to.getSymNameAttr()));
110 return buildPathFromRoot(to.getOperation(), origin, std::move(path), whichRoot);
113FailureOr<SymbolRefAttr>
getPathFromRoot(StructDefOp &to, RootSelector whichRoot) {
114 std::vector<FlatSymbolRefAttr> path;
115 return buildPathFromRoot(to, to.getOperation(), std::move(path), whichRoot);
118FailureOr<SymbolRefAttr>
getPathFromRoot(FuncDefOp &to, RootSelector whichRoot) {
119 std::vector<FlatSymbolRefAttr> path;
121 path.push_back(FlatSymbolRefAttr::get(to.getSymNameAttr()));
124 Operation *current = to.getOperation();
125 Operation *parent = current->getParentOp();
126 if (StructDefOp parentStruct = llvm::dyn_cast_if_present<StructDefOp>(parent)) {
127 return buildPathFromRoot(parentStruct, current, std::move(path), whichRoot);
128 }
else if (ModuleOp parentMod = llvm::dyn_cast_if_present<ModuleOp>(parent)) {
129 return buildPathFromRoot(parentMod.getOperation(), current, std::move(path), whichRoot);
138llvm::SmallVector<StringRef>
getNames(SymbolRefAttr ref) {
139 llvm::SmallVector<StringRef>
names;
140 names.push_back(ref.getRootReference().getValue());
141 for (
const FlatSymbolRefAttr &r : ref.getNestedReferences()) {
142 names.push_back(r.getValue());
147llvm::SmallVector<FlatSymbolRefAttr>
getPieces(SymbolRefAttr ref) {
148 llvm::SmallVector<FlatSymbolRefAttr> pieces;
149 pieces.push_back(FlatSymbolRefAttr::get(ref.getRootReference()));
150 for (
const FlatSymbolRefAttr &r : ref.getNestedReferences()) {
158SymbolRefAttr changeLeafImpl(
159 StringAttr origRoot, ArrayRef<FlatSymbolRefAttr> origTail, FlatSymbolRefAttr newLeaf,
162 llvm::SmallVector<FlatSymbolRefAttr> newTail;
163 newTail.append(origTail.begin(), origTail.drop_back(drop).end());
164 newTail.push_back(newLeaf);
165 return SymbolRefAttr::get(origRoot, newTail);
170SymbolRefAttr
replaceLeaf(SymbolRefAttr orig, FlatSymbolRefAttr newLeaf) {
171 ArrayRef<FlatSymbolRefAttr> origTail = orig.getNestedReferences();
172 if (origTail.empty()) {
176 return changeLeafImpl(orig.getRootReference(), origTail, newLeaf);
180SymbolRefAttr
appendLeaf(SymbolRefAttr orig, FlatSymbolRefAttr newLeaf) {
181 return changeLeafImpl(orig.getRootReference(), orig.getNestedReferences(), newLeaf, 0);
185 ArrayRef<FlatSymbolRefAttr> origTail = orig.getNestedReferences();
186 if (origTail.empty()) {
189 orig.getContext(), orig.getRootReference().getValue() + newLeafSuffix
192 return changeLeafImpl(
193 orig.getRootReference(), origTail,
200 std::vector<FlatSymbolRefAttr> path;
201 return collectPathToRoot(
from,
from, path, RootSelector::CLOSEST);
213 std::vector<FlatSymbolRefAttr> path;
214 return collectPathToRoot(
from,
from, path, RootSelector::FURTHEST);
226 assert(symbol &&
"pre-condition");
227 assert(
from &&
"pre-condition");
229 SymbolTable::walkSymbolTables(
from,
false, [symbol, &result](Operation *symbolTableOp,
bool) {
230 assert(symbolTableOp->hasTrait<OpTrait::SymbolTable>());
231 bool hasUse = (symbol != symbolTableOp) &&
232 !SymbolTable::symbolKnownUseEmpty(symbol, &symbolTableOp->getRegion(0));
236 auto uses = SymbolTable::getSymbolUses(symbol, &symbolTableOp->getRegion(0));
237 assert(uses.has_value());
238 llvm::dbgs() <<
"Found users of " << *symbol <<
"\n";
239 for (SymbolTable::SymbolUse user : uses.value()) {
240 llvm::dbgs() <<
" * " << *user.getUser() <<
"\n";
249 SymbolTableCollection &tables, SymbolRefAttr param, Type parameterizedType, Operation *origin
254 if (param.getNestedReferences().empty()) {
256 if (succeeded(getParentRes)) {
257 if (getParentRes->hasParamNamed(param.getRootReference())) {
264 if (failed(lookupRes)) {
267 Operation *foundOp = lookupRes->get();
268 if (!llvm::isa<GlobalDefOp>(foundOp)) {
269 return origin->emitError() <<
"ref \"" << param <<
"\" in type " << parameterizedType
270 <<
" refers to a '" << foundOp->getName()
271 <<
"' which is not allowed";
277 SymbolTableCollection &tables, ArrayRef<Attribute> tyParams, Type parameterizedType,
282 LogicalResult paramCheckResult = success();
283 for (Attribute attr : tyParams) {
285 if (SymbolRefAttr symRefParam = llvm::dyn_cast<SymbolRefAttr>(attr)) {
287 paramCheckResult = failure();
289 }
else if (TypeAttr typeParam = llvm::dyn_cast<TypeAttr>(attr)) {
291 paramCheckResult = failure();
296 return paramCheckResult;
299FailureOr<StructDefOp>
307 return origin->emitError()
309 "Cannot unify parameters of type ", ty,
" with parameters of '",
312 .attachNote(defForType.getLoc())
313 .append(
"type parameters must unify with parameters defined here");
316 if (ArrayAttr tyParams = ty.
getParams()) {
325 if (
StructType sTy = llvm::dyn_cast<StructType>(ty)) {
327 }
else if (
ArrayType aTy = llvm::dyn_cast<ArrayType>(ty)) {
332 }
else if (
TypeVarType vTy = llvm::dyn_cast<TypeVarType>(ty)) {
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::ArrayAttr getParams() const
::mlir::FailureOr< SymbolLookupResult< StructDefOp > > getDefinition(::mlir::SymbolTableCollection &symbolTable, ::mlir::Operation *op) const
Gets the struct op that defines this struct.
static constexpr ::llvm::StringLiteral getOperationName()
void assertValidAttrForParamOfType(Attribute attr)
FailureOr< SymbolRefAttr > getPathFromRoot(StructDefOp &to)
SymbolRefAttr appendLeafName(SymbolRefAttr orig, const Twine &newLeafSuffix)
constexpr char LANG_ATTR_NAME[]
Name of the attribute on the top-level ModuleOp that specifies the IR language name.
bool hasUsesWithin(Operation *symbol, Operation *from)
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)
llvm::SmallVector< StringRef > getNames(SymbolRefAttr ref)
bool structTypesUnify(StructType lhs, StructType rhs, ArrayRef< StringRef > rhsReversePrefix, UnificationMap *unifications)
FailureOr< ModuleOp > getRootModule(Operation *from)
SymbolRefAttr appendLeaf(SymbolRefAttr orig, FlatSymbolRefAttr newLeaf)
SymbolRefAttr replaceLeaf(SymbolRefAttr orig, FlatSymbolRefAttr newLeaf)
FailureOr< StructDefOp > verifyStructTypeResolution(SymbolTableCollection &tables, StructType ty, Operation *origin)
FailureOr< SymbolRefAttr > getPathFromTopRoot(StructDefOp &to)
FailureOr< ModuleOp > getTopRootModule(Operation *from)
LogicalResult verifyTypeResolution(SymbolTableCollection &tables, Operation *origin, Type ty)
LogicalResult verifyParamsOfType(SymbolTableCollection &tables, ArrayRef< Attribute > tyParams, Type parameterizedType, Operation *origin)
mlir::SymbolRefAttr asSymbolRefAttr(mlir::StringAttr root, mlir::SymbolRefAttr tail)
Build a SymbolRefAttr that prepends tail with root, i.e. root::tail.
mlir::FailureOr< OpClass > getParentOfType(mlir::Operation *op)
Return the closest surrounding parent operation that is of type 'OpClass'.
LogicalResult verifyParamOfType(SymbolTableCollection &tables, SymbolRefAttr param, Type parameterizedType, Operation *origin)
llvm::SmallVector< FlatSymbolRefAttr > getPieces(SymbolRefAttr ref)