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

llvmlistbot at llvm.org llvmlistbot at llvm.org
Sat Nov 23 05:12:08 PST 2024


Author: Jacques Pienaar
Date: 2024-11-23T05:12:04-08:00
New Revision: 01e75646a5d4977a9e441e3db1042df0beccc4bb

URL: https://github.com/llvm/llvm-project/commit/01e75646a5d4977a9e441e3db1042df0beccc4bb
DIFF: https://github.com/llvm/llvm-project/commit/01e75646a5d4977a9e441e3db1042df0beccc4bb.diff

LOG: [mlir] Add FileRange location type. (#80213)

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. In memory its encoded as trailing objects. This keeps the memory
requirement the same as FileLineColLoc today (makes the rather common
File:Line cheaper) at the expense of extra work at decoding time. Kept the unsigned
type.

There was the option to always have file range be castable to
FileLineColLoc. This cast would just drop other fields. That may result
in some simpler staging. TBD.

This is a rather minimal change, it does not yet add bindings (C or
Python), lowering to LLVM debug locations etc. that supports end line:cols.

---------

Co-authored-by: River Riddle <riddleriver at gmail.com>

Added: 
    

Modified: 
    mlir/include/mlir/IR/Builders.h
    mlir/include/mlir/IR/BuiltinDialectBytecode.td
    mlir/include/mlir/IR/BuiltinLocationAttributes.td
    mlir/include/mlir/IR/Location.h
    mlir/lib/AsmParser/LocationParser.cpp
    mlir/lib/AsmParser/Parser.h
    mlir/lib/IR/AsmPrinter.cpp
    mlir/lib/IR/BuiltinDialectBytecode.cpp
    mlir/lib/IR/Location.cpp
    mlir/test/IR/locations.mlir

Removed: 
    


################################################################################
diff  --git a/mlir/include/mlir/IR/Builders.h b/mlir/include/mlir/IR/Builders.h
index 6fb71ccefda151..daea2a23d6fbed 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..87da8fd3568fa2 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
-)>;
+  VarInt:$start_line,
+  VarInt:$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..fe4e61100872f2 100644
--- a/mlir/include/mlir/IR/BuiltinLocationAttributes.td
+++ b/mlir/include/mlir/IR/BuiltinLocationAttributes.td
@@ -60,46 +60,98 @@ 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);
+
+  let parameters = (ins "StringAttr":$filename,
+    "unsigned":$start_line, "unsigned":$start_column,
+    "unsigned":$end_line, "unsigned":$end_column);
   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 = [{
+    ::mlir::StringAttr getFilename() const;
+    unsigned getStartLine() const;
+    unsigned getStartColumn() const;
+    unsigned getEndColumn() const;
+    unsigned getEndLine() const;
+  }];
   let skipDefaultBuilders = 1;
-  let attrName = "builtin.file_line_loc";
+  let genAccessors = 0;
+  let genStorageClass = 0;
+  let attrName = "builtin.file_line_range";
 }
 
 //===----------------------------------------------------------------------===//

diff  --git a/mlir/include/mlir/IR/Location.h b/mlir/include/mlir/IR/Location.h
index 5eb1bfaf4afcdc..e206501f5ee6a2 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 4979cfc6e69e41..37670bd789fecb 100644
--- a/mlir/lib/AsmParser/Parser.h
+++ b/mlir/lib/AsmParser/Parser.h
@@ -310,7 +310,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..61b90bc9b0a7bb 100644
--- a/mlir/lib/IR/AsmPrinter.cpp
+++ b/mlir/lib/IR/AsmPrinter.cpp
@@ -2009,12 +2009,23 @@ 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();
+        if (loc.getEndColumn() == loc.getStartColumn() &&
+            loc.getStartLine() == loc.getEndLine()) {
+          os << ':' << loc.getStartLine() << ':' << loc.getStartColumn();
+          return;
+        }
+        if (loc.getStartLine() == loc.getEndLine()) {
+          os << ':' << loc.getStartLine() << ':' << loc.getStartColumn()
+             << " to :" << loc.getEndColumn();
+          return;
+        }
+        os << ':' << loc.getStartLine() << ':' << loc.getStartColumn() << " to "
+           << loc.getEndLine() << ':' << 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..6095c6bcb2ce39 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;
 
@@ -70,8 +73,8 @@ readPotentiallySplatString(DialectBytecodeReader &reader, ShapedType type,
   return success();
 }
 
-void writePotentiallySplatString(DialectBytecodeWriter &writer,
-                                 DenseStringElementsAttr attr) {
+static void writePotentiallySplatString(DialectBytecodeWriter &writer,
+                                        DenseStringElementsAttr attr) {
   bool isSplat = attr.isSplat();
   if (isSplat)
     return writer.writeOwnedString(attr.getRawStringData().front());
@@ -80,6 +83,70 @@ void writePotentiallySplatString(DialectBytecodeWriter &writer,
     writer.writeOwnedString(str);
 }
 
+static 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[2], lineCols[3]);
+  default:
+    return {};
+  }
+}
+
+static LogicalResult
+readFileLineColRangeLocs(DialectBytecodeReader &reader,
+                         SmallVectorImpl<uint64_t> &lineCols) {
+  return reader.readList(
+      lineCols, [&reader](uint64_t &val) { return reader.readVarInt(val); });
+}
+
+static void writeFileLineColRangeLocs(DialectBytecodeWriter &writer,
+                                      FileLineColRange range) {
+  if (range.getStartLine() == 0 && range.getStartColumn() == 0 &&
+      range.getEndLine() == 0 && range.getEndColumn() == 0) {
+    writer.writeVarInt(0);
+    return;
+  }
+  if (range.getStartColumn() == 0 &&
+      range.getStartLine() == range.getEndLine()) {
+    writer.writeVarInt(1);
+    writer.writeVarInt(range.getStartLine());
+    return;
+  }
+  // The single file:line:col is handled by other writer, but checked here for
+  // completeness.
+  if (range.getEndColumn() == range.getStartColumn() &&
+      range.getStartLine() == range.getEndLine()) {
+    writer.writeVarInt(2);
+    writer.writeVarInt(range.getStartLine());
+    writer.writeVarInt(range.getStartColumn());
+    return;
+  }
+  if (range.getStartLine() == range.getEndLine()) {
+    writer.writeVarInt(3);
+    writer.writeVarInt(range.getStartLine());
+    writer.writeVarInt(range.getStartColumn());
+    writer.writeVarInt(range.getEndColumn());
+    return;
+  }
+  writer.writeVarInt(4);
+  writer.writeVarInt(range.getStartLine());
+  writer.writeVarInt(range.getStartColumn());
+  writer.writeVarInt(range.getEndLine());
+  writer.writeVarInt(range.getEndColumn());
+}
+
 #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..ce78d30ee0a526 100644
--- a/mlir/lib/IR/Location.cpp
+++ b/mlir/lib/IR/Location.cpp
@@ -7,31 +7,118 @@
 //===----------------------------------------------------------------------===//
 
 #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>>;
 
-#define GET_ATTRDEF_CLASSES
-#include "mlir/IR/BuiltinLocationAttributes.cpp.inc"
+  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;
+  }
+
+  // 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());
+  }
+
+  unsigned getLineCols(unsigned index) const {
+    return getTrailingObjects<unsigned>()[index - 1];
+  }
+
+  unsigned getStartLine() const { return startLine; }
+  unsigned getStartColumn() const {
+    if (size() <= 1)
+      return 0;
+    return getLineCols(1);
+  }
+  unsigned getEndColumn() const {
+    if (size() <= 2)
+      return getStartColumn();
+    return getLineCols(2);
+  }
+  unsigned getEndLine() const {
+    if (size() <= 3)
+      return getStartLine();
+    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 +153,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();
+}
+
+unsigned FileLineColRange::getStartLine() const {
+  return getImpl()->getStartLine();
+}
+unsigned FileLineColRange::getStartColumn() const {
+  return getImpl()->getStartColumn();
+}
+unsigned FileLineColRange::getEndColumn() const {
+  return getImpl()->getEndColumn();
+}
+unsigned FileLineColRange::getEndLine() const {
+  return getImpl()->getEndLine();
+}
+
 //===----------------------------------------------------------------------===//
 // FusedLoc
 //===----------------------------------------------------------------------===//
@@ -107,3 +247,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..b725307b420b79 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:0)})
+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