[llvm] [TableGen] Include source location in JSON dump (PR #79028)

via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 24 06:49:30 PST 2024


https://github.com/ostannard updated https://github.com/llvm/llvm-project/pull/79028

>From 538c588569a11826eb9571e0b7e56f3f3cb3117a Mon Sep 17 00:00:00 2001
From: Oliver Stannard <oliver.stannard at arm.com>
Date: Mon, 22 Jan 2024 17:13:43 +0000
Subject: [PATCH 1/2] [TableGen] Include source location in JSON dump

This adds a '!loc' field to each record containing the file name and
line number of the record declaration.
---
 llvm/lib/TableGen/JSONBackend.cpp | 2 ++
 llvm/test/TableGen/JSON.td        | 2 ++
 2 files changed, 4 insertions(+)

diff --git a/llvm/lib/TableGen/JSONBackend.cpp b/llvm/lib/TableGen/JSONBackend.cpp
index 2a3f522a9c0ef2f..9b489cf7deddbe4 100644
--- a/llvm/lib/TableGen/JSONBackend.cpp
+++ b/llvm/lib/TableGen/JSONBackend.cpp
@@ -15,6 +15,7 @@
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/JSON.h"
+#include "llvm/TableGen/Error.h"
 #include "llvm/TableGen/Record.h"
 
 #define DEBUG_TYPE "json-emitter"
@@ -158,6 +159,7 @@ void JSONEmitter::run(raw_ostream &OS) {
 
     obj["!name"] = Name;
     obj["!anonymous"] = Def.isAnonymous();
+    obj["!loc"] = SrcMgr.getFormattedLocationNoOffset(Def.getLoc().front());
 
     root[Name] = std::move(obj);
 
diff --git a/llvm/test/TableGen/JSON.td b/llvm/test/TableGen/JSON.td
index 3fb2ec4014fbcd2..20d3c0fcc131989 100644
--- a/llvm/test/TableGen/JSON.td
+++ b/llvm/test/TableGen/JSON.td
@@ -3,12 +3,14 @@
 // CHECK: data['!tablegen_json_version'] == 1
 
 // CHECK: all(data[s]['!name'] == s for s in data if not s.startswith("!"))
+// CHECK: all(data[s]['!loc'].startswith("JSON.td:") for s in data if not s.startswith("!"))
 
 class Base {}
 class Intermediate : Base {}
 class Derived : Intermediate {}
 
 def D : Intermediate {}
+// CHECK: data['D']['!loc'] == 'JSON.td:12'
 // CHECK: 'D' in data['!instanceof']['Base']
 // CHECK: 'D' in data['!instanceof']['Intermediate']
 // CHECK: 'D' not in data['!instanceof']['Derived']

>From e39b4d7b2c433388242d575283301fbdb31e27cc Mon Sep 17 00:00:00 2001
From: Oliver Stannard <oliver.stannard at arm.com>
Date: Wed, 24 Jan 2024 14:45:04 +0000
Subject: [PATCH 2/2] Emit an array of source locations for multiclasses

---
 llvm/docs/TableGen/BackEnds.rst   |  6 +++++
 llvm/lib/TableGen/JSONBackend.cpp |  6 ++++-
 llvm/test/TableGen/JSON-locs.td   | 44 +++++++++++++++++++++++++++++++
 llvm/test/TableGen/JSON.td        |  5 ++--
 4 files changed, 58 insertions(+), 3 deletions(-)
 create mode 100644 llvm/test/TableGen/JSON-locs.td

diff --git a/llvm/docs/TableGen/BackEnds.rst b/llvm/docs/TableGen/BackEnds.rst
index 5cbb3232ef02387..742fea51bcf32be 100644
--- a/llvm/docs/TableGen/BackEnds.rst
+++ b/llvm/docs/TableGen/BackEnds.rst
@@ -506,6 +506,12 @@ following fixed keys:
   specified by the TableGen input (if it is ``false``), or invented by
   TableGen itself (if ``true``).
 
+* ``!locs``: an array of strings giving the source locations associated with
+  this record. For records instantiated from a ``multiclass``, this gives the
+  location of each ``def`` or ``defm``, starting with the inner-most
+  ``multiclass``, and ending with the top-level ``defm``. Each string contains
+  the file name and line number, separated by a colon.
+
 For each variable defined in a record, the ``def`` object for that
 record also has a key for the variable name. The corresponding value
 is a translation into JSON of the variable's value, using the
diff --git a/llvm/lib/TableGen/JSONBackend.cpp b/llvm/lib/TableGen/JSONBackend.cpp
index 9b489cf7deddbe4..cd10c22094e45bf 100644
--- a/llvm/lib/TableGen/JSONBackend.cpp
+++ b/llvm/lib/TableGen/JSONBackend.cpp
@@ -159,7 +159,11 @@ void JSONEmitter::run(raw_ostream &OS) {
 
     obj["!name"] = Name;
     obj["!anonymous"] = Def.isAnonymous();
-    obj["!loc"] = SrcMgr.getFormattedLocationNoOffset(Def.getLoc().front());
+
+    json::Array locs;
+    for (const SMLoc Loc : Def.getLoc())
+      locs.push_back(SrcMgr.getFormattedLocationNoOffset(Loc));
+    obj["!locs"] = std::move(locs);
 
     root[Name] = std::move(obj);
 
diff --git a/llvm/test/TableGen/JSON-locs.td b/llvm/test/TableGen/JSON-locs.td
new file mode 100644
index 000000000000000..38baf4693148904
--- /dev/null
+++ b/llvm/test/TableGen/JSON-locs.td
@@ -0,0 +1,44 @@
+// RUN: llvm-tblgen -dump-json %s | %python %S/JSON-check.py %s
+
+def Simple {}
+// CHECK: data['Simple']['!locs'] == ['JSON-locs.td:3']
+
+multiclass Multiclass1 {
+  def Instance1 {}
+  def Instance2 {}
+}
+
+defm DefM1 : Multiclass1;
+
+// CHECK: data['DefM1Instance1']['!locs'] == ['JSON-locs.td:7', 'JSON-locs.td:11']
+// CHECK: data['DefM1Instance2']['!locs'] == ['JSON-locs.td:8', 'JSON-locs.td:11']
+
+multiclass Multiclass2 {
+  def Instance3 {}
+  def Instance4 {}
+}
+
+defm DefM2 : Multiclass1, Multiclass2;
+// CHECK: data['DefM2Instance1']['!locs'] == ['JSON-locs.td:7', 'JSON-locs.td:21']
+// CHECK: data['DefM2Instance2']['!locs'] == ['JSON-locs.td:8', 'JSON-locs.td:21']
+// CHECK: data['DefM2Instance3']['!locs'] == ['JSON-locs.td:17', 'JSON-locs.td:21']
+// CHECK: data['DefM2Instance4']['!locs'] == ['JSON-locs.td:18', 'JSON-locs.td:21']
+
+multiclass Multiclass3 {
+  defm InnerDefM : Multiclass1;
+  def Instance5 {}
+}
+
+defm DefM3: Multiclass3;
+// CHECK: data['DefM3InnerDefMInstance1']['!locs'] == ['JSON-locs.td:7', 'JSON-locs.td:28', 'JSON-locs.td:32']
+// CHECK: data['DefM3InnerDefMInstance2']['!locs'] == ['JSON-locs.td:8', 'JSON-locs.td:28', 'JSON-locs.td:32']
+// CHECK: data['DefM3Instance5']['!locs'] == ['JSON-locs.td:29', 'JSON-locs.td:32']
+
+class BaseClass {}
+class DerivedClass : BaseClass {}
+// Classes do not appear in the JSON, so do not get locations.
+// CHECK: 'BaseClass' not in data
+// CHECK: 'DerivedClass' not in data
+
+def ClassInstance : DerivedClass {}
+// CHECK: data['ClassInstance']['!locs'] == ['JSON-locs.td:43']
diff --git a/llvm/test/TableGen/JSON.td b/llvm/test/TableGen/JSON.td
index 20d3c0fcc131989..4d8c3a466bfd072 100644
--- a/llvm/test/TableGen/JSON.td
+++ b/llvm/test/TableGen/JSON.td
@@ -3,14 +3,15 @@
 // CHECK: data['!tablegen_json_version'] == 1
 
 // CHECK: all(data[s]['!name'] == s for s in data if not s.startswith("!"))
-// CHECK: all(data[s]['!loc'].startswith("JSON.td:") for s in data if not s.startswith("!"))
+// CHECK: all('!locs' in data[s] for s in data if not s.startswith("!"))
+// CHECK: all(all(loc.startswith("JSON.td:") for loc in data[s]['!locs']) for s in data if not s.startswith("!"))
 
 class Base {}
 class Intermediate : Base {}
 class Derived : Intermediate {}
 
 def D : Intermediate {}
-// CHECK: data['D']['!loc'] == 'JSON.td:12'
+// CHECK: data['D']['!locs'] == ['JSON.td:13']
 // CHECK: 'D' in data['!instanceof']['Base']
 // CHECK: 'D' in data['!instanceof']['Intermediate']
 // CHECK: 'D' not in data['!instanceof']['Derived']



More information about the llvm-commits mailing list