From bebdea05ff7ae08007d4238aa3855e8a3c5e2600 Mon Sep 17 00:00:00 2001
From: Ben Gamari <ben@smart-cactus.org>
Date: Thu, 7 Mar 2024 18:09:28 -0500
Subject: [PATCH] IPE: Expose unit ID in InfoTableProv

Here we add the unit ID to the info table provenance structure.
---
 compiler/GHC/StgToCmm/InfoTableProv.hs        | 10 +++--
 libraries/base/changelog.md                   |  1 +
 .../src/GHC/Internal/InfoProv/Types.hsc       |  7 +++-
 rts/IPE.c                                     |  1 +
 rts/Trace.c                                   |  5 ++-
 rts/include/rts/IPE.h                         |  3 +-
 .../interface-stability/base-exports.stdout   |  2 +-
 ...se-exports.stdout-javascript-unknown-ghcjs |  2 +-
 .../base-exports.stdout-mingw32               |  2 +-
 .../base-exports.stdout-ws-32                 |  2 +-
 .../should_run/staticcallstack001.stdout      |  6 +--
 .../should_run/staticcallstack002.stdout      |  8 ++--
 testsuite/tests/rts/ipe/T24005/t24005.stdout  |  4 +-
 testsuite/tests/rts/ipe/ipeEventLog.stderr    | 40 +++++++++----------
 .../tests/rts/ipe/ipeEventLog_fromMap.stderr  | 40 +++++++++----------
 testsuite/tests/rts/ipe/ipeMap.c              |  3 ++
 testsuite/tests/rts/ipe/ipe_lib.c             |  5 +++
 17 files changed, 81 insertions(+), 60 deletions(-)

diff --git a/compiler/GHC/StgToCmm/InfoTableProv.hs b/compiler/GHC/StgToCmm/InfoTableProv.hs
index 6728d73784a3..d62103be90d5 100644
--- a/compiler/GHC/StgToCmm/InfoTableProv.hs
+++ b/compiler/GHC/StgToCmm/InfoTableProv.hs
@@ -83,10 +83,11 @@ emitIpeBufferListNode this_mod ents = do
         platform = stgToCmmPlatform cfg
         int n    = mkIntCLit platform n
 
-        ((cg_ipes, module_name), strtab) = flip runState emptyStringTable $ do
-          module_name <- lookupStringTable $ ST.pack $ renderWithContext ctx (ppr this_mod)
+        ((cg_ipes, unit_id, module_name), strtab) = flip runState emptyStringTable $ do
+          unit_id <- lookupStringTable $ ST.pack $ renderWithContext ctx (ppr $ moduleName this_mod)
+          module_name <- lookupStringTable $ ST.pack $ renderWithContext ctx (ppr $ moduleUnit this_mod)
           cg_ipes <- mapM (toCgIPE platform ctx) ents
-          return (cg_ipes, module_name)
+          return (cg_ipes, unit_id, module_name)
 
         tables :: [CmmStatic]
         tables = map (CmmStaticLit . CmmLabel . ipeInfoTablePtr) cg_ipes
@@ -140,6 +141,9 @@ emitIpeBufferListNode this_mod ents = do
 
             -- 'module_name' field
           , CmmInt (fromIntegral module_name) W32
+
+            -- 'unit_id' field
+          , CmmInt (fromIntegral unit_id) W32
           ]
 
     -- Emit the list of info table pointers
diff --git a/libraries/base/changelog.md b/libraries/base/changelog.md
index 2f77e41d7302..5ffc4d886469 100644
--- a/libraries/base/changelog.md
+++ b/libraries/base/changelog.md
@@ -47,6 +47,7 @@
     matches a `data` or `data instance` declaration) with all of its
     constructors in scope and the levity of `t` is statically known,
     then the constraint `DataToTag t` can always be solved.
+  * `GHC.InfoProv.InfoProv` now provides a `ipUnitId :: String` field encoding the unit ID of the unit defining the info table ([CLC proposal #214](https://github.com/haskell/core-libraries-committee/issues/214))
 
     ([CLC proposal #104](https://github.com/haskell/core-libraries-committee/issues/104))
   * Add `sortOn` to `Data.List.NonEmpty`
diff --git a/libraries/ghc-internal/src/GHC/Internal/InfoProv/Types.hsc b/libraries/ghc-internal/src/GHC/Internal/InfoProv/Types.hsc
index df189bbc9070..ce46ed246e20 100644
--- a/libraries/ghc-internal/src/GHC/Internal/InfoProv/Types.hsc
+++ b/libraries/ghc-internal/src/GHC/Internal/InfoProv/Types.hsc
@@ -35,6 +35,8 @@ data InfoProv = InfoProv {
   ipDesc :: ClosureType,
   ipTyDesc :: String,
   ipLabel :: String,
+  -- | @since base-4.20.0.0
+  ipUnitId :: String,
   ipMod :: String,
   ipSrcFile :: String,
   ipSrcSpan :: String
@@ -67,10 +69,11 @@ getIPE obj fail k = allocaBytes (#size InfoProvEnt) $ \p -> IO $ \s ->
 ipeProv :: Ptr InfoProvEnt -> Ptr InfoProv
 ipeProv p = (#ptr InfoProvEnt, prov) p
 
-peekIpName, peekIpDesc, peekIpLabel, peekIpModule, peekIpSrcFile, peekIpSrcSpan, peekIpTyDesc :: Ptr InfoProv -> IO CString
+peekIpName, peekIpDesc, peekIpLabel, peekIpUnitId, peekIpModule, peekIpSrcFile, peekIpSrcSpan, peekIpTyDesc :: Ptr InfoProv -> IO CString
 peekIpName p    =  (# peek InfoProv, table_name) p
 peekIpDesc p    =  (# peek InfoProv, closure_desc) p
 peekIpLabel p   =  (# peek InfoProv, label) p
+peekIpUnitId p  =  (# peek InfoProv, unit_id) p
 peekIpModule p  =  (# peek InfoProv, module) p
 peekIpSrcFile p =  (# peek InfoProv, src_file) p
 peekIpSrcSpan p =  (# peek InfoProv, src_span) p
@@ -82,6 +85,7 @@ peekInfoProv infop = do
   desc <- peekCString utf8 =<< peekIpDesc infop
   tyDesc <- peekCString utf8 =<< peekIpTyDesc infop
   label <- peekCString utf8 =<< peekIpLabel infop
+  unit_id <- peekCString utf8 =<< peekIpUnitId infop
   mod <- peekCString utf8 =<< peekIpModule infop
   file <- peekCString utf8 =<< peekIpSrcFile infop
   span <- peekCString utf8 =<< peekIpSrcSpan infop
@@ -92,6 +96,7 @@ peekInfoProv infop = do
       ipDesc = maybe INVALID_OBJECT toEnum . readMaybe @Int $ desc,
       ipTyDesc = tyDesc,
       ipLabel = label,
+      ipUnitId = unit_id,
       ipMod = mod,
       ipSrcFile = file,
       ipSrcSpan = span
diff --git a/rts/IPE.c b/rts/IPE.c
index d293ca434fea..7eb78384f7c4 100644
--- a/rts/IPE.c
+++ b/rts/IPE.c
@@ -108,6 +108,7 @@ static InfoProvEnt ipeBufferEntryToIpe(const IpeBufferListNode *node, uint32_t i
                 .closure_desc = &strings[ent->closure_desc],
                 .ty_desc = &strings[ent->ty_desc],
                 .label = &strings[ent->label],
+                .unit_id = &strings[node->unit_id],
                 .module = &strings[node->module_name],
                 .src_file = &strings[ent->src_file],
                 .src_span = &strings[ent->src_span]
diff --git a/rts/Trace.c b/rts/Trace.c
index 7b9843fae30d..956242bcaf8e 100644
--- a/rts/Trace.c
+++ b/rts/Trace.c
@@ -689,9 +689,10 @@ void traceIPE(const InfoProvEnt *ipe)
         ACQUIRE_LOCK(&trace_utx);
 
         tracePreface();
-        debugBelch("IPE: table_name %s, closure_desc %s, ty_desc %s, label %s, module %s, srcloc %s:%s\n",
+        debugBelch("IPE: table_name %s, closure_desc %s, ty_desc %s, label %s, unit %s, module %s, srcloc %s:%s\n",
                    ipe->prov.table_name, ipe->prov.closure_desc, ipe->prov.ty_desc,
-                   ipe->prov.label, ipe->prov.module, ipe->prov.src_file, ipe->prov.src_span);
+                   ipe->prov.label, ipe->prov.unit_id, ipe->prov.module,
+                   ipe->prov.src_file, ipe->prov.src_span);
 
         RELEASE_LOCK(&trace_utx);
     } else
diff --git a/rts/include/rts/IPE.h b/rts/include/rts/IPE.h
index d1e0d3c88ab0..cba97cb640ba 100644
--- a/rts/include/rts/IPE.h
+++ b/rts/include/rts/IPE.h
@@ -18,6 +18,7 @@ typedef struct InfoProv_ {
     const char *closure_desc;
     const char *ty_desc;
     const char *label;
+    const char *unit_id;
     const char *module;
     const char *src_file;
     const char *src_span;
@@ -75,7 +76,6 @@ typedef struct IpeBufferListNode_ {
     // When TNTC is enabled, these will point to the entry code
     // not the info table itself.
     const StgInfoTable **tables;
-
     IpeBufferEntry *entries;
     StgWord entries_size; // decompressed size
 
@@ -83,6 +83,7 @@ typedef struct IpeBufferListNode_ {
     StgWord string_table_size; // decompressed size
 
     // Shared by all entries
+    StringIdx unit_id;
     StringIdx module_name;
 } IpeBufferListNode;
 
diff --git a/testsuite/tests/interface-stability/base-exports.stdout b/testsuite/tests/interface-stability/base-exports.stdout
index f5df15d3eb14..0e4548eecf85 100644
--- a/testsuite/tests/interface-stability/base-exports.stdout
+++ b/testsuite/tests/interface-stability/base-exports.stdout
@@ -8105,7 +8105,7 @@ module GHC.IORef where
 module GHC.InfoProv where
   -- Safety: Safe
   type InfoProv :: *
-  data InfoProv = InfoProv {ipName :: GHC.Internal.Base.String, ipDesc :: GHC.Internal.ClosureTypes.ClosureType, ipTyDesc :: GHC.Internal.Base.String, ipLabel :: GHC.Internal.Base.String, ipMod :: GHC.Internal.Base.String, ipSrcFile :: GHC.Internal.Base.String, ipSrcSpan :: GHC.Internal.Base.String}
+  data InfoProv = InfoProv {ipName :: GHC.Internal.Base.String, ipDesc :: GHC.Internal.ClosureTypes.ClosureType, ipTyDesc :: GHC.Internal.Base.String, ipLabel :: GHC.Internal.Base.String, ipUnitId :: GHC.Internal.Base.String, ipMod :: GHC.Internal.Base.String, ipSrcFile :: GHC.Internal.Base.String, ipSrcSpan :: GHC.Internal.Base.String}
   type InfoProvEnt :: *
   data InfoProvEnt
   ipLoc :: InfoProv -> GHC.Internal.Base.String
diff --git a/testsuite/tests/interface-stability/base-exports.stdout-javascript-unknown-ghcjs b/testsuite/tests/interface-stability/base-exports.stdout-javascript-unknown-ghcjs
index ac9c3ca676df..952c51ca37b5 100644
--- a/testsuite/tests/interface-stability/base-exports.stdout-javascript-unknown-ghcjs
+++ b/testsuite/tests/interface-stability/base-exports.stdout-javascript-unknown-ghcjs
@@ -8074,7 +8074,7 @@ module GHC.IORef where
 module GHC.InfoProv where
   -- Safety: Safe
   type InfoProv :: *
-  data InfoProv = InfoProv {ipName :: GHC.Internal.Base.String, ipDesc :: GHC.Internal.ClosureTypes.ClosureType, ipTyDesc :: GHC.Internal.Base.String, ipLabel :: GHC.Internal.Base.String, ipMod :: GHC.Internal.Base.String, ipSrcFile :: GHC.Internal.Base.String, ipSrcSpan :: GHC.Internal.Base.String}
+  data InfoProv = InfoProv {ipName :: GHC.Internal.Base.String, ipDesc :: GHC.Internal.ClosureTypes.ClosureType, ipTyDesc :: GHC.Internal.Base.String, ipLabel :: GHC.Internal.Base.String, ipUnitId :: GHC.Internal.Base.String, ipMod :: GHC.Internal.Base.String, ipSrcFile :: GHC.Internal.Base.String, ipSrcSpan :: GHC.Internal.Base.String}
   type InfoProvEnt :: *
   data InfoProvEnt
   ipLoc :: InfoProv -> GHC.Internal.Base.String
diff --git a/testsuite/tests/interface-stability/base-exports.stdout-mingw32 b/testsuite/tests/interface-stability/base-exports.stdout-mingw32
index 295e298a3bf6..54dc6fe5d9ef 100644
--- a/testsuite/tests/interface-stability/base-exports.stdout-mingw32
+++ b/testsuite/tests/interface-stability/base-exports.stdout-mingw32
@@ -8329,7 +8329,7 @@ module GHC.IORef where
 module GHC.InfoProv where
   -- Safety: Safe
   type InfoProv :: *
-  data InfoProv = InfoProv {ipName :: GHC.Internal.Base.String, ipDesc :: GHC.Internal.ClosureTypes.ClosureType, ipTyDesc :: GHC.Internal.Base.String, ipLabel :: GHC.Internal.Base.String, ipMod :: GHC.Internal.Base.String, ipSrcFile :: GHC.Internal.Base.String, ipSrcSpan :: GHC.Internal.Base.String}
+  data InfoProv = InfoProv {ipName :: GHC.Internal.Base.String, ipDesc :: GHC.Internal.ClosureTypes.ClosureType, ipTyDesc :: GHC.Internal.Base.String, ipLabel :: GHC.Internal.Base.String, ipUnitId :: GHC.Internal.Base.String, ipMod :: GHC.Internal.Base.String, ipSrcFile :: GHC.Internal.Base.String, ipSrcSpan :: GHC.Internal.Base.String}
   type InfoProvEnt :: *
   data InfoProvEnt
   ipLoc :: InfoProv -> GHC.Internal.Base.String
diff --git a/testsuite/tests/interface-stability/base-exports.stdout-ws-32 b/testsuite/tests/interface-stability/base-exports.stdout-ws-32
index f5df15d3eb14..0e4548eecf85 100644
--- a/testsuite/tests/interface-stability/base-exports.stdout-ws-32
+++ b/testsuite/tests/interface-stability/base-exports.stdout-ws-32
@@ -8105,7 +8105,7 @@ module GHC.IORef where
 module GHC.InfoProv where
   -- Safety: Safe
   type InfoProv :: *
-  data InfoProv = InfoProv {ipName :: GHC.Internal.Base.String, ipDesc :: GHC.Internal.ClosureTypes.ClosureType, ipTyDesc :: GHC.Internal.Base.String, ipLabel :: GHC.Internal.Base.String, ipMod :: GHC.Internal.Base.String, ipSrcFile :: GHC.Internal.Base.String, ipSrcSpan :: GHC.Internal.Base.String}
+  data InfoProv = InfoProv {ipName :: GHC.Internal.Base.String, ipDesc :: GHC.Internal.ClosureTypes.ClosureType, ipTyDesc :: GHC.Internal.Base.String, ipLabel :: GHC.Internal.Base.String, ipUnitId :: GHC.Internal.Base.String, ipMod :: GHC.Internal.Base.String, ipSrcFile :: GHC.Internal.Base.String, ipSrcSpan :: GHC.Internal.Base.String}
   type InfoProvEnt :: *
   data InfoProvEnt
   ipLoc :: InfoProv -> GHC.Internal.Base.String
diff --git a/testsuite/tests/profiling/should_run/staticcallstack001.stdout b/testsuite/tests/profiling/should_run/staticcallstack001.stdout
index abc747dec117..e8d4a332dd7b 100644
--- a/testsuite/tests/profiling/should_run/staticcallstack001.stdout
+++ b/testsuite/tests/profiling/should_run/staticcallstack001.stdout
@@ -1,3 +1,3 @@
-Just (InfoProv {ipName = "D_Main_4_con_info", ipDesc = CONSTR_1_0, ipTyDesc = "D", ipLabel = "main", ipMod = "Main", ipSrcFile = "staticcallstack001.hs", ipSrcSpan = "16:13-27"})
-Just (InfoProv {ipName = "D_Main_2_con_info", ipDesc = CONSTR_1_0, ipTyDesc = "D", ipLabel = "caf", ipMod = "Main", ipSrcFile = "staticcallstack001.hs", ipSrcSpan = "13:1-9"})
-Just (InfoProv {ipName = "sat_s11M_info", ipDesc = THUNK, ipTyDesc = "D", ipLabel = "main", ipMod = "Main", ipSrcFile = "staticcallstack001.hs", ipSrcSpan = "18:23-32"})
+Just (InfoProv {ipName = "D_Main_4_con_info", ipDesc = CONSTR_1_0, ipTyDesc = "D", ipLabel = "main", ipUnitId = "main", ipMod = "Main", ipSrcFile = "staticcallstack001.hs", ipSrcSpan = "16:13-27"})
+Just (InfoProv {ipName = "D_Main_2_con_info", ipDesc = CONSTR_1_0, ipTyDesc = "D", ipLabel = "caf", ipUnitId = "main", ipMod = "Main", ipSrcFile = "staticcallstack001.hs", ipSrcSpan = "13:1-9"})
+Just (InfoProv {ipName = "sat_s23z_info", ipDesc = THUNK, ipTyDesc = "D", ipLabel = "main", ipUnitId = "main", ipMod = "Main", ipSrcFile = "staticcallstack001.hs", ipSrcSpan = "18:23-32"})
diff --git a/testsuite/tests/profiling/should_run/staticcallstack002.stdout b/testsuite/tests/profiling/should_run/staticcallstack002.stdout
index acf38927139c..23219ce31e43 100644
--- a/testsuite/tests/profiling/should_run/staticcallstack002.stdout
+++ b/testsuite/tests/profiling/should_run/staticcallstack002.stdout
@@ -1,4 +1,4 @@
-Just (InfoProv {ipName = "sat_s11p_info", ipDesc = THUNK, ipTyDesc = "Any", ipLabel = "main", ipMod = "Main", ipSrcFile = "staticcallstack002.hs", ipSrcSpan = "10:23-39"})
-Just (InfoProv {ipName = "sat_s11F_info", ipDesc = THUNK, ipTyDesc = "Any", ipLabel = "main", ipMod = "Main", ipSrcFile = "staticcallstack002.hs", ipSrcSpan = "11:23-42"})
-Just (InfoProv {ipName = "sat_s11V_info", ipDesc = THUNK, ipTyDesc = "Any", ipLabel = "main", ipMod = "Main", ipSrcFile = "staticcallstack002.hs", ipSrcSpan = "12:23-46"})
-Just (InfoProv {ipName = "sat_s12b_info", ipDesc = THUNK, ipTyDesc = "Any", ipLabel = "main", ipMod = "Main", ipSrcFile = "staticcallstack002.hs", ipSrcSpan = "13:23-44"})
+Just (InfoProv {ipName = "sat_s237_info", ipDesc = THUNK, ipTyDesc = "Any", ipLabel = "main", ipUnitId = "main", ipMod = "Main", ipSrcFile = "staticcallstack002.hs", ipSrcSpan = "10:23-39"})
+Just (InfoProv {ipName = "sat_s23r_info", ipDesc = THUNK, ipTyDesc = "Any", ipLabel = "main", ipUnitId = "main", ipMod = "Main", ipSrcFile = "staticcallstack002.hs", ipSrcSpan = "11:23-42"})
+Just (InfoProv {ipName = "sat_s23L_info", ipDesc = THUNK, ipTyDesc = "Any", ipLabel = "main", ipUnitId = "main", ipMod = "Main", ipSrcFile = "staticcallstack002.hs", ipSrcSpan = "12:23-46"})
+Just (InfoProv {ipName = "sat_s245_info", ipDesc = THUNK, ipTyDesc = "Any", ipLabel = "main", ipUnitId = "main", ipMod = "Main", ipSrcFile = "staticcallstack002.hs", ipSrcSpan = "13:23-44"})
diff --git a/testsuite/tests/rts/ipe/T24005/t24005.stdout b/testsuite/tests/rts/ipe/T24005/t24005.stdout
index c3fb55f09823..91d50c8fc44f 100644
--- a/testsuite/tests/rts/ipe/T24005/t24005.stdout
+++ b/testsuite/tests/rts/ipe/T24005/t24005.stdout
@@ -1,2 +1,2 @@
-Just (InfoProv {ipName = "C:Show_Main_1_con_info", ipDesc = CONSTR, ipTyDesc = "Show", ipLabel = "$fShowA", ipMod = "Main", ipSrcFile = "t24005.hs", ipSrcSpan = "25:10-15"})
-Just (InfoProv {ipName = "C:Show_Main_0_con_info", ipDesc = CONSTR, ipTyDesc = "Show", ipLabel = "$fShowB", ipMod = "Main", ipSrcFile = "t24005.hs", ipSrcSpan = "29:10-29"})
+Just (InfoProv {ipName = "C:Show_Main_1_con_info", ipDesc = CONSTR, ipTyDesc = "Show", ipLabel = "$fShowA", ipUnitId = "main", ipMod = "Main", ipSrcFile = "t24005.hs", ipSrcSpan = "25:10-15"})
+Just (InfoProv {ipName = "C:Show_Main_0_con_info", ipDesc = CONSTR, ipTyDesc = "Show", ipLabel = "$fShowB", ipUnitId = "main", ipMod = "Main", ipSrcFile = "t24005.hs", ipSrcSpan = "29:10-29"})
diff --git a/testsuite/tests/rts/ipe/ipeEventLog.stderr b/testsuite/tests/rts/ipe/ipeEventLog.stderr
index a9d0995bb381..982b938cd498 100644
--- a/testsuite/tests/rts/ipe/ipeEventLog.stderr
+++ b/testsuite/tests/rts/ipe/ipeEventLog.stderr
@@ -1,20 +1,20 @@
-7ffff7a4d740: IPE: table_name table_name_000, closure_desc closure_desc_000, ty_desc ty_desc_000, label label_000, module module_000, srcloc src_file_000:src_span_000
-7ffff7a4d740: IPE: table_name table_name_001, closure_desc closure_desc_001, ty_desc ty_desc_001, label label_001, module module_000, srcloc src_file_001:src_span_001
-7ffff7a4d740: IPE: table_name table_name_002, closure_desc closure_desc_002, ty_desc ty_desc_002, label label_002, module module_000, srcloc src_file_002:src_span_002
-7ffff7a4d740: IPE: table_name table_name_003, closure_desc closure_desc_003, ty_desc ty_desc_003, label label_003, module module_000, srcloc src_file_003:src_span_003
-7ffff7a4d740: IPE: table_name table_name_004, closure_desc closure_desc_004, ty_desc ty_desc_004, label label_004, module module_000, srcloc src_file_004:src_span_004
-7ffff7a4d740: IPE: table_name table_name_005, closure_desc closure_desc_005, ty_desc ty_desc_005, label label_005, module module_000, srcloc src_file_005:src_span_005
-7ffff7a4d740: IPE: table_name table_name_006, closure_desc closure_desc_006, ty_desc ty_desc_006, label label_006, module module_000, srcloc src_file_006:src_span_006
-7ffff7a4d740: IPE: table_name table_name_007, closure_desc closure_desc_007, ty_desc ty_desc_007, label label_007, module module_000, srcloc src_file_007:src_span_007
-7ffff7a4d740: IPE: table_name table_name_008, closure_desc closure_desc_008, ty_desc ty_desc_008, label label_008, module module_000, srcloc src_file_008:src_span_008
-7ffff7a4d740: IPE: table_name table_name_009, closure_desc closure_desc_009, ty_desc ty_desc_009, label label_009, module module_000, srcloc src_file_009:src_span_009
-7ffff7a4d740: IPE: table_name table_name_000, closure_desc closure_desc_000, ty_desc ty_desc_000, label label_000, module module_000, srcloc src_file_000:src_span_000
-7ffff7a4d740: IPE: table_name table_name_001, closure_desc closure_desc_001, ty_desc ty_desc_001, label label_001, module module_000, srcloc src_file_001:src_span_001
-7ffff7a4d740: IPE: table_name table_name_002, closure_desc closure_desc_002, ty_desc ty_desc_002, label label_002, module module_000, srcloc src_file_002:src_span_002
-7ffff7a4d740: IPE: table_name table_name_003, closure_desc closure_desc_003, ty_desc ty_desc_003, label label_003, module module_000, srcloc src_file_003:src_span_003
-7ffff7a4d740: IPE: table_name table_name_004, closure_desc closure_desc_004, ty_desc ty_desc_004, label label_004, module module_000, srcloc src_file_004:src_span_004
-7ffff7a4d740: IPE: table_name table_name_005, closure_desc closure_desc_005, ty_desc ty_desc_005, label label_005, module module_000, srcloc src_file_005:src_span_005
-7ffff7a4d740: IPE: table_name table_name_006, closure_desc closure_desc_006, ty_desc ty_desc_006, label label_006, module module_000, srcloc src_file_006:src_span_006
-7ffff7a4d740: IPE: table_name table_name_007, closure_desc closure_desc_007, ty_desc ty_desc_007, label label_007, module module_000, srcloc src_file_007:src_span_007
-7ffff7a4d740: IPE: table_name table_name_008, closure_desc closure_desc_008, ty_desc ty_desc_008, label label_008, module module_000, srcloc src_file_008:src_span_008
-7ffff7a4d740: IPE: table_name table_name_009, closure_desc closure_desc_009, ty_desc ty_desc_009, label label_009, module module_000, srcloc src_file_009:src_span_009
+7ffff7a4d740: IPE: table_name table_name_000, closure_desc closure_desc_000, ty_desc ty_desc_000, label label_000, unit unit_id_000, module module_000, srcloc src_file_000:src_span_000
+7ffff7a4d740: IPE: table_name table_name_001, closure_desc closure_desc_001, ty_desc ty_desc_001, label label_001, unit unit_id_000, module module_000, srcloc src_file_001:src_span_001
+7ffff7a4d740: IPE: table_name table_name_002, closure_desc closure_desc_002, ty_desc ty_desc_002, label label_002, unit unit_id_000, module module_000, srcloc src_file_002:src_span_002
+7ffff7a4d740: IPE: table_name table_name_003, closure_desc closure_desc_003, ty_desc ty_desc_003, label label_003, unit unit_id_000, module module_000, srcloc src_file_003:src_span_003
+7ffff7a4d740: IPE: table_name table_name_004, closure_desc closure_desc_004, ty_desc ty_desc_004, label label_004, unit unit_id_000, module module_000, srcloc src_file_004:src_span_004
+7ffff7a4d740: IPE: table_name table_name_005, closure_desc closure_desc_005, ty_desc ty_desc_005, label label_005, unit unit_id_000, module module_000, srcloc src_file_005:src_span_005
+7ffff7a4d740: IPE: table_name table_name_006, closure_desc closure_desc_006, ty_desc ty_desc_006, label label_006, unit unit_id_000, module module_000, srcloc src_file_006:src_span_006
+7ffff7a4d740: IPE: table_name table_name_007, closure_desc closure_desc_007, ty_desc ty_desc_007, label label_007, unit unit_id_000, module module_000, srcloc src_file_007:src_span_007
+7ffff7a4d740: IPE: table_name table_name_008, closure_desc closure_desc_008, ty_desc ty_desc_008, label label_008, unit unit_id_000, module module_000, srcloc src_file_008:src_span_008
+7ffff7a4d740: IPE: table_name table_name_009, closure_desc closure_desc_009, ty_desc ty_desc_009, label label_009, unit unit_id_000, module module_000, srcloc src_file_009:src_span_009
+7ffff7a4d740: IPE: table_name table_name_000, closure_desc closure_desc_000, ty_desc ty_desc_000, label label_000, unit unit_id_000, module module_000, srcloc src_file_000:src_span_000
+7ffff7a4d740: IPE: table_name table_name_001, closure_desc closure_desc_001, ty_desc ty_desc_001, label label_001, unit unit_id_000, module module_000, srcloc src_file_001:src_span_001
+7ffff7a4d740: IPE: table_name table_name_002, closure_desc closure_desc_002, ty_desc ty_desc_002, label label_002, unit unit_id_000, module module_000, srcloc src_file_002:src_span_002
+7ffff7a4d740: IPE: table_name table_name_003, closure_desc closure_desc_003, ty_desc ty_desc_003, label label_003, unit unit_id_000, module module_000, srcloc src_file_003:src_span_003
+7ffff7a4d740: IPE: table_name table_name_004, closure_desc closure_desc_004, ty_desc ty_desc_004, label label_004, unit unit_id_000, module module_000, srcloc src_file_004:src_span_004
+7ffff7a4d740: IPE: table_name table_name_005, closure_desc closure_desc_005, ty_desc ty_desc_005, label label_005, unit unit_id_000, module module_000, srcloc src_file_005:src_span_005
+7ffff7a4d740: IPE: table_name table_name_006, closure_desc closure_desc_006, ty_desc ty_desc_006, label label_006, unit unit_id_000, module module_000, srcloc src_file_006:src_span_006
+7ffff7a4d740: IPE: table_name table_name_007, closure_desc closure_desc_007, ty_desc ty_desc_007, label label_007, unit unit_id_000, module module_000, srcloc src_file_007:src_span_007
+7ffff7a4d740: IPE: table_name table_name_008, closure_desc closure_desc_008, ty_desc ty_desc_008, label label_008, unit unit_id_000, module module_000, srcloc src_file_008:src_span_008
+7ffff7a4d740: IPE: table_name table_name_009, closure_desc closure_desc_009, ty_desc ty_desc_009, label label_009, unit unit_id_000, module module_000, srcloc src_file_009:src_span_009
diff --git a/testsuite/tests/rts/ipe/ipeEventLog_fromMap.stderr b/testsuite/tests/rts/ipe/ipeEventLog_fromMap.stderr
index 4c94fe5393b4..f2c32287da2e 100644
--- a/testsuite/tests/rts/ipe/ipeEventLog_fromMap.stderr
+++ b/testsuite/tests/rts/ipe/ipeEventLog_fromMap.stderr
@@ -1,20 +1,20 @@
-7ffff7a4d740: IPE: table_name table_name_009, closure_desc closure_desc_009, ty_desc ty_desc_009, label label_009, module module_000, srcloc src_file_009:src_span_009
-7ffff7a4d740: IPE: table_name table_name_008, closure_desc closure_desc_008, ty_desc ty_desc_008, label label_008, module module_000, srcloc src_file_008:src_span_008
-7ffff7a4d740: IPE: table_name table_name_007, closure_desc closure_desc_007, ty_desc ty_desc_007, label label_007, module module_000, srcloc src_file_007:src_span_007
-7ffff7a4d740: IPE: table_name table_name_006, closure_desc closure_desc_006, ty_desc ty_desc_006, label label_006, module module_000, srcloc src_file_006:src_span_006
-7ffff7a4d740: IPE: table_name table_name_005, closure_desc closure_desc_005, ty_desc ty_desc_005, label label_005, module module_000, srcloc src_file_005:src_span_005
-7ffff7a4d740: IPE: table_name table_name_004, closure_desc closure_desc_004, ty_desc ty_desc_004, label label_004, module module_000, srcloc src_file_004:src_span_004
-7ffff7a4d740: IPE: table_name table_name_003, closure_desc closure_desc_003, ty_desc ty_desc_003, label label_003, module module_000, srcloc src_file_003:src_span_003
-7ffff7a4d740: IPE: table_name table_name_002, closure_desc closure_desc_002, ty_desc ty_desc_002, label label_002, module module_000, srcloc src_file_002:src_span_002
-7ffff7a4d740: IPE: table_name table_name_001, closure_desc closure_desc_001, ty_desc ty_desc_001, label label_001, module module_000, srcloc src_file_001:src_span_001
-7ffff7a4d740: IPE: table_name table_name_000, closure_desc closure_desc_000, ty_desc ty_desc_000, label label_000, module module_000, srcloc src_file_000:src_span_000
-7ffff7a4d740: IPE: table_name table_name_009, closure_desc closure_desc_009, ty_desc ty_desc_009, label label_009, module module_000, srcloc src_file_009:src_span_009
-7ffff7a4d740: IPE: table_name table_name_008, closure_desc closure_desc_008, ty_desc ty_desc_008, label label_008, module module_000, srcloc src_file_008:src_span_008
-7ffff7a4d740: IPE: table_name table_name_007, closure_desc closure_desc_007, ty_desc ty_desc_007, label label_007, module module_000, srcloc src_file_007:src_span_007
-7ffff7a4d740: IPE: table_name table_name_006, closure_desc closure_desc_006, ty_desc ty_desc_006, label label_006, module module_000, srcloc src_file_006:src_span_006
-7ffff7a4d740: IPE: table_name table_name_005, closure_desc closure_desc_005, ty_desc ty_desc_005, label label_005, module module_000, srcloc src_file_005:src_span_005
-7ffff7a4d740: IPE: table_name table_name_004, closure_desc closure_desc_004, ty_desc ty_desc_004, label label_004, module module_000, srcloc src_file_004:src_span_004
-7ffff7a4d740: IPE: table_name table_name_003, closure_desc closure_desc_003, ty_desc ty_desc_003, label label_003, module module_000, srcloc src_file_003:src_span_003
-7ffff7a4d740: IPE: table_name table_name_002, closure_desc closure_desc_002, ty_desc ty_desc_002, label label_002, module module_000, srcloc src_file_002:src_span_002
-7ffff7a4d740: IPE: table_name table_name_001, closure_desc closure_desc_001, ty_desc ty_desc_001, label label_001, module module_000, srcloc src_file_001:src_span_001
-7ffff7a4d740: IPE: table_name table_name_000, closure_desc closure_desc_000, ty_desc ty_desc_000, label label_000, module module_000, srcloc src_file_000:src_span_000
+7ffff7a4d740: IPE: table_name table_name_009, closure_desc closure_desc_009, ty_desc ty_desc_009, label label_009, unit unit_id_000, module module_000, srcloc src_file_009:src_span_009
+7ffff7a4d740: IPE: table_name table_name_008, closure_desc closure_desc_008, ty_desc ty_desc_008, label label_008, unit unit_id_000, module module_000, srcloc src_file_008:src_span_008
+7ffff7a4d740: IPE: table_name table_name_007, closure_desc closure_desc_007, ty_desc ty_desc_007, label label_007, unit unit_id_000, module module_000, srcloc src_file_007:src_span_007
+7ffff7a4d740: IPE: table_name table_name_006, closure_desc closure_desc_006, ty_desc ty_desc_006, label label_006, unit unit_id_000, module module_000, srcloc src_file_006:src_span_006
+7ffff7a4d740: IPE: table_name table_name_005, closure_desc closure_desc_005, ty_desc ty_desc_005, label label_005, unit unit_id_000, module module_000, srcloc src_file_005:src_span_005
+7ffff7a4d740: IPE: table_name table_name_004, closure_desc closure_desc_004, ty_desc ty_desc_004, label label_004, unit unit_id_000, module module_000, srcloc src_file_004:src_span_004
+7ffff7a4d740: IPE: table_name table_name_003, closure_desc closure_desc_003, ty_desc ty_desc_003, label label_003, unit unit_id_000, module module_000, srcloc src_file_003:src_span_003
+7ffff7a4d740: IPE: table_name table_name_002, closure_desc closure_desc_002, ty_desc ty_desc_002, label label_002, unit unit_id_000, module module_000, srcloc src_file_002:src_span_002
+7ffff7a4d740: IPE: table_name table_name_001, closure_desc closure_desc_001, ty_desc ty_desc_001, label label_001, unit unit_id_000, module module_000, srcloc src_file_001:src_span_001
+7ffff7a4d740: IPE: table_name table_name_000, closure_desc closure_desc_000, ty_desc ty_desc_000, label label_000, unit unit_id_000, module module_000, srcloc src_file_000:src_span_000
+7ffff7a4d740: IPE: table_name table_name_009, closure_desc closure_desc_009, ty_desc ty_desc_009, label label_009, unit unit_id_000, module module_000, srcloc src_file_009:src_span_009
+7ffff7a4d740: IPE: table_name table_name_008, closure_desc closure_desc_008, ty_desc ty_desc_008, label label_008, unit unit_id_000, module module_000, srcloc src_file_008:src_span_008
+7ffff7a4d740: IPE: table_name table_name_007, closure_desc closure_desc_007, ty_desc ty_desc_007, label label_007, unit unit_id_000, module module_000, srcloc src_file_007:src_span_007
+7ffff7a4d740: IPE: table_name table_name_006, closure_desc closure_desc_006, ty_desc ty_desc_006, label label_006, unit unit_id_000, module module_000, srcloc src_file_006:src_span_006
+7ffff7a4d740: IPE: table_name table_name_005, closure_desc closure_desc_005, ty_desc ty_desc_005, label label_005, unit unit_id_000, module module_000, srcloc src_file_005:src_span_005
+7ffff7a4d740: IPE: table_name table_name_004, closure_desc closure_desc_004, ty_desc ty_desc_004, label label_004, unit unit_id_000, module module_000, srcloc src_file_004:src_span_004
+7ffff7a4d740: IPE: table_name table_name_003, closure_desc closure_desc_003, ty_desc ty_desc_003, label label_003, unit unit_id_000, module module_000, srcloc src_file_003:src_span_003
+7ffff7a4d740: IPE: table_name table_name_002, closure_desc closure_desc_002, ty_desc ty_desc_002, label label_002, unit unit_id_000, module module_000, srcloc src_file_002:src_span_002
+7ffff7a4d740: IPE: table_name table_name_001, closure_desc closure_desc_001, ty_desc ty_desc_001, label label_001, unit unit_id_000, module module_000, srcloc src_file_001:src_span_001
+7ffff7a4d740: IPE: table_name table_name_000, closure_desc closure_desc_000, ty_desc ty_desc_000, label label_000, unit unit_id_000, module module_000, srcloc src_file_000:src_span_000
diff --git a/testsuite/tests/rts/ipe/ipeMap.c b/testsuite/tests/rts/ipe/ipeMap.c
index a1d8db0296a2..53c8654f19dd 100644
--- a/testsuite/tests/rts/ipe/ipeMap.c
+++ b/testsuite/tests/rts/ipe/ipeMap.c
@@ -53,6 +53,7 @@ HaskellObj shouldFindOneIfItHasBeenRegistered(Capability *cap) {
     StringTable st;
     init_string_table(&st);
 
+    node->unit_id = add_string(&st, "unit-id");
     node->module_name = add_string(&st, "TheModule");
 
     HaskellObj fortyTwo = UNTAG_CLOSURE(rts_mkInt(cap, 42));
@@ -73,6 +74,7 @@ HaskellObj shouldFindOneIfItHasBeenRegistered(Capability *cap) {
     assertStringsEqual(result.prov.closure_desc, "closure_desc_042");
     assertStringsEqual(result.prov.ty_desc, "ty_desc_042");
     assertStringsEqual(result.prov.label, "label_042");
+    assertStringsEqual(result.prov.unit_id, "unit-id");
     assertStringsEqual(result.prov.module, "TheModule");
     assertStringsEqual(result.prov.src_file, "src_file_042");
     assertStringsEqual(result.prov.src_span, "src_span_042");
@@ -90,6 +92,7 @@ void shouldFindTwoIfTwoHaveBeenRegistered(Capability *cap,
     StringTable st;
     init_string_table(&st);
 
+    node->unit_id = add_string(&st, "unit-id");
     node->module_name = add_string(&st, "TheModule");
 
     HaskellObj twentyThree = UNTAG_CLOSURE(rts_mkInt8(cap, 23));
diff --git a/testsuite/tests/rts/ipe/ipe_lib.c b/testsuite/tests/rts/ipe/ipe_lib.c
index b07ee8b2b252..2e2df8c4367c 100644
--- a/testsuite/tests/rts/ipe/ipe_lib.c
+++ b/testsuite/tests/rts/ipe/ipe_lib.c
@@ -72,6 +72,11 @@ IpeBufferListNode *makeAnyProvEntries(Capability *cap, int start, int end) {
     StringTable st;
     init_string_table(&st);
 
+    unsigned int unitIdLength = strlen("unit_id_") + 3 /* digits */ + 1 /* null character */;
+    char *unitId = malloc(sizeof(char) * unitIdLength);
+    snprintf(unitId, unitIdLength, "unit_id_%03i", start);
+    node->unit_id = add_string(&st, unitId);
+
     unsigned int moduleLength = strlen("module_") + 3 /* digits */ + 1 /* null character */;
     char *module = malloc(sizeof(char) * moduleLength);
     snprintf(module, moduleLength, "module_%03i", start);
-- 
GitLab