diff --git a/mlir/include/mlir/IR/Location.h b/mlir/include/mlir/IR/Location.h index 4f2a30332125..ad30031d33d7 100644 --- a/mlir/include/mlir/IR/Location.h +++ b/mlir/include/mlir/IR/Location.h @@ -53,10 +53,10 @@ public: /// This represents a file/line/column location. FileLineCol, - /// This represents an identity name, such as variable and function name. + /// This represents an identity name attached to a child location. Name, - /// This represents a location as call site or variable usage site. . + /// This represents a location as a call site. CallSite, // Represents a location as a 'void*' pointer to a front-end's opaque @@ -170,17 +170,25 @@ public: static bool kindof(Kind kind) { return kind == Kind::FileLineCol; } }; -/// Represents an identity name. It is usually the callee of a CallLocation. +/// Represents an identity name attached to a child location. class NameLoc : public Location { public: using ImplType = detail::NameLocationStorage; using Location::Location; - /// Return a uniqued name location object. + /// Return a uniqued name location object. The child location must not be + /// another NameLoc. + static NameLoc get(Identifier name, Location child, MLIRContext *context); + + /// Return a uniqued name location object with an unknown child. static NameLoc get(Identifier name, MLIRContext *context); + /// Return the name identifier. Identifier getName() const; + /// Return the child location. + Location getChildLoc() const; + /// Methods for support type inquiry through isa, cast, and dyn_cast. static bool kindof(Kind kind) { return kind == Kind::Name; } }; diff --git a/mlir/lib/IR/AsmPrinter.cpp b/mlir/lib/IR/AsmPrinter.cpp index 15cb07528309..ba0b9b5c082d 100644 --- a/mlir/lib/IR/AsmPrinter.cpp +++ b/mlir/lib/IR/AsmPrinter.cpp @@ -397,7 +397,16 @@ void ModulePrinter::printLocationInternal(Location loc, bool pretty) { break; } case Location::Kind::Name: { - os << '\"' << loc.cast().getName() << '\"'; + auto nameLoc = loc.cast(); + os << '\"' << nameLoc.getName() << '\"'; + + // Print the child if it isn't unknown. + auto childLoc = nameLoc.getChildLoc(); + if (!childLoc.isa()) { + os << '('; + printLocationInternal(childLoc, pretty); + os << ')'; + } break; } case Location::Kind::CallSite: { diff --git a/mlir/lib/IR/Location.cpp b/mlir/lib/IR/Location.cpp index 74a1744e9f3d..d4553ab67a38 100644 --- a/mlir/lib/IR/Location.cpp +++ b/mlir/lib/IR/Location.cpp @@ -45,10 +45,20 @@ unsigned FileLineColLoc::getColumn() const { // NameLoc //===----------------------------------------------------------------------===// +NameLoc NameLoc::get(Identifier name, MLIRContext *context) { + return get(name, UnknownLoc::get(context), context); +} + +/// Return the name identifier. Identifier NameLoc::getName() const { return static_cast(loc)->name; } +/// Return the child location. +Location NameLoc::getChildLoc() const { + return static_cast(loc)->child; +} + //===----------------------------------------------------------------------===// // CallSiteLoc //===----------------------------------------------------------------------===// diff --git a/mlir/lib/IR/LocationDetail.h b/mlir/lib/IR/LocationDetail.h index 1e23fa914066..35e1317eea0b 100644 --- a/mlir/lib/IR/LocationDetail.h +++ b/mlir/lib/IR/LocationDetail.h @@ -56,10 +56,11 @@ struct FileLineColLocationStorage : public LocationStorage { }; struct NameLocationStorage : public LocationStorage { - NameLocationStorage(Identifier name) - : LocationStorage(Location::Kind::Name), name(name) {} + NameLocationStorage(Identifier name, Location child) + : LocationStorage(Location::Kind::Name), name(name), child(child) {} Identifier name; + Location child; }; struct CallSiteLocationStorage : public LocationStorage { diff --git a/mlir/lib/IR/MLIRContext.cpp b/mlir/lib/IR/MLIRContext.cpp index 944c2ddf275b..679c2c2de900 100644 --- a/mlir/lib/IR/MLIRContext.cpp +++ b/mlir/lib/IR/MLIRContext.cpp @@ -638,13 +638,15 @@ FileLineColLoc FileLineColLoc::get(UniquedFilename filename, unsigned line, }); } -NameLoc NameLoc::get(Identifier name, MLIRContext *context) { +NameLoc NameLoc::get(Identifier name, Location child, MLIRContext *context) { auto &impl = context->getImpl(); + assert(!child.isa() && + "a NameLoc cannot be used as a child of another NameLoc"); // Safely get or create a location instance. return safeGetOrCreate(impl.nameLocs, name.data(), impl.locationMutex, [&] { return new (impl.locationAllocator.Allocate()) - NameLocationStorage(name); + NameLocationStorage(name, child); }); } diff --git a/mlir/lib/Parser/Parser.cpp b/mlir/lib/Parser/Parser.cpp index f416e28799fd..31b77664df6f 100644 --- a/mlir/lib/Parser/Parser.cpp +++ b/mlir/lib/Parser/Parser.cpp @@ -1502,7 +1502,30 @@ ParseResult Parser::parseLocationInstance(llvm::Optional *loc) { } // Otherwise, this is a NameLoc. - *loc = NameLoc::get(Identifier::get(str, ctx), ctx); + + // Check for a child location. + if (consumeIf(Token::l_paren)) { + auto childSourceLoc = getToken().getLoc(); + + // Parse the child location. + llvm::Optional childLoc; + if (parseLocationInstance(&childLoc)) + return failure(); + + // The child must not be another NameLoc. + if (childLoc->isa()) + return emitError(childSourceLoc, + "child of NameLoc cannot be another NameLoc"); + *loc = NameLoc::get(Identifier::get(str, ctx), *childLoc, ctx); + + // Parse the closing ')'. + if (parseToken(Token::r_paren, + "expected ')' after child location of NameLoc")) + return failure(); + } else { + *loc = NameLoc::get(Identifier::get(str, ctx), ctx); + } + return success(); } diff --git a/mlir/test/IR/invalid-locations.mlir b/mlir/test/IR/invalid-locations.mlir index 7d4e19349c6f..d1e2dd2f90eb 100644 --- a/mlir/test/IR/invalid-locations.mlir +++ b/mlir/test/IR/invalid-locations.mlir @@ -23,6 +23,20 @@ func @location_invalid_instance() { // ----- +func @location_name_missing_r_paren() { +^bb: + return loc("foo"(unknown]) // expected-error {{expected ')' after child location of NameLoc}} +} + +// ----- + +func @location_name_child_is_name() { +^bb: + return loc("foo"("foo")) // expected-error {{child of NameLoc cannot be another NameLoc}} +} + +// ----- + func @location_callsite_missing_l_paren() { ^bb: return loc(callsite unknown // expected-error {{expected '(' in callsite location}}