Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RemoveDIs] Add flag to preserve the debug info format of input IR #87379

Merged
merged 3 commits into from
Apr 5, 2024

Conversation

SLTozer
Copy link
Contributor

@SLTozer SLTozer commented Apr 2, 2024

This patch adds a new flag: --preserve-input-debuginfo-format

This flag instructs the tool to not convert the debug info format (intrinsics/records) of input IR, but to instead determine the format of the input IR and overwrite the other format-determining flags so that we process and output the file in the same format that we received it in. This flag is turned off by llvm-link, llvm-lto, and llvm-lto2, and should be turned off by any other tool that expects to parse multiple IR modules and have their debug info formats match.

The motivation for this flag is to allow tools to not convert the debug info format - verify-uselistorder and llvm-reduce, and any downstream tools that seek to test or mutate IR as-is, without applying extraneous modifications to the input. This is a necessary step to using debug records by default in all (other) LLVM tools.

The implementation of this flag may not be to everyone's liking - setting it to "true" directly overwrites the value of the flags:

--experimental-debuginfo-iterators
--write-experimental-debuginfo
--write-experimental-debuginfo-iterators-to-bitcode

The reason for this approach is that when we pass this new flag, we're intending to override any effect that those flags could actually have on the IR; this could be done by adding a check at every site where those flags are used, but I'm planning to rewrite or remove those flags soon, so this method avoids updating the same set of code twice without a functional change; if modifying the flag values is a problem though, then this can be rewritten.

This patch adds a new flag: --preserve-input-debuginfo-format

This flag instructs the tool to not convert the debug info format
(intrinsics/records), but to instead determine the format of the input IR
and override the other format-determining flags so that we process and
output the file in the same format that we received it in. This flag is
turned off by llvm-link, llvm-lto, and llvm-lto2, and should be turned off
by any other tool that expects to parse multiple IR files.

The motivation for this flag is to allow us to use debug records by default
in all LLVM tools except for those that have an interest in not converting
the debug info format - verify-uselistorder and llvm-reduce, and any
downstream tools that seek to test or mutate IR as-is, without applying
extraneous modifications to the input.

The implementation of this flag may not be to everyone's liking - setting
it to "true" directly modifies the value of the flags:
  --experimental-debuginfo-iterators
  --write-experimental-debuginfo
  --write-experimental-debuginfo-iterators-to-bitcode
The reason for this approach is that when we pass this new flag, we're
intending to override any effect that those flags might actually have; this
could be done by adding a check at every site where those flags are used,
but I'm planning to rewrite or remove those flags soon, so this method
avoids updating the same sets of code twice without a functional change; if
modifying the flag values is a problem though, then this can be rewritten.
@llvmbot
Copy link
Collaborator

llvmbot commented Apr 3, 2024

@llvm/pr-subscribers-llvm-ir

@llvm/pr-subscribers-debuginfo

Author: Stephen Tozer (SLTozer)

Changes

This patch adds a new flag: --preserve-input-debuginfo-format

This flag instructs the tool to not convert the debug info format (intrinsics/records) of input IR, but to instead determine the format of the input IR and overwrite the other format-determining flags so that we process and output the file in the same format that we received it in. This flag is turned off by llvm-link, llvm-lto, and llvm-lto2, and should be turned off by any other tool that expects to parse multiple IR modules and have their debug info formats match.

The motivation for this flag is to allow tools to not convert the debug info format - verify-uselistorder and llvm-reduce, and any downstream tools that seek to test or mutate IR as-is, without applying extraneous modifications to the input. This is a necessary step to using debug records by default in all (other) LLVM tools.

The implementation of this flag may not be to everyone's liking - setting it to "true" directly overwrites the value of the flags:

--experimental-debuginfo-iterators
--write-experimental-debuginfo
--write-experimental-debuginfo-iterators-to-bitcode

The reason for this approach is that when we pass this new flag, we're intending to override any effect that those flags could actually have on the IR; this could be done by adding a check at every site where those flags are used, but I'm planning to rewrite or remove those flags soon, so this method avoids updating the same set of code twice without a functional change; if modifying the flag values is a problem though, then this can be rewritten.


Patch is 24.09 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/87379.diff

15 Files Affected:

  • (modified) llvm/include/llvm/AsmParser/LLParser.h (+1)
  • (modified) llvm/include/llvm/IR/AutoUpgrade.h (+2-1)
  • (modified) llvm/include/llvm/IR/BasicBlock.h (+3-3)
  • (modified) llvm/include/llvm/IR/Function.h (+3-3)
  • (modified) llvm/include/llvm/IR/Module.h (+7-7)
  • (modified) llvm/lib/AsmParser/LLParser.cpp (+20-7)
  • (modified) llvm/lib/Bitcode/Reader/BitcodeReader.cpp (+57-13)
  • (modified) llvm/lib/IR/AutoUpgrade.cpp (+8-4)
  • (modified) llvm/lib/IR/BasicBlock.cpp (+16-6)
  • (modified) llvm/lib/IR/Function.cpp (+7-7)
  • (modified) llvm/test/Bitcode/dbg-record-roundtrip.ll (+10)
  • (modified) llvm/test/DebugInfo/roundtrip-non-instruction-debug-info.ll (+8)
  • (modified) llvm/tools/llvm-link/llvm-link.cpp (+5)
  • (modified) llvm/tools/llvm-lto/llvm-lto.cpp (+5)
  • (modified) llvm/tools/llvm-lto2/llvm-lto2.cpp (+5)
diff --git a/llvm/include/llvm/AsmParser/LLParser.h b/llvm/include/llvm/AsmParser/LLParser.h
index 8ebd0d3409c899..b4e971fea1a139 100644
--- a/llvm/include/llvm/AsmParser/LLParser.h
+++ b/llvm/include/llvm/AsmParser/LLParser.h
@@ -335,6 +335,7 @@ namespace llvm {
 
     // Top-Level Entities
     bool parseTopLevelEntities();
+    bool finalizeDebugInfoFormat(Module *M);
     void dropUnknownMetadataReferences();
     bool validateEndOfModule(bool UpgradeDebugInfo);
     bool validateEndOfIndex();
diff --git a/llvm/include/llvm/IR/AutoUpgrade.h b/llvm/include/llvm/IR/AutoUpgrade.h
index 152f781ffa9b30..97c3e4d7589d7b 100644
--- a/llvm/include/llvm/IR/AutoUpgrade.h
+++ b/llvm/include/llvm/IR/AutoUpgrade.h
@@ -36,7 +36,8 @@ namespace llvm {
   /// for upgrading, and returns true if it requires upgrading. It may return
   /// null in NewFn if the all calls to the original intrinsic function
   /// should be transformed to non-function-call instructions.
-  bool UpgradeIntrinsicFunction(Function *F, Function *&NewFn);
+  bool UpgradeIntrinsicFunction(Function *F, Function *&NewFn,
+                                bool CanUpgradeDebugIntrinsicsToRecords = true);
 
   /// This is the complement to the above, replacing a specific call to an
   /// intrinsic function with a call to the specified new function.
diff --git a/llvm/include/llvm/IR/BasicBlock.h b/llvm/include/llvm/IR/BasicBlock.h
index 0eea4cdccca5bb..f14d5d92da72de 100644
--- a/llvm/include/llvm/IR/BasicBlock.h
+++ b/llvm/include/llvm/IR/BasicBlock.h
@@ -81,17 +81,17 @@ class BasicBlock final : public Value, // Basic blocks are data objects also
   /// intrinsics into DbgMarkers / DbgRecords. Deletes all dbg.values in
   /// the process and sets IsNewDbgInfoFormat = true. Only takes effect if
   /// the UseNewDbgInfoFormat LLVM command line option is given.
-  void convertToNewDbgValues();
+  void convertToNewDbgValues(bool UpdateFlagOnly = false);
 
   /// Convert variable location debugging information stored in DbgMarkers and
   /// DbgRecords into the dbg.value intrinsic representation. Sets
   /// IsNewDbgInfoFormat = false.
-  void convertFromNewDbgValues();
+  void convertFromNewDbgValues(bool UpdateFlagOnly = false);
 
   /// Ensure the block is in "old" dbg.value format (\p NewFlag == false) or
   /// in the new format (\p NewFlag == true), converting to the desired format
   /// if necessary.
-  void setIsNewDbgInfoFormat(bool NewFlag);
+  void setIsNewDbgInfoFormat(bool NewFlag, bool UpdateFlagOnly = false);
 
   /// Record that the collection of DbgRecords in \p M "trails" after the last
   /// instruction of this block. These are equivalent to dbg.value intrinsics
diff --git a/llvm/include/llvm/IR/Function.h b/llvm/include/llvm/IR/Function.h
index d96d506a9b05d0..8c881f38748fdc 100644
--- a/llvm/include/llvm/IR/Function.h
+++ b/llvm/include/llvm/IR/Function.h
@@ -114,12 +114,12 @@ class LLVM_EXTERNAL_VISIBILITY Function : public GlobalObject,
   }
 
   /// \see BasicBlock::convertToNewDbgValues.
-  void convertToNewDbgValues();
+  void convertToNewDbgValues(bool UpdateFlagOnly = false);
 
   /// \see BasicBlock::convertFromNewDbgValues.
-  void convertFromNewDbgValues();
+  void convertFromNewDbgValues(bool UpdateFlagOnly = false);
 
-  void setIsNewDbgInfoFormat(bool NewVal);
+  void setIsNewDbgInfoFormat(bool NewVal, bool UpdateFlagOnly = false);
 
 private:
   friend class TargetLibraryInfoImpl;
diff --git a/llvm/include/llvm/IR/Module.h b/llvm/include/llvm/IR/Module.h
index bb2e667ef6f410..bc3986140f0b9a 100644
--- a/llvm/include/llvm/IR/Module.h
+++ b/llvm/include/llvm/IR/Module.h
@@ -224,26 +224,26 @@ class LLVM_EXTERNAL_VISIBILITY Module {
   void removeDebugIntrinsicDeclarations();
 
   /// \see BasicBlock::convertToNewDbgValues.
-  void convertToNewDbgValues() {
+  void convertToNewDbgValues(bool UpdateFlagOnly = false) {
     for (auto &F : *this) {
-      F.convertToNewDbgValues();
+      F.convertToNewDbgValues(UpdateFlagOnly);
     }
     IsNewDbgInfoFormat = true;
   }
 
   /// \see BasicBlock::convertFromNewDbgValues.
-  void convertFromNewDbgValues() {
+  void convertFromNewDbgValues(bool UpdateFlagOnly = false) {
     for (auto &F : *this) {
-      F.convertFromNewDbgValues();
+      F.convertFromNewDbgValues(UpdateFlagOnly);
     }
     IsNewDbgInfoFormat = false;
   }
 
-  void setIsNewDbgInfoFormat(bool UseNewFormat) {
+  void setIsNewDbgInfoFormat(bool UseNewFormat, bool UpdateFlagOnly = false) {
     if (UseNewFormat && !IsNewDbgInfoFormat)
-      convertToNewDbgValues();
+      convertToNewDbgValues(UpdateFlagOnly);
     else if (!UseNewFormat && IsNewDbgInfoFormat)
-      convertFromNewDbgValues();
+      convertFromNewDbgValues(UpdateFlagOnly);
   }
 
   /// The Module constructor. Note that there is no default constructor. You
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index f0be021668afa7..70a6ef864f5656 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -63,6 +63,9 @@ static cl::opt<bool> AllowIncompleteIR(
         "metadata will be dropped)"));
 
 extern llvm::cl::opt<bool> UseNewDbgInfoFormat;
+extern cl::opt<cl::boolOrDefault> PreserveInputDbgFormat;
+extern bool WriteNewDbgInfoFormatToBitcode;
+extern cl::opt<bool> WriteNewDbgInfoFormat;
 
 static std::string getTypeString(Type *T) {
   std::string Result;
@@ -71,12 +74,20 @@ static std::string getTypeString(Type *T) {
   return Tmp.str();
 }
 
-// Currently, we should always process modules in the old debug info format by
-// default regardless of the module's format in IR; convert it to the old format
-// here.
-bool finalizeDebugInfoFormat(Module *M) {
-  if (M)
+// Whatever debug info format we parsed, we should convert to the expected debug
+// info format immediately afterwards.
+bool LLParser::finalizeDebugInfoFormat(Module *M) {
+  // We should have already returned an error if we observed both intrinsics and
+  // records in this IR.
+  assert(!(SeenNewDbgInfoFormat && SeenOldDbgInfoFormat) &&
+         "Mixed debug intrinsics/records seen without a parsing error?");
+  if (PreserveInputDbgFormat == cl::boolOrDefault::BOU_TRUE) {
+    UseNewDbgInfoFormat = SeenNewDbgInfoFormat;
+    WriteNewDbgInfoFormatToBitcode = SeenNewDbgInfoFormat;
+    WriteNewDbgInfoFormat = SeenNewDbgInfoFormat;
+  } else if (M) {
     M->setIsNewDbgInfoFormat(false);
+  }
   return false;
 }
 
@@ -6507,10 +6518,10 @@ bool LLParser::parseBasicBlock(PerFunctionState &PFS) {
       if (SeenOldDbgInfoFormat)
         return error(Lex.getLoc(), "debug record should not appear in a module "
                                    "containing debug info intrinsics");
+      if (!SeenNewDbgInfoFormat)
+        M->setIsNewDbgInfoFormat(true, true);
       SeenNewDbgInfoFormat = true;
       Lex.Lex();
-      if (!M->IsNewDbgInfoFormat)
-        M->convertToNewDbgValues();
 
       DbgRecord *DR;
       if (parseDebugRecord(DR, PFS))
@@ -7912,6 +7923,8 @@ bool LLParser::parseCall(Instruction *&Inst, PerFunctionState &PFS,
       return error(CallLoc, "llvm.dbg intrinsic should not appear in a module "
                             "using non-intrinsic debug info");
     }
+    if (!SeenOldDbgInfoFormat)
+      M->setIsNewDbgInfoFormat(false, true);
     SeenOldDbgInfoFormat = true;
   }
   CI->setAttributes(PAL);
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index 6ee93f17792b4f..5d92d8bed061b3 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -108,6 +108,9 @@ cl::opt<cl::boolOrDefault> LoadBitcodeIntoNewDbgInfoFormat(
     "load-bitcode-into-experimental-debuginfo-iterators", cl::Hidden,
     cl::desc("Load bitcode directly into the new debug info format (regardless "
              "of input format)"));
+extern cl::opt<cl::boolOrDefault> PreserveInputDbgFormat;
+extern bool WriteNewDbgInfoFormatToBitcode;
+extern cl::opt<bool> WriteNewDbgInfoFormat;
 
 namespace {
 
@@ -682,6 +685,11 @@ class BitcodeReader : public BitcodeReaderBase, public GVMaterializer {
   /// (e.g.) blockaddress forward references.
   bool WillMaterializeAllForwardRefs = false;
 
+  /// Tracks whether we have seen debug intrinsics or records in this bitcode;
+  /// seeing both in a single module is currently a fatal error.
+  bool SeenDebugIntrinsic = false;
+  bool SeenDebugRecord = false;
+
   bool StripDebugInfo = false;
   TBAAVerifier TBAAVerifyHelper;
 
@@ -3774,7 +3782,11 @@ Error BitcodeReader::globalCleanup() {
   for (Function &F : *TheModule) {
     MDLoader->upgradeDebugIntrinsics(F);
     Function *NewFn;
-    if (UpgradeIntrinsicFunction(&F, NewFn))
+    // If PreserveInputDbgFormat=true, then we don't know whether we want
+    // intrinsics or records, and we won't perform any conversions in either
+    // case, so don't upgrade intrinsics to records.
+    if (UpgradeIntrinsicFunction(
+            &F, NewFn, PreserveInputDbgFormat != cl::boolOrDefault::BOU_TRUE))
       UpgradedIntrinsics[&F] = NewFn;
     // Look for functions that rely on old function attribute behavior.
     UpgradeFunctionAttributes(F);
@@ -4301,10 +4313,13 @@ Error BitcodeReader::parseModule(uint64_t ResumeBit,
                                  bool ShouldLazyLoadMetadata,
                                  ParserCallbacks Callbacks) {
   // Load directly into RemoveDIs format if LoadBitcodeIntoNewDbgInfoFormat
-  // has been set to true (default action: load into the old debug format).
-  TheModule->IsNewDbgInfoFormat =
-      UseNewDbgInfoFormat &&
-      LoadBitcodeIntoNewDbgInfoFormat == cl::boolOrDefault::BOU_TRUE;
+  // has been set to true and we aren't attempting to preserve the existing
+  // format in the bitcode (default action: load into the old debug format).
+  if (PreserveInputDbgFormat != cl::boolOrDefault::BOU_TRUE) {
+    TheModule->IsNewDbgInfoFormat =
+        UseNewDbgInfoFormat &&
+        LoadBitcodeIntoNewDbgInfoFormat == cl::boolOrDefault::BOU_TRUE;
+  }
 
   this->ValueTypeCallback = std::move(Callbacks.ValueType);
   if (ResumeBit) {
@@ -6443,6 +6458,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
     case bitc::FUNC_CODE_DEBUG_RECORD_ASSIGN: {
       // DbgVariableRecords are placed after the Instructions that they are
       // attached to.
+      SeenDebugRecord = true;
       Instruction *Inst = getLastInstruction();
       if (!Inst)
         return error("Invalid dbg record: missing instruction");
@@ -6603,6 +6619,8 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
         TCK = CallInst::TCK_NoTail;
       cast<CallInst>(I)->setTailCallKind(TCK);
       cast<CallInst>(I)->setAttributes(PAL);
+      if (isa<DbgInfoIntrinsic>(I))
+        SeenDebugIntrinsic = true;
       if (Error Err = propagateAttributeTypes(cast<CallBase>(I), ArgTyIDs)) {
         I->deleteValue();
         return Err;
@@ -6791,20 +6809,46 @@ Error BitcodeReader::materialize(GlobalValue *GV) {
   if (Error JumpFailed = Stream.JumpToBit(DFII->second))
     return JumpFailed;
 
-  // Set the debug info mode to "new", possibly creating a mismatch between
-  // module and function debug modes. This is okay because we'll convert
-  // everything back to the old mode after parsing if needed.
-  // FIXME: Remove this once all tools support RemoveDIs.
+  // Regardless of the debug info format we want to end up in, we need
+  // IsNewDbgInfoFormat=true to construct any debug records seen in the bitcode.
   F->IsNewDbgInfoFormat = true;
 
   if (Error Err = parseFunctionBody(F))
     return Err;
   F->setIsMaterializable(false);
 
-  // Convert new debug info records into intrinsics.
-  // FIXME: Remove this once all tools support RemoveDIs.
-  if (!F->getParent()->IsNewDbgInfoFormat)
-    F->convertFromNewDbgValues();
+  // All parsed Functions should load into the debug info format dictated by the
+  // Module, unless we're attempting to preserve the input debug info format.
+  if (SeenDebugIntrinsic && SeenDebugRecord)
+    return error("Mixed debug intrinsics and debug records in bitcode module!");
+  if (PreserveInputDbgFormat == cl::boolOrDefault::BOU_TRUE) {
+    bool SeenAnyDebugInfo = SeenDebugIntrinsic || SeenDebugRecord;
+    bool NewDbgInfoFormatDesired =
+        SeenAnyDebugInfo ? SeenDebugRecord : F->getParent()->IsNewDbgInfoFormat;
+    if (SeenAnyDebugInfo) {
+      UseNewDbgInfoFormat = SeenDebugRecord;
+      WriteNewDbgInfoFormatToBitcode = SeenDebugRecord;
+      WriteNewDbgInfoFormat = SeenDebugRecord;
+    }
+    // If the module's debug info format doesn't match the observed input
+    // format, then set its format now; we don't need to call the conversion
+    // function because there must be no existing intrinsics to convert.
+    // Otherwise, just set the format on this function now.
+    if (NewDbgInfoFormatDesired != F->getParent()->IsNewDbgInfoFormat)
+      F->getParent()->setIsNewDbgInfoFormat(NewDbgInfoFormatDesired, true);
+    else
+      F->setIsNewDbgInfoFormat(NewDbgInfoFormatDesired, true);
+  } else {
+    // If we aren't preserving formats, we use the Module flag to get our
+    // desired format instead of reading flags, in case we are lazy-loading and
+    // the format of the module has been changed since it was set by the flags.
+    // We only need to convert debug info here if we have debug records but
+    // desire the intrinsic format; everything else is a no-op or handled by the
+    // autoupgrader.
+    bool ModuleIsNewDbgInfoFormat = F->getParent()->IsNewDbgInfoFormat;
+    F->setIsNewDbgInfoFormat(ModuleIsNewDbgInfoFormat,
+                             ModuleIsNewDbgInfoFormat || !SeenDebugRecord);
+  }
 
   if (StripDebugInfo)
     stripDebugInfo(*F);
diff --git a/llvm/lib/IR/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp
index a44f6af4162f03..dc0b7347e4fe4e 100644
--- a/llvm/lib/IR/AutoUpgrade.cpp
+++ b/llvm/lib/IR/AutoUpgrade.cpp
@@ -983,7 +983,8 @@ static Intrinsic::ID shouldUpgradeNVPTXBF16Intrinsic(StringRef Name) {
   return Intrinsic::not_intrinsic;
 }
 
-static bool upgradeIntrinsicFunction1(Function *F, Function *&NewFn) {
+static bool upgradeIntrinsicFunction1(Function *F, Function *&NewFn,
+                                      bool CanUpgradeDebugIntrinsicsToRecords) {
   assert(F && "Illegal to upgrade a non-existent Function.");
 
   StringRef Name = F->getName();
@@ -1057,7 +1058,8 @@ static bool upgradeIntrinsicFunction1(Function *F, Function *&NewFn) {
   case 'd':
     if (Name.consume_front("dbg.")) {
       // Mark debug intrinsics for upgrade to new debug format.
-      if (F->getParent()->IsNewDbgInfoFormat) {
+      if (CanUpgradeDebugIntrinsicsToRecords &&
+          F->getParent()->IsNewDbgInfoFormat) {
         if (Name == "addr" || Name == "value" || Name == "assign" ||
             Name == "declare" || Name == "label") {
           // There's no function to replace these with.
@@ -1413,9 +1415,11 @@ static bool upgradeIntrinsicFunction1(Function *F, Function *&NewFn) {
   return false;
 }
 
-bool llvm::UpgradeIntrinsicFunction(Function *F, Function *&NewFn) {
+bool llvm::UpgradeIntrinsicFunction(Function *F, Function *&NewFn,
+                                    bool CanUpgradeDebugIntrinsicsToRecords) {
   NewFn = nullptr;
-  bool Upgraded = upgradeIntrinsicFunction1(F, NewFn);
+  bool Upgraded =
+      upgradeIntrinsicFunction1(F, NewFn, CanUpgradeDebugIntrinsicsToRecords);
   assert(F != NewFn && "Intrinsic function upgraded to the same function");
 
   // Upgrade intrinsic attributes.  This does not change the function.
diff --git a/llvm/lib/IR/BasicBlock.cpp b/llvm/lib/IR/BasicBlock.cpp
index f088c7a2cc4e77..3bb0f423f270ca 100644
--- a/llvm/lib/IR/BasicBlock.cpp
+++ b/llvm/lib/IR/BasicBlock.cpp
@@ -35,6 +35,12 @@ cl::opt<bool>
                         cl::desc("Enable communicating debuginfo positions "
                                  "through iterators, eliminating intrinsics"),
                         cl::init(true));
+cl::opt<cl::boolOrDefault> PreserveInputDbgFormat(
+    "preserve-input-debuginfo-format", cl::Hidden,
+    cl::desc("When set to true, IR files will be processed and printed in "
+             "their current debug info format, regardless of default behaviour "
+             "or other flags passed. Has no effect if input IR does not "
+             "contain debug records or intrinsics."));
 
 bool WriteNewDbgInfoFormatToBitcode /*set default value in cl::init() below*/;
 cl::opt<bool, true> WriteNewDbgInfoFormatToBitcode2(
@@ -65,8 +71,10 @@ DbgMarker *BasicBlock::createMarker(InstListType::iterator It) {
   return DM;
 }
 
-void BasicBlock::convertToNewDbgValues() {
+void BasicBlock::convertToNewDbgValues(bool UpdateFlagOnly) {
   IsNewDbgInfoFormat = true;
+  if (UpdateFlagOnly)
+    return;
 
   // Iterate over all instructions in the instruction list, collecting debug
   // info intrinsics and converting them to DbgRecords. Once we find a "real"
@@ -104,9 +112,11 @@ void BasicBlock::convertToNewDbgValues() {
   }
 }
 
-void BasicBlock::convertFromNewDbgValues() {
-  invalidateOrders();
+void BasicBlock::convertFromNewDbgValues(bool UpdateFlagOnly) {
   IsNewDbgInfoFormat = false;
+  if (UpdateFlagOnly)
+    return;
+  invalidateOrders();
 
   // Iterate over the block, finding instructions annotated with DbgMarkers.
   // Convert any attached DbgRecords to debug intrinsics and insert ahead of the
@@ -141,11 +151,11 @@ void BasicBlock::dumpDbgValues() const {
 }
 #endif
 
-void BasicBlock::setIsNewDbgInfoFormat(bool NewFlag) {
+void BasicBlock::setIsNewDbgInfoFormat(bool NewFlag, bool UpdateFlagOnly) {
   if (NewFlag && !IsNewDbgInfoFormat)
-    convertToNewDbgValues();
+    convertToNewDbgValues(UpdateFlagOnly);
   else if (!NewFlag && IsNewDbgInfoFormat)
-    convertFromNewDbgValues();
+    convertFromNewDbgValues(UpdateFlagOnly);
 }
 
 ValueSymbolTable *BasicBlock::getValueSymbolTable() {
diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp
index eb126f182eadcb..953977ca33ed40 100644
--- a/llvm/lib/IR/Function.cpp
+++ b/llvm/lib/IR/Function.cpp
@@ -83,25 +83,25 @@ static cl::opt<unsigned> NonGlobalValueMaxNameSize(
     "non-global-value-max-name-size", cl::Hidden, cl::init(1024),
     cl::desc("Maximum size for the name of non-global values."));
 
-void Function::convertToNewDbgValues() {
+void Function::convertToNewDbgValues(bool UpdateFlagOnly) {
   IsNewDbgInfoFormat = true;
   for (auto &BB : *this) {
-    BB.convertToNewDbgValues();
+    BB.convertToNewDbgValues(UpdateFlagOnly);
   }
 }
 
-void Function::convertFromNewDbgValues() {
+void Function::convertFromNewDbgValues(bool UpdateFlagOnly) {
   IsNewDbgInfoFormat = false;
   for (auto &BB : *this) {
-    BB.convertFromNewDbgValues();
+    BB.convertFromNewDbgValues(UpdateFlagOnly);
   }
 }
 
-void Function::setIsNewDbgInfoFormat(bool NewFlag) {
+void Function::setIsNewDbgInfoFormat(bool NewFlag, bool UpdateFlagOnly) {
   if (NewFlag && !IsNewDbgInfoFormat)
-    convertToNewDbgValues();
+    convertToNewDbgValues(UpdateFlagOnly);
   else if (!NewFlag && IsNewDbgInfoFormat)
-    convertFromNewDbgValues();
+    convertFromNewDbgValues(UpdateFlagOnly);
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/llvm/test/Bitcode/dbg-record-roundtrip.ll b/llvm/test/Bitcode/dbg-record-roundtrip.ll
index bd347cac720677..cc83fdd4fa5381 100644
--- a/llvm/test/Bitcode/dbg-record-roundtrip.ll
+++ b/llvm/test/Bitcode/dbg-record-roundtrip.ll
@@ -15,6 +15,16 @@
 ; RUN: | llvm-dis --load-bitcode-into-experimental-debuginfo-iterators=true --write-experimental-debuginfo=true \
 ; RUN: | FileCheck %s --check-prefixes=RECORDS
 
+;; When preserving, we should output the format the bitcode was written in
+;; regardless of the value of the write flag.
+; RUN: llvm-as --write-experimental-debuginfo-iterators-to-bitcode=true %s -o - \
+; RUN: | llvm-dis --preserve-input-debuginfo-format=true --write-experimental-debuginfo=false \
+; RUN: | FileCheck %s --check-prefixes=RECORDS
+
+; RUN: llvm-as --write-experimental-debuginfo-iterators-to-bitcode=false %s -o - \
+; RUN: | llvm-dis --preserve-input-debuginfo-format=true --write-experimental-debuginfo=true \
+; RUN: | FileCheck %s
+
 ;; Check that verify-uselistorder passes regardless of input format.
 ; RUN: llvm-as %s --write-experimental-debuginfo-iterators-to-bitcode=true -o - | verify-uselistorder
 ; RUN: verify-uselistorder %s
diff --git a/llvm/test/DebugInfo/round...
[truncated]

Copy link
Contributor

@OCHyams OCHyams left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree this functionality is needed. Meddling with the other flags so far from initialisation feels a little sketchy - I feel like it could easily become confusing and/or buggy.

We discussed offline the possibility of a --experimental-debuginfo-iterators=[always|never|input] flag, and that might involve more invasive checks all over the place. Are there any other alternatives?

e.g. I wonder if this should be a flag at all. Would it make sense for this to just be a (non-flag) global that llvm-reduce and llvm-verifyuselistorder opt into unconditionally?

@@ -36,7 +36,8 @@ namespace llvm {
/// for upgrading, and returns true if it requires upgrading. It may return
/// null in NewFn if the all calls to the original intrinsic function
/// should be transformed to non-function-call instructions.
bool UpgradeIntrinsicFunction(Function *F, Function *&NewFn);
bool UpgradeIntrinsicFunction(Function *F, Function *&NewFn,
bool CanUpgradeDebugIntrinsicsToRecords = true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leaked in from another pull request?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, this part is used in this patch in BitcodeReader.cpp:3789, to avoid upgrading debug intrinsics to records specifically when we have the preserve flag enabled.

@@ -81,17 +81,17 @@ class BasicBlock final : public Value, // Basic blocks are data objects also
/// intrinsics into DbgMarkers / DbgRecords. Deletes all dbg.values in
/// the process and sets IsNewDbgInfoFormat = true. Only takes effect if
/// the UseNewDbgInfoFormat LLVM command line option is given.
void convertToNewDbgValues();
void convertToNewDbgValues(bool UpdateFlagOnly = false);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit of a nit, but something about having the additional UpdateFlagOnly param in these (and the other similar) functions feels slightly off. I think a separate function would signal intent more clearly that only a flag is changing. YMMV. If you prefer to keep the new parameter, please can you add a doc-comment describing its purpose?

This "offness" might be solved by simply adding inline comments to the call sites , e.g. convertToNewDbgValues(true, /*UpdateFlagOnly=*/true).

wdyt?

Copy link
Contributor Author

@SLTozer SLTozer Apr 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a separate function would signal intent more clearly that only a flag is changing.

This is probably fine - one of the reasons for making it a parameter rather than a function was that in one of the cases here, we're using a non-constant as the argument here (i.e. /*UpdateFlagOnly=*/ ModuleIsNewDbgInfoFormat || !SeenDebugRecord); this can easily be changed to an if-else though.

cl::desc("When set to true, IR files will be processed and printed in "
"their current debug info format, regardless of default behaviour "
"or other flags passed. Has no effect if input IR does not "
"contain debug records or intrinsics."));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"ignored in llvm-link, llvm-lto, llvm-lto2"

@SLTozer
Copy link
Contributor Author

SLTozer commented Apr 4, 2024

e.g. I wonder if this should be a flag at all. Would it make sense for this to just be a (non-flag) global that llvm-reduce and llvm-verifyuselistorder opt into unconditionally?

Main reason this is a flag rather than just an internal global is that it should be user controllable - for llvm-reduce at least it's generally desirable to maintain format, but may not always be intended. Aside from that, it will be a flag-controllable feature later on (as you mentioned), so it seems sensible to introduce it as such now.

Copy link
Contributor

@OCHyams OCHyams left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aside from that, it will be a flag-controllable feature later on (as you mentioned), so it seems sensible to introduce it as such now.

If we're definitely moving in that direction, towards a unified flag, then I think this could be an acceptable stepping stone.

Can you add comments (and update any flag description text if there is any) for the other flags explaining that they get overridden by this one?

LoadBitcodeIntoNewDbgInfoFormat == cl::boolOrDefault::BOU_TRUE;
// has been set to true and we aren't attempting to preserve the existing
// format in the bitcode (default action: load into the old debug format).
if (PreserveInputDbgFormat != cl::boolOrDefault::BOU_TRUE) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why isn't this == cl::boolOrDefault::BOU_TRUE?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The intent is that if we're preserving the input format, then we don't want to update TheModule->IsNewDbgInfoFormat according to the rule below. It could all be folded into a boolean expression, but I think that might obfuscate the meaning.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I think I see where my confusion comes in, TheModule->IsNewDbgInfoFormat is currently always false. Is this patch intended to land after the "set IsNewDbgInfoFormat in Module ctor based on UseNewDbgInfoFormat" patch (alternatively: is your reply above intended to be true after that patch lands, even if this one lands first)?

Otherwise, without the module-ctor-patch, the default behaviour becomes convert all inputs into intrinsic mode (because of the code down on line 6842). Or am I misreading this situation?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't require the ctor change; the behaviour is that:

  • If we aren't preserving inputs, then we follow the existing behaviour - we set IsNewDbgInfoFormat according to the UseNewDbgInfoFormat and LoadBitcodeIntoNewDbgInfoFormat flags, and then when we materialize the function we either 1) convert any existing records to intrinsics via the call to setIsNewDbgInfoFormat on line 6849, or 2) convert any existing intrinsics to records during autoupgrading, depending on whether we're loading into the new format or not.
  • If we are preserving inputs, then we never convert between intrinsics and records at any point - we insert records/intrinsics as we materialize the function, and then we set the IsNewDbgInfoFormat flag on the module and its functions once we've determined what format the input was in.

@llvmbot llvmbot added the llvm:ir label Apr 5, 2024
Copy link
Contributor

@OCHyams OCHyams left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I think this is the only outstanding comment:

Can you add comments (and update any flag description text if there is any) for the other flags explaining that they get overridden by this one?

LGTM with that done

@SLTozer SLTozer merged commit 379628d into llvm:main Apr 5, 2024
3 of 4 checks passed
@mikaelholmen
Copy link
Collaborator

Hello @SLTozer
With this patch, the following starts crashing:

clang -cc1 -emit-llvm-bc -debug-info-kind=constructor -o bbi-94196.bc bbi-94196.c
opt bbi-94196.bc -o bbi-94196.opt.bc

It results in

opt: ../lib/IR/BasicBlock.cpp:85: void llvm::BasicBlock::convertToNewDbgValues(): Assertion `!I.DebugMarker && "DebugMarker already set on old-format instrs?"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.	Program arguments: build-all/bin/opt bbi-94196.bc -o bbi-94196.opt.bc
 #0 0x0000558b7a61d537 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (build-all/bin/opt+0x3e1e537)
 #1 0x0000558b7a61b00e llvm::sys::RunSignalHandlers() (build-all/bin/opt+0x3e1c00e)
 #2 0x0000558b7a61deff SignalHandler(int) Signals.cpp:0:0
 #3 0x00007f7429cfb630 __restore_rt sigaction.c:0:0
 #4 0x00007f7427442387 raise (/lib64/libc.so.6+0x36387)
 #5 0x00007f7427443a78 abort (/lib64/libc.so.6+0x37a78)
 #6 0x00007f742743b1a6 __assert_fail_base (/lib64/libc.so.6+0x2f1a6)
 #7 0x00007f742743b252 (/lib64/libc.so.6+0x2f252)
 #8 0x0000558b7a75f32a llvm::BasicBlock::convertToNewDbgValues() (build-all/bin/opt+0x3f6032a)
 #9 0x0000558b7a74df5e llvm::Function::convertToNewDbgValues() (build-all/bin/opt+0x3f4ef5e)
#10 0x0000558b7a69309e llvm::Module::setIsNewDbgInfoFormat(bool) IRPrintingPasses.cpp:0:0
#11 0x0000558b7a7ff61d llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (build-all/bin/opt+0x400061d)
#12 0x0000558b7b8ce33b llvm::runPassPipeline(llvm::StringRef, llvm::Module&, llvm::TargetMachine*, llvm::TargetLibraryInfoImpl*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::StringRef, llvm::ArrayRef<llvm::PassPlugin>, llvm::ArrayRef<std::function<void (llvm::PassBuilder&)>>, llvm::opt_tool::OutputKind, llvm::opt_tool::VerifierKind, bool, bool, bool, bool, bool, bool, bool) (build-all/bin/opt+0x50cf33b)
#13 0x0000558b7a5e5aad optMain (build-all/bin/opt+0x3de6aad)
#14 0x00007f742742e555 __libc_start_main (/lib64/libc.so.6+0x22555)
#15 0x0000558b7a5df629 _start (build-all/bin/opt+0x3de0629)
Abort (core dumped)

bbi-94196.c.gz

@nathanchance
Copy link
Member

I am seeing a similar crash when building the Linux kernel for arm64 after this change, although I only see it when LTO is enabled, so it may or may not be the exact same problem as above?

struct hc_driver {
  int (*urb_dequeue)();
};
static int isp1760_hc_setup() {
  unsigned val = ({
    ({
      for (;;)
        ;
      val;
    });
  });
}
void isp1760_irq() {
  goto leave;
leave:;
}
struct hc_driver isp1760_hc_driver = {isp1760_hc_setup};
$ clang --target=aarch64-linux-gnu -flto=thin -g -c -o object isp1760-hcd.i

$ llvm-ar cDPrST archive object

$ ld.lld -EL -maarch64elf -z norelro -z noexecstack -r -o /dev/null --whole-archive archive
ld.lld: /home/nathan/tmp/cvise.L3dhxztcjp/src/llvm/lib/IR/BasicBlock.cpp:85: void llvm::BasicBlock::convertToNewDbgValues(): Assertion `!I.DebugMarker && "DebugMarker already set on old-format instrs?"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
 #0 0x0000000001a06bbc llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/home/nathan/tmp/cvise.L3dhxztcjp/install/llvm-bad/bin/lld+0x1a06bbc)
 #1 0x0000000001a04a64 llvm::sys::RunSignalHandlers() (/home/nathan/tmp/cvise.L3dhxztcjp/install/llvm-bad/bin/lld+0x1a04a64)
 #2 0x0000000001a07640 SignalHandler(int) Signals.cpp:0:0
 #3 0x0000ffffa82127f0 (linux-vdso.so.1+0x7f0)
 #4 0x0000ffffa7bd85a0 __pthread_kill_implementation (/lib64/libc.so.6+0x985a0)
 #5 0x0000ffffa7b859c0 gsignal (/lib64/libc.so.6+0x459c0)
 #6 0x0000ffffa7b70288 abort (/lib64/libc.so.6+0x30288)
 #7 0x0000ffffa7b7e3c0 __assert_fail_base (/lib64/libc.so.6+0x3e3c0)
 #8 0x0000ffffa7b7e434 (/lib64/libc.so.6+0x3e434)
 #9 0x0000000004019900 llvm::BasicBlock::convertToNewDbgValues() (/home/nathan/tmp/cvise.L3dhxztcjp/install/llvm-bad/bin/lld+0x4019900)
#10 0x00000000040df1b4 llvm::Function::convertToNewDbgValues() (/home/nathan/tmp/cvise.L3dhxztcjp/install/llvm-bad/bin/lld+0x40df1b4)
#11 0x0000000002aef8c0 llvm::Module::setIsNewDbgInfoFormat(bool) MIRPrinter.cpp:0:0
#12 0x000000000417a264 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/home/nathan/tmp/cvise.L3dhxztcjp/install/llvm-bad/bin/lld+0x417a264)
#13 0x000000000276dc44 llvm::lto::opt(llvm::lto::Config const&, llvm::TargetMachine*, unsigned int, llvm::Module&, bool, llvm::ModuleSummaryIndex*, llvm::ModuleSummaryIndex const*, std::vector<unsigned char, std::allocator<unsigned char>> const&) (/home/nathan/tmp/cvise.L3dhxztcjp/install/llvm-bad/bin/lld+0x276dc44)
#14 0x0000000002770074 llvm::lto::thinBackend(llvm::lto::Config const&, unsigned int, std::function<llvm::Expected<std::unique_ptr<llvm::CachedFileStream, std::default_delete<llvm::CachedFileStream>>> (unsigned int, llvm::Twine const&)>, llvm::Module&, llvm::ModuleSummaryIndex const&, llvm::DenseMap<llvm::StringRef, std::unordered_set<unsigned long, std::hash<unsigned long>, std::equal_to<unsigned long>, std::allocator<unsigned long>>, llvm::DenseMapInfo<llvm::StringRef, void>, llvm::detail::DenseMapPair<llvm::StringRef, std::unordered_set<unsigned long, std::hash<unsigned long>, std::equal_to<unsigned long>, std::allocator<unsigned long>>>> const&, llvm::DenseMap<unsigned long, llvm::GlobalValueSummary*, llvm::DenseMapInfo<unsigned long, void>, llvm::detail::DenseMapPair<unsigned long, llvm::GlobalValueSummary*>> const&, llvm::MapVector<llvm::StringRef, llvm::BitcodeModule, llvm::DenseMap<llvm::StringRef, unsigned int, llvm::DenseMapInfo<llvm::StringRef, void>, llvm::detail::DenseMapPair<llvm::StringRef, unsigned int>>, llvm::SmallVector<std::pair<llvm::StringRef, llvm::BitcodeModule>, 0u>>*, std::vector<unsigned char, std::allocator<unsigned char>> const&)::$_1::operator()(llvm::Module&, llvm::TargetMachine*, std::unique_ptr<llvm::ToolOutputFile, std::default_delete<llvm::ToolOutputFile>>) const LTOBackend.cpp:0:0
#15 0x000000000276feec llvm::lto::thinBackend(llvm::lto::Config const&, unsigned int, std::function<llvm::Expected<std::unique_ptr<llvm::CachedFileStream, std::default_delete<llvm::CachedFileStream>>> (unsigned int, llvm::Twine const&)>, llvm::Module&, llvm::ModuleSummaryIndex const&, llvm::DenseMap<llvm::StringRef, std::unordered_set<unsigned long, std::hash<unsigned long>, std::equal_to<unsigned long>, std::allocator<unsigned long>>, llvm::DenseMapInfo<llvm::StringRef, void>, llvm::detail::DenseMapPair<llvm::StringRef, std::unordered_set<unsigned long, std::hash<unsigned long>, std::equal_to<unsigned long>, std::allocator<unsigned long>>>> const&, llvm::DenseMap<unsigned long, llvm::GlobalValueSummary*, llvm::DenseMapInfo<unsigned long, void>, llvm::detail::DenseMapPair<unsigned long, llvm::GlobalValueSummary*>> const&, llvm::MapVector<llvm::StringRef, llvm::BitcodeModule, llvm::DenseMap<llvm::StringRef, unsigned int, llvm::DenseMapInfo<llvm::StringRef, void>, llvm::detail::DenseMapPair<llvm::StringRef, unsigned int>>, llvm::SmallVector<std::pair<llvm::StringRef, llvm::BitcodeModule>, 0u>>*, std::vector<unsigned char, std::allocator<unsigned char>> const&) (/home/nathan/tmp/cvise.L3dhxztcjp/install/llvm-bad/bin/lld+0x276feec)
#16 0x0000000002769950 (anonymous namespace)::InProcessThinBackend::runThinLTOBackendThread(std::function<llvm::Expected<std::unique_ptr<llvm::CachedFileStream, std::default_delete<llvm::CachedFileStream>>> (unsigned int, llvm::Twine const&)>, std::function<llvm::Expected<std::function<llvm::Expected<std::unique_ptr<llvm::CachedFileStream, std::default_delete<llvm::CachedFileStream>>> (unsigned int, llvm::Twine const&)>> (unsigned int, llvm::StringRef, llvm::Twine const&)>, unsigned int, llvm::BitcodeModule, llvm::ModuleSummaryIndex&, llvm::DenseMap<llvm::StringRef, std::unordered_set<unsigned long, std::hash<unsigned long>, std::equal_to<unsigned long>, std::allocator<unsigned long>>, llvm::DenseMapInfo<llvm::StringRef, void>, llvm::detail::DenseMapPair<llvm::StringRef, std::unordered_set<unsigned long, std::hash<unsigned long>, std::equal_to<unsigned long>, std::allocator<unsigned long>>>> const&, llvm::DenseSet<llvm::ValueInfo, llvm::DenseMapInfo<llvm::ValueInfo, void>> const&, std::map<unsigned long, llvm::GlobalValue::LinkageTypes, std::less<unsigned long>, std::allocator<std::pair<unsigned long const, llvm::GlobalValue::LinkageTypes>>> const&, llvm::DenseMap<unsigned long, llvm::GlobalValueSummary*, llvm::DenseMapInfo<unsigned long, void>, llvm::detail::DenseMapPair<unsigned long, llvm::GlobalValueSummary*>> const&, llvm::MapVector<llvm::StringRef, llvm::BitcodeModule, llvm::DenseMap<llvm::StringRef, unsigned int, llvm::DenseMapInfo<llvm::StringRef, void>, llvm::detail::DenseMapPair<llvm::StringRef, unsigned int>>, llvm::SmallVector<std::pair<llvm::StringRef, llvm::BitcodeModule>, 0u>>&)::'lambda'(std::function<llvm::Expected<std::unique_ptr<llvm::CachedFileStream, std::default_delete<llvm::CachedFileStream>>> (unsigned int, llvm::Twine const&)>)::operator()(std::function<llvm::Expected<std::unique_ptr<llvm::CachedFileStream, std::default_delete<llvm::CachedFileStream>>> (unsigned int, llvm::Twine const&)>) const LTO.cpp:0:0
#17 0x0000000002769330 std::_Function_handler<void (), std::_Bind<(anonymous namespace)::InProcessThinBackend::start(unsigned int, llvm::BitcodeModule, llvm::DenseMap<llvm::StringRef, std::unordered_set<unsigned long, std::hash<unsigned long>, std::equal_to<unsigned long>, std::allocator<unsigned long>>, llvm::DenseMapInfo<llvm::StringRef, void>, llvm::detail::DenseMapPair<llvm::StringRef, std::unordered_set<unsigned long, std::hash<unsigned long>, std::equal_to<unsigned long>, std::allocator<unsigned long>>>> const&, llvm::DenseSet<llvm::ValueInfo, llvm::DenseMapInfo<llvm::ValueInfo, void>> const&, std::map<unsigned long, llvm::GlobalValue::LinkageTypes, std::less<unsigned long>, std::allocator<std::pair<unsigned long const, llvm::GlobalValue::LinkageTypes>>> const&, llvm::MapVector<llvm::StringRef, llvm::BitcodeModule, llvm::DenseMap<llvm::StringRef, unsigned int, llvm::DenseMapInfo<llvm::StringRef, void>, llvm::detail::DenseMapPair<llvm::StringRef, unsigned int>>, llvm::SmallVector<std::pair<llvm::StringRef, llvm::BitcodeModule>, 0u>>&)::'lambda'(llvm::BitcodeModule, llvm::ModuleSummaryIndex&, llvm::DenseMap<llvm::StringRef, std::unordered_set<unsigned long, std::hash<unsigned long>, std::equal_to<unsigned long>, std::allocator<unsigned long>>, llvm::DenseMapInfo<llvm::StringRef, void>, llvm::detail::DenseMapPair<llvm::StringRef, std::unordered_set<unsigned long, std::hash<unsigned long>, std::equal_to<unsigned long>, std::allocator<unsigned long>>>> const&, llvm::DenseSet<llvm::ValueInfo, llvm::DenseMapInfo<llvm::ValueInfo, void>> const&, std::map<unsigned long, llvm::GlobalValue::LinkageTypes, std::less<unsigned long>, std::allocator<std::pair<unsigned long const, llvm::GlobalValue::LinkageTypes>>> const&, llvm::DenseMap<unsigned long, llvm::GlobalValueSummary*, llvm::DenseMapInfo<unsigned long, void>, llvm::detail::DenseMapPair<unsigned long, llvm::GlobalValueSummary*>> const&, llvm::MapVector<llvm::StringRef, llvm::BitcodeModule, llvm::DenseMap<llvm::StringRef, unsigned int, llvm::DenseMapInfo<llvm::StringRef, void>, llvm::detail::DenseMapPair<llvm::StringRef, unsigned int>>, llvm::SmallVector<std::pair<llvm::StringRef, llvm::BitcodeModule>, 0u>>&) (llvm::BitcodeModule, std::reference_wrapper<llvm::ModuleSummaryIndex>, std::reference_wrapper<llvm::DenseMap<llvm::StringRef, std::unordered_set<unsigned long, std::hash<unsigned long>, std::equal_to<unsigned long>, std::allocator<unsigned long>>, llvm::DenseMapInfo<llvm::StringRef, void>, llvm::detail::DenseMapPair<llvm::StringRef, std::unordered_set<unsigned long, std::hash<unsigned long>, std::equal_to<unsigned long>, std::allocator<unsigned long>>>> const>, std::reference_wrapper<llvm::DenseSet<llvm::ValueInfo, llvm::DenseMapInfo<llvm::ValueInfo, void>> const>, std::reference_wrapper<std::map<unsigned long, llvm::GlobalValue::LinkageTypes, std::less<unsigned long>, std::allocator<std::pair<unsigned long const, llvm::GlobalValue::LinkageTypes>>> const>, std::reference_wrapper<llvm::DenseMap<unsigned long, llvm::GlobalValueSummary*, llvm::DenseMapInfo<unsigned long, void>, llvm::detail::DenseMapPair<unsigned long, llvm::GlobalValueSummary*>> const>, std::reference_wrapper<llvm::MapVector<llvm::StringRef, llvm::BitcodeModule, llvm::DenseMap<llvm::StringRef, unsigned int, llvm::DenseMapInfo<llvm::StringRef, void>, llvm::detail::DenseMapPair<llvm::StringRef, unsigned int>>, llvm::SmallVector<std::pair<llvm::StringRef, llvm::BitcodeModule>, 0u>>>)>>::_M_invoke(std::_Any_data const&) LTO.cpp:0:0
#18 0x0000000001d7b8bc std::_Function_handler<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> (), std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::thread::_Invoker<std::tuple<std::function<void ()>>>, void>>::_M_invoke(std::_Any_data const&) Writer.cpp:0:0
#19 0x0000000001a43214 std::__future_base::_State_baseV2::_M_do_set(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*) Driver.cpp:0:0
#20 0x0000ffffa7bdbdac __pthread_once_slow.isra.0 (/lib64/libc.so.6+0x9bdac)
#21 0x0000ffffa7bdbe64 pthread_once@@GLIBC_2.34 (/lib64/libc.so.6+0x9be64)
#22 0x0000000001d7bc00 std::__future_base::_Deferred_state<std::thread::_Invoker<std::tuple<std::function<void ()>>>, void>::_M_complete_async() Writer.cpp:0:0
#23 0x0000000001d7bc94 std::_Function_handler<void (), std::shared_future<void> llvm::ThreadPoolInterface::asyncImpl<void>(std::function<void ()>, llvm::ThreadPoolTaskGroup*)::'lambda'()>::_M_invoke(std::_Any_data const&) Writer.cpp:0:0
#24 0x0000000001d835a8 llvm::StdThreadPool::processTasks(llvm::ThreadPoolTaskGroup*) (/home/nathan/tmp/cvise.L3dhxztcjp/install/llvm-bad/bin/lld+0x1d835a8)
#25 0x0000000001d84ad0 void* llvm::thread::ThreadProxy<std::tuple<llvm::StdThreadPool::grow(int)::$_0>>(void*) ThreadPool.cpp:0:0
#26 0x0000ffffa7bd6798 start_thread (/lib64/libc.so.6+0x96798)
#27 0x0000ffffa7c41acc thread_start (/lib64/libc.so.6+0x101acc)

If this is not going to be forward fixed quickly, can the change be reverted in the meantime?

@jryans
Copy link
Member

jryans commented Apr 11, 2024

If this is not going to be forward fixed quickly, can the change be reverted in the meantime?

The PR author and several of the reviewers here have been attending EuroLLVM this week, and so they may not have noticed updates here. I assume they will reply early next week, but if action is needed before then, I suggest reverting.

SLTozer added a commit that referenced this pull request Apr 15, 2024
…88718)

Fixes the reported errors on:
#87379

A previous patch updated the bitcode reading for debug
intrinsics/records to not perform the expensive debug info format
conversion from records to intrinsics in cases where no records were
present, but the patch did not actually track when debug labels had been
seen, resulting in errors when parsing bitcode where functions contained
debug label records but no other debug records. This patch fixes that
case and adds a test for it.
@SLTozer
Copy link
Contributor Author

SLTozer commented Apr 15, 2024

Apologies for the delay, as mentioned above I was away for the last week. The error in this patch turned out to be fairly obvious, and should be fixed by #88718, which I've just merged.

@mikaelholmen
Copy link
Collaborator

Thanks! The fix solves the problem we saw.

bazuzi pushed a commit to bazuzi/llvm-project that referenced this pull request Apr 15, 2024
…lvm#88718)

Fixes the reported errors on:
llvm#87379

A previous patch updated the bitcode reading for debug
intrinsics/records to not perform the expensive debug info format
conversion from records to intrinsics in cases where no records were
present, but the patch did not actually track when debug labels had been
seen, resulting in errors when parsing bitcode where functions contained
debug label records but no other debug records. This patch fixes that
case and adds a test for it.
aniplcc pushed a commit to aniplcc/llvm-project that referenced this pull request Apr 15, 2024
…lvm#88718)

Fixes the reported errors on:
llvm#87379

A previous patch updated the bitcode reading for debug
intrinsics/records to not perform the expensive debug info format
conversion from records to intrinsics in cases where no records were
present, but the patch did not actually track when debug labels had been
seen, resulting in errors when parsing bitcode where functions contained
debug label records but no other debug records. This patch fixes that
case and adds a test for it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants