[Mlir-commits] [mlir] [mlir] Add FileRange location type. (PR #80213)

Jacques Pienaar llvmlistbot at llvm.org
Sun Oct 20 20:30:09 PDT 2024


https://github.com/jpienaar updated https://github.com/llvm/llvm-project/pull/80213

>From 9fc9ed39167c6501037f2e4df919ebe567705f64 Mon Sep 17 00:00:00 2001
From: Jacques Pienaar <jpienaar at google.com>
Date: Mon, 21 Oct 2024 03:17:33 +0000
Subject: [PATCH] [mlir] Add FileRange location type.

This location type represents a contiguous range inside a file. It is
effectively a pair of FileLineCols. Add new type and make FileLineCol a
view for case where it matches existing previous one.

The location includes filename and optional start line & col, and end
line & col. Considered common cases are file:line, file:line:col,
file:line:start_col to file:line:end_col and general range within same
file.
---
 mlir/include/mlir/IR/Builders.h               |   1 +
 .../include/mlir/IR/BuiltinDialectBytecode.td |  24 ++-
 .../mlir/IR/BuiltinLocationAttributes.td      |  83 +++++++--
 mlir/include/mlir/IR/BytecodeBase.td          |   6 +
 mlir/include/mlir/IR/Location.h               |  31 ++++
 mlir/lib/AsmParser/LocationParser.cpp         |  74 ++++++--
 mlir/lib/AsmParser/Parser.h                   |   2 +-
 mlir/lib/IR/AsmPrinter.cpp                    |  13 +-
 mlir/lib/IR/BuiltinDialectBytecode.cpp        |  47 +++++
 mlir/lib/IR/Location.cpp                      | 168 ++++++++++++++++--
 mlir/test/IR/locations.mlir                   |   9 +
 11 files changed, 410 insertions(+), 48 deletions(-)

diff --git a/mlir/include/mlir/IR/Builders.h b/mlir/include/mlir/IR/Builders.h
index 04a8bddc3cd59a..18732101f939c9 100644
--- a/mlir/include/mlir/IR/Builders.h
+++ b/mlir/include/mlir/IR/Builders.h
@@ -19,6 +19,7 @@ class AffineExpr;
 class IRMapping;
 class UnknownLoc;
 class FileLineColLoc;
+class FileLineColRange;
 class Type;
 class PrimitiveType;
 class IntegerType;
diff --git a/mlir/include/mlir/IR/BuiltinDialectBytecode.td b/mlir/include/mlir/IR/BuiltinDialectBytecode.td
index f50b5dd7ad8226..09b21173b71a74 100644
--- a/mlir/include/mlir/IR/BuiltinDialectBytecode.td
+++ b/mlir/include/mlir/IR/BuiltinDialectBytecode.td
@@ -95,11 +95,26 @@ def CallSiteLoc : DialectAttribute<(attr
   LocationAttr:$caller
 )>;
 
+let cType = "FileLineColRange" in {
+def FileLineColRange : DialectAttribute<(attr
+  StringAttr:$filename,
+  WithBuilder<"$_args",
+    WithType<"SmallVector<uint64_t>",
+    WithParser <"succeeded(readFileLineColRangeLocs($_reader, $_var))",
+    WithPrinter<"writeFileLineColRangeLocs($_writer, $_name)">>>>:$rawLocData
+)> {
+  let cBuilder = "getFileLineColRange(context, filename, rawLocData)";
+  let printerPredicate = "!::llvm::isa<FileLineColLoc>($_val)";
+}
+
 def FileLineColLoc : DialectAttribute<(attr
   StringAttr:$filename,
-  VarInt:$line,
-  VarInt:$column
-)>;
+  PresentOptionalVarInt:$start_line,
+  PresentOptionalVarInt:$start_column
+)> {
+  let printerPredicate = "::llvm::isa<FileLineColLoc>($_val)";
+}
+}
 
 let cType = "FusedLoc",
     cBuilder = "cast<FusedLoc>(get<FusedLoc>(context, $_args))" in {
@@ -321,7 +336,8 @@ def BuiltinDialectAttributes : DialectAttributes<"Builtin"> {
     DenseIntOrFPElementsAttr,
     DenseStringElementsAttr,
     SparseElementsAttr,
-    DistinctAttr
+    DistinctAttr,
+    FileLineColRange,
   ];
 }
 
diff --git a/mlir/include/mlir/IR/BuiltinLocationAttributes.td b/mlir/include/mlir/IR/BuiltinLocationAttributes.td
index bbe566ce977775..ca609f8bbbe263 100644
--- a/mlir/include/mlir/IR/BuiltinLocationAttributes.td
+++ b/mlir/include/mlir/IR/BuiltinLocationAttributes.td
@@ -60,46 +60,97 @@ def CallSiteLoc : Builtin_LocationAttr<"CallSiteLoc"> {
 }
 
 //===----------------------------------------------------------------------===//
-// FileLineColLoc
+// FileLineColRange
 //===----------------------------------------------------------------------===//
 
-def FileLineColLoc : Builtin_LocationAttr<"FileLineColLoc"> {
-  let summary = "A file:line:column source location";
+def FileLineColRange : Builtin_LocationAttr<"FileLineColRange"> {
+  let summary = "A file:line:column source location range";
   let description = [{
     Syntax:
 
     ```
     filelinecol-location ::= string-literal `:` integer-literal `:`
                              integer-literal
+                             (`to` (integer-literal ?) `:` integer-literal ?)
     ```
 
-    An instance of this location represents a tuple of file, line number, and
-    column number. This is similar to the type of location that you get from
-    most source languages.
+    An instance of this location represents a tuple of file, start and end line
+    number, and start and end column number. It allows for the following
+    configurations:
+
+    *   A single file line location: `file:line`;
+    *   A single file line col location: `file:line:column`;
+    *   A single line range: `file:line:column to :column`;
+    *   A single file range: `file:line:column to line:column`;
 
     Example:
 
     ```mlir
-    loc("mysource.cc":10:8)
+    loc("mysource.cc":10:8 to 12:18)
     ```
   }];
-  let parameters = (ins "StringAttr":$filename, "unsigned":$line,
-                        "unsigned":$column);
+
+  // Note: this only shows the parameters for which accessors are generated. The
+  // locations are only set in storage.
+  let parameters = (ins "StringAttr":$filename);
   let builders = [
+
+    AttrBuilderWithInferredContext<(ins "StringAttr":$filename), [{
+      return $_get(filename.getContext(), filename, ArrayRef<unsigned>{});
+    }]>,
+    AttrBuilderWithInferredContext<(ins "StringAttr":$filename,
+                                        "unsigned":$line), [{
+      return $_get(filename.getContext(), filename,
+                   ArrayRef<unsigned>{line});
+    }]>,
     AttrBuilderWithInferredContext<(ins "StringAttr":$filename,
                                         "unsigned":$line,
                                         "unsigned":$column), [{
-      return $_get(filename.getContext(), filename, line, column);
+      return $_get(filename.getContext(), filename,
+                   ArrayRef<unsigned>{line, column});
     }]>,
-    AttrBuilder<(ins "StringRef":$filename, "unsigned":$line,
-                     "unsigned":$column), [{
+    AttrBuilder<(ins "::llvm::StringRef":$filename,
+                     "unsigned":$start_line,
+                     "unsigned":$start_column), [{
       return $_get($_ctxt,
-                   StringAttr::get($_ctxt, filename.empty() ? "-" : filename),
-                   line, column);
-    }]>
+        StringAttr::get($_ctxt, filename.empty() ? "-" : filename),
+        ArrayRef<unsigned>{start_line, start_column});
+    }]>,
+    AttrBuilderWithInferredContext<(ins "::mlir::StringAttr":$filename,
+                                        "unsigned":$line,
+                                        "unsigned":$start_column,
+                                        "unsigned":$end_column), [{
+      return $_get(filename.getContext(), filename,
+                   ArrayRef<unsigned>{line, start_column, end_column});
+    }]>,
+    AttrBuilderWithInferredContext<(ins "::mlir::StringAttr":$filename,
+                                        "unsigned":$start_line,
+                                        "unsigned":$start_column,
+                                        "unsigned":$end_line,
+                                        "unsigned":$end_column), [{
+      return $_get(filename.getContext(), filename,
+        ArrayRef<unsigned>{start_line, start_column, end_column, end_line});
+    }]>,
+    AttrBuilder<(ins "::llvm::StringRef":$filename,
+                     "unsigned":$start_line,
+                     "unsigned":$start_column,
+                     "unsigned":$end_line,
+                     "unsigned":$end_column), [{
+      return $_get($_ctxt,
+        StringAttr::get($_ctxt, filename.empty() ? "-" : filename),
+        ArrayRef<unsigned>{start_line, start_column, end_column, end_line});
+    }]>,
   ];
+
+  let extraClassDeclaration = [{
+    std::optional<unsigned> getStartLine() const;
+    std::optional<unsigned> getStartColumn() const;
+    std::optional<unsigned> getEndColumn() const;
+    std::optional<unsigned> getEndLine() const;
+  }];
   let skipDefaultBuilders = 1;
-  let attrName = "builtin.file_line_loc";
+  let genStorageClass = 0;
+  let attrName = "builtin.file_line_range";
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/mlir/include/mlir/IR/BytecodeBase.td b/mlir/include/mlir/IR/BytecodeBase.td
index 07f1e284156c36..e6799988cbd3ce 100644
--- a/mlir/include/mlir/IR/BytecodeBase.td
+++ b/mlir/include/mlir/IR/BytecodeBase.td
@@ -82,6 +82,12 @@ def VarInt :
   WithBuilder<"$_args",
   WithPrinter<"$_writer.writeVarInt($_getter)",
   WithType   <"uint64_t">>>>;
+// This is for optional ints which are guaranteed to be present.
+def PresentOptionalVarInt :
+  WithParser <"succeeded($_reader.readVarInt($_var))",
+  WithBuilder<"$_args",
+  WithPrinter<"$_writer.writeVarInt(*$_getter)",
+  WithType   <"uint64_t">>>>;
 def SignedVarInt :
   WithParser <"succeeded($_reader.readSignedVarInt($_var))",
   WithBuilder<"$_args",
diff --git a/mlir/include/mlir/IR/Location.h b/mlir/include/mlir/IR/Location.h
index 5eb1bfaf4afcdc..1f5b51ada7f0ca 100644
--- a/mlir/include/mlir/IR/Location.h
+++ b/mlir/include/mlir/IR/Location.h
@@ -136,6 +136,11 @@ inline ::llvm::hash_code hash_value(Location arg) {
 // Tablegen Attribute Declarations
 //===----------------------------------------------------------------------===//
 
+// Forward declaration for class created later.
+namespace mlir::detail {
+struct FileLineColRangeAttrStorage;
+} // namespace mlir::detail
+
 #define GET_ATTRDEF_CLASSES
 #include "mlir/IR/BuiltinLocationAttributes.h.inc"
 
@@ -164,6 +169,32 @@ class FusedLocWith : public FusedLoc {
   }
 };
 
+//===----------------------------------------------------------------------===//
+// FileLineColLoc
+//===----------------------------------------------------------------------===//
+
+// An instance of this location represents a tuple of file, line number, and
+// column number. This is similar to the type of location that you get from
+// most source languages.
+//
+// FileLineColLoc is a FileLineColRange with exactly one line and column.
+class FileLineColLoc : public FileLineColRange {
+public:
+  using FileLineColRange::FileLineColRange;
+
+  static FileLineColLoc get(StringAttr filename, unsigned line,
+                            unsigned column);
+  static FileLineColLoc get(MLIRContext *context, StringRef fileName,
+                            unsigned line, unsigned column);
+
+  StringAttr getFilename() const;
+  unsigned getLine() const;
+  unsigned getColumn() const;
+
+  /// Methods for support type inquiry through isa, cast, and dyn_cast.
+  static bool classof(Attribute attr);
+};
+
 //===----------------------------------------------------------------------===//
 // OpaqueLoc
 //===----------------------------------------------------------------------===//
diff --git a/mlir/lib/AsmParser/LocationParser.cpp b/mlir/lib/AsmParser/LocationParser.cpp
index 1365da03c7c3d6..fb0999bed201d5 100644
--- a/mlir/lib/AsmParser/LocationParser.cpp
+++ b/mlir/lib/AsmParser/LocationParser.cpp
@@ -12,6 +12,7 @@
 #include "mlir/IR/BuiltinAttributes.h"
 #include "mlir/IR/Location.h"
 #include "mlir/Support/LLVM.h"
+#include <optional>
 
 using namespace mlir;
 using namespace mlir::detail;
@@ -97,37 +98,82 @@ ParseResult Parser::parseFusedLocation(LocationAttr &loc) {
   return success();
 }
 
-ParseResult Parser::parseNameOrFileLineColLocation(LocationAttr &loc) {
+ParseResult Parser::parseNameOrFileLineColRange(LocationAttr &loc) {
   auto *ctx = getContext();
   auto str = getToken().getStringValue();
   consumeToken(Token::string);
 
+  std::optional<unsigned> startLine, startColumn, endLine, endColumn;
+
   // If the next token is ':' this is a filelinecol location.
   if (consumeIf(Token::colon)) {
     // Parse the line number.
     if (getToken().isNot(Token::integer))
       return emitWrongTokenError(
-          "expected integer line number in FileLineColLoc");
-    auto line = getToken().getUnsignedIntegerValue();
-    if (!line)
+          "expected integer line number in FileLineColRange");
+    startLine = getToken().getUnsignedIntegerValue();
+    if (!startLine)
       return emitWrongTokenError(
-          "expected integer line number in FileLineColLoc");
+          "expected integer line number in FileLineColRange");
     consumeToken(Token::integer);
 
     // Parse the ':'.
-    if (parseToken(Token::colon, "expected ':' in FileLineColLoc"))
-      return failure();
+    if (getToken().isNot(Token::colon)) {
+      loc = FileLineColRange::get(StringAttr::get(ctx, str), *startLine);
+      return success();
+    }
+    consumeToken(Token::colon);
 
     // Parse the column number.
-    if (getToken().isNot(Token::integer))
+    if (getToken().isNot(Token::integer)) {
+      return emitWrongTokenError(
+          "expected integer column number in FileLineColRange");
+    }
+    startColumn = getToken().getUnsignedIntegerValue();
+    if (!startColumn.has_value())
+      return emitError("expected integer column number in FileLineColRange");
+    consumeToken(Token::integer);
+
+    if (!isCurrentTokenAKeyword() || getTokenSpelling() != "to") {
+      loc = FileLineColLoc::get(ctx, str, *startLine, *startColumn);
+      return success();
+    }
+    consumeToken();
+
+    // Parse the line number.
+    if (getToken().is(Token::integer)) {
+      endLine = getToken().getUnsignedIntegerValue();
+      if (!endLine) {
+        return emitWrongTokenError(
+            "expected integer line number in FileLineColRange");
+      }
+      consumeToken(Token::integer);
+    }
+
+    // Parse the ':'.
+    if (getToken().isNot(Token::colon)) {
+      return emitWrongTokenError(
+          "expected either integer or `:` post `to` in FileLineColRange");
+    }
+    consumeToken(Token::colon);
+
+    // Parse the column number.
+    if (getToken().isNot(Token::integer)) {
       return emitWrongTokenError(
-          "expected integer column number in FileLineColLoc");
-    auto column = getToken().getUnsignedIntegerValue();
-    if (!column.has_value())
-      return emitError("expected integer column number in FileLineColLoc");
+          "expected integer column number in FileLineColRange");
+    }
+    endColumn = getToken().getUnsignedIntegerValue();
+    if (!endColumn.has_value())
+      return emitError("expected integer column number in FileLineColRange");
     consumeToken(Token::integer);
 
-    loc = FileLineColLoc::get(ctx, str, *line, *column);
+    if (endLine.has_value()) {
+      loc = FileLineColRange::get(StringAttr::get(ctx, str), *startLine,
+                                  *startColumn, *endLine, *endColumn);
+    } else {
+      loc = FileLineColRange::get(StringAttr::get(ctx, str), *startLine,
+                                  *startColumn, *endColumn);
+    }
     return success();
   }
 
@@ -166,7 +212,7 @@ ParseResult Parser::parseLocationInstance(LocationAttr &loc) {
 
   // Handle either name or filelinecol locations.
   if (getToken().is(Token::string))
-    return parseNameOrFileLineColLocation(loc);
+    return parseNameOrFileLineColRange(loc);
 
   // Bare tokens required for other cases.
   if (!getToken().is(Token::bare_identifier))
diff --git a/mlir/lib/AsmParser/Parser.h b/mlir/lib/AsmParser/Parser.h
index bf91831798056b..ff06e5be6e6b7c 100644
--- a/mlir/lib/AsmParser/Parser.h
+++ b/mlir/lib/AsmParser/Parser.h
@@ -305,7 +305,7 @@ class Parser {
   ParseResult parseFusedLocation(LocationAttr &loc);
 
   /// Parse a name or FileLineCol location instance.
-  ParseResult parseNameOrFileLineColLocation(LocationAttr &loc);
+  ParseResult parseNameOrFileLineColRange(LocationAttr &loc);
 
   //===--------------------------------------------------------------------===//
   // Affine Parsing
diff --git a/mlir/lib/IR/AsmPrinter.cpp b/mlir/lib/IR/AsmPrinter.cpp
index a728425f2ec6ba..0305740ad442c4 100644
--- a/mlir/lib/IR/AsmPrinter.cpp
+++ b/mlir/lib/IR/AsmPrinter.cpp
@@ -2009,12 +2009,21 @@ void AsmPrinter::Impl::printLocationInternal(LocationAttr loc, bool pretty,
         else
           os << "unknown";
       })
-      .Case<FileLineColLoc>([&](FileLineColLoc loc) {
+      .Case<FileLineColRange>([&](FileLineColRange loc) {
         if (pretty)
           os << loc.getFilename().getValue();
         else
           printEscapedString(loc.getFilename());
-        os << ':' << loc.getLine() << ':' << loc.getColumn();
+        os << ':' << *loc.getStartLine();
+        if (loc.getStartColumn()) {
+          os << ':' << *loc.getStartColumn();
+          if (loc.getEndColumn().has_value() || loc.getEndLine().has_value())
+            os << " to ";
+          if (loc.getEndLine().has_value())
+            os << *loc.getEndLine();
+          if (loc.getEndColumn().has_value())
+            os << ':' << *loc.getEndColumn();
+        }
       })
       .Case<NameLoc>([&](NameLoc loc) {
         printEscapedString(loc.getName());
diff --git a/mlir/lib/IR/BuiltinDialectBytecode.cpp b/mlir/lib/IR/BuiltinDialectBytecode.cpp
index 6131b7eae90c8b..17767a3b49f51a 100644
--- a/mlir/lib/IR/BuiltinDialectBytecode.cpp
+++ b/mlir/lib/IR/BuiltinDialectBytecode.cpp
@@ -14,7 +14,10 @@
 #include "mlir/IR/BuiltinTypes.h"
 #include "mlir/IR/Diagnostics.h"
 #include "mlir/IR/DialectResourceBlobManager.h"
+#include "mlir/IR/Location.h"
+#include "mlir/Support/LLVM.h"
 #include "llvm/ADT/TypeSwitch.h"
+#include <cstdint>
 
 using namespace mlir;
 
@@ -80,6 +83,50 @@ void writePotentiallySplatString(DialectBytecodeWriter &writer,
     writer.writeOwnedString(str);
 }
 
+FileLineColRange getFileLineColRange(MLIRContext *context, StringAttr filename,
+                                     ArrayRef<uint64_t> lineCols) {
+  switch (lineCols.size()) {
+  case 0:
+    return FileLineColRange::get(filename);
+  case 1:
+    return FileLineColRange::get(filename, lineCols[0]);
+  case 2:
+    return FileLineColRange::get(filename, lineCols[0], lineCols[1]);
+  case 3:
+    return FileLineColRange::get(filename, lineCols[0], lineCols[1],
+                                 lineCols[2]);
+  case 4:
+    return FileLineColRange::get(filename, lineCols[0], lineCols[1],
+                                 lineCols[3], lineCols[2]);
+  default:
+    return {};
+  }
+}
+
+LogicalResult readFileLineColRangeLocs(DialectBytecodeReader &reader,
+                                       SmallVectorImpl<uint64_t> &lineCols) {
+  return reader.readList(
+      lineCols, [&reader](uint64_t &val) { return reader.readVarInt(val); });
+}
+
+void writeFileLineColRangeLocs(DialectBytecodeWriter &writer,
+                               FileLineColRange range) {
+  int count = range.getStartLine().has_value() +
+              range.getStartColumn().has_value() +
+              range.getEndLine().has_value() + range.getEndColumn().has_value();
+  writer.writeVarInt(count);
+  if (count == 0)
+    return;
+  // Startline here is either known or zero with other trailing offsets.
+  writer.writeVarInt(range.getStartLine().value_or(0));
+  if (range.getStartColumn().has_value())
+    writer.writeVarInt(*range.getStartColumn());
+  if (range.getEndColumn().has_value())
+    writer.writeVarInt(*range.getEndColumn());
+  if (range.getEndLine().has_value())
+    writer.writeVarInt(*range.getEndLine());
+}
+
 #include "mlir/IR/BuiltinDialectBytecode.cpp.inc"
 
 /// This class implements the bytecode interface for the builtin dialect.
diff --git a/mlir/lib/IR/Location.cpp b/mlir/lib/IR/Location.cpp
index dbd84912a8657d..7cae5f1099b1b5 100644
--- a/mlir/lib/IR/Location.cpp
+++ b/mlir/lib/IR/Location.cpp
@@ -7,31 +7,113 @@
 //===----------------------------------------------------------------------===//
 
 #include "mlir/IR/Location.h"
+#include "mlir/IR/AttributeSupport.h"
+#include "mlir/IR/BuiltinAttributes.h"
 #include "mlir/IR/BuiltinDialect.h"
+#include "mlir/IR/MLIRContext.h"
 #include "mlir/IR/Visitors.h"
+#include "mlir/Support/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/TypeSwitch.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/TrailingObjects.h"
+#include <cassert>
+#include <iterator>
+#include <memory>
+#include <optional>
+#include <tuple>
+#include <utility>
 
 using namespace mlir;
 using namespace mlir::detail;
 
-//===----------------------------------------------------------------------===//
-/// Tablegen Attribute Definitions
-//===----------------------------------------------------------------------===//
+namespace mlir::detail {
+struct FileLineColRangeAttrStorage final
+    : public ::mlir::AttributeStorage,
+      public llvm::TrailingObjects<FileLineColRangeAttrStorage, unsigned> {
+  using PointerPair = llvm::PointerIntPair<StringAttr, 2>;
+  using KeyTy = std::tuple<StringAttr, ::llvm::ArrayRef<unsigned>>;
+
+  FileLineColRangeAttrStorage(StringAttr filename, int numLocs)
+      : filenameAndTrailing(filename, numLocs) {}
+
+  static FileLineColRangeAttrStorage *
+  construct(::mlir::AttributeStorageAllocator &allocator, KeyTy &&tblgenKey) {
+    auto numInArray = std::get<1>(tblgenKey).size();
+    // Note: Considered asserting that numInArray is at least 1, but this
+    // is not needed in memory or in printed form. This should very rarely be
+    // 0 here as that means a NamedLoc would have been more efficient. But this
+    // does allow for location with just a file, and also having the interface
+    // be more uniform.
+    auto locEnc = numInArray == 0 ? 1 : numInArray;
+    // Allocate a new storage instance.
+    auto byteSize =
+        FileLineColRangeAttrStorage::totalSizeToAlloc<unsigned>(locEnc - 1);
+    auto *rawMem =
+        allocator.allocate(byteSize, alignof(FileLineColRangeAttrStorage));
+    auto *result = ::new (rawMem) FileLineColRangeAttrStorage(
+        std::move(std::get<0>(tblgenKey)), locEnc - 1);
+    if (numInArray > 0) {
+      result->startLine = std::get<1>(tblgenKey)[0];
+      // Copy in the element types into the trailing storage.
+      std::uninitialized_copy(std::next(std::get<1>(tblgenKey).begin()),
+                              std::get<1>(tblgenKey).end(),
+                              result->getTrailingObjects<unsigned>());
+    }
+    return result;
+  }
 
-#define GET_ATTRDEF_CLASSES
-#include "mlir/IR/BuiltinLocationAttributes.cpp.inc"
+  // Return the number of held types.
+  unsigned size() const { return filenameAndTrailing.getInt() + 1; }
+
+  bool operator==(const KeyTy &tblgenKey) const {
+    return (filenameAndTrailing.getPointer() == std::get<0>(tblgenKey)) &&
+           (size() == std::get<1>(tblgenKey).size()) &&
+           (startLine == std::get<1>(tblgenKey)[0]) &&
+           (ArrayRef<unsigned>{getTrailingObjects<unsigned>(), size() - 1} ==
+            ArrayRef<unsigned>{std::get<1>(tblgenKey)}.drop_front());
+  }
+
+  std::optional<unsigned> getLineCols(unsigned index) const {
+    if (size() <= index)
+      return std::nullopt;
+    return getTrailingObjects<unsigned>()[index - 1];
+  }
+
+  std::optional<unsigned> getStartLine() const {
+    // Only return nullopt if there are no other locations and start line is 0.
+    if (startLine == 0 && filenameAndTrailing.getInt() == 0)
+      return std::nullopt;
+    return startLine;
+  }
+  std::optional<unsigned> getStartColumn() const { return getLineCols(1); }
+  std::optional<unsigned> getEndColumn() const { return getLineCols(2); }
+  std::optional<unsigned> getEndLine() const { return getLineCols(3); }
+
+  static ::llvm::hash_code hashKey(const KeyTy &tblgenKey) {
+    return ::llvm::hash_combine(std::get<0>(tblgenKey), std::get<1>(tblgenKey));
+  }
+
+  // Supports
+  //  - 0 (file:line)
+  //  - 1 (file:line:col)
+  //  - 2 (file:line:start_col to file:line:end_col) and
+  //  - 3 (file:start_line:start_col to file:end_line:end_col)
+  llvm::PointerIntPair<StringAttr, 2> filenameAndTrailing;
+  unsigned startLine = 0;
+};
+} // namespace mlir::detail
 
 //===----------------------------------------------------------------------===//
-// BuiltinDialect
+/// Tablegen Attribute Definitions
 //===----------------------------------------------------------------------===//
 
-void BuiltinDialect::registerLocationAttributes() {
-  addAttributes<
-#define GET_ATTRDEF_LIST
+#define GET_ATTRDEF_CLASSES
 #include "mlir/IR/BuiltinLocationAttributes.cpp.inc"
-      >();
-}
 
 //===----------------------------------------------------------------------===//
 // LocationAttr
@@ -66,6 +148,59 @@ CallSiteLoc CallSiteLoc::get(Location name, ArrayRef<Location> frames) {
   return CallSiteLoc::get(name, caller);
 }
 
+//===----------------------------------------------------------------------===//
+// FileLineColLoc
+//===----------------------------------------------------------------------===//
+
+FileLineColLoc FileLineColLoc::get(StringAttr filename, unsigned line,
+                                   unsigned column) {
+  return llvm::cast<FileLineColLoc>(
+      FileLineColRange::get(filename, line, column));
+}
+
+FileLineColLoc FileLineColLoc::get(MLIRContext *context, StringRef fileName,
+                                   unsigned line, unsigned column) {
+  return llvm::cast<FileLineColLoc>(
+      FileLineColRange::get(context, fileName, line, column));
+}
+
+StringAttr FileLineColLoc::getFilename() const {
+  return FileLineColRange::getFilename();
+}
+
+unsigned FileLineColLoc::getLine() const { return *getStartLine(); }
+
+unsigned FileLineColLoc::getColumn() const { return *getStartColumn(); }
+
+bool FileLineColLoc::classof(Attribute attr) {
+  // This could also have been for <= 2. But given this is matching previous
+  // behavior, it is left as is.
+  if (auto range = mlir::dyn_cast<FileLineColRange>(attr))
+    return range.getImpl()->size() == 2;
+  return false;
+}
+
+//===----------------------------------------------------------------------===//
+// FileLineColRange
+//===----------------------------------------------------------------------===//
+
+StringAttr FileLineColRange::getFilename() const {
+  return getImpl()->filenameAndTrailing.getPointer();
+}
+
+std::optional<unsigned> FileLineColRange::getStartLine() const {
+  return getImpl()->getStartLine();
+}
+std::optional<unsigned> FileLineColRange::getStartColumn() const {
+  return getImpl()->getStartColumn();
+}
+std::optional<unsigned> FileLineColRange::getEndColumn() const {
+  return getImpl()->getEndColumn();
+}
+std::optional<unsigned> FileLineColRange::getEndLine() const {
+  return getImpl()->getEndLine();
+}
+
 //===----------------------------------------------------------------------===//
 // FusedLoc
 //===----------------------------------------------------------------------===//
@@ -107,3 +242,14 @@ Location FusedLoc::get(ArrayRef<Location> locs, Attribute metadata,
 
   return Base::get(context, locs, metadata);
 }
+
+//===----------------------------------------------------------------------===//
+// BuiltinDialect
+//===----------------------------------------------------------------------===//
+
+void BuiltinDialect::registerLocationAttributes() {
+  addAttributes<
+#define GET_ATTRDEF_LIST
+#include "mlir/IR/BuiltinLocationAttributes.cpp.inc"
+      >();
+}
diff --git a/mlir/test/IR/locations.mlir b/mlir/test/IR/locations.mlir
index 0c6426ebec8746..d76763c8e5ab76 100644
--- a/mlir/test/IR/locations.mlir
+++ b/mlir/test/IR/locations.mlir
@@ -33,6 +33,15 @@ func.func @inline_notation() -> i32 {
 // CHECK-LABEL: func private @loc_attr(i1 {foo.loc_attr = loc(callsite("foo" at "mysource.cc":10:8))})
 func.func private @loc_attr(i1 {foo.loc_attr = loc(callsite("foo" at "mysource.cc":10:8))})
 
+// CHECK-LABEL: func.func private @filelocrange_attr1(i1 {foo.loc_attr = loc("mysource.cc":10)})
+func.func private @filelocrange_attr1(i1 {foo.loc_attr = loc("mysource.cc":10)})
+// CHECK-LABEL: func.func private @filelocrange_attr2(i1 {foo.loc_attr = loc("mysource.cc":10:8)})
+func.func private @filelocrange_attr2(i1 {foo.loc_attr = loc("mysource.cc":10:8)})
+// CHECK-LABEL: func.func private @filelocrange_attr3(i1 {foo.loc_attr = loc("mysource.cc":10:8 to :12)})
+func.func private @filelocrange_attr3(i1 {foo.loc_attr = loc("mysource.cc":10:8 to :12)})
+// CHECK-LABEL: func.func private @filelocrange_attr4(i1 {foo.loc_attr = loc("mysource.cc":10:8 to 12:4)})
+func.func private @filelocrange_attr4(i1 {foo.loc_attr = loc("mysource.cc":10:8 to 12:4)})
+
   // Check that locations get properly escaped.
 // CHECK-LABEL: func @escape_strings()
 func.func @escape_strings() {



More information about the Mlir-commits mailing list