[clang] [lldb] [llvm] [BOLT][DWARF][NFC] Remove old GDB Index functions (PR #95019)

via cfe-commits cfe-commits at lists.llvm.org
Mon Jun 10 11:20:33 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-x86

Author: Sayhaan Siddiqui (sayhaan)

<details>
<summary>Changes</summary>

Remove old usages of GDB Index functions after replacing them with new ones.

---

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


22 Files Affected:

- (modified) bolt/include/bolt/Rewrite/DWARFRewriter.h (-11) 
- (modified) bolt/lib/Core/BinaryEmitter.cpp (+1) 
- (modified) bolt/lib/Rewrite/DWARFRewriter.cpp (-171) 
- (modified) clang/include/clang/Driver/Options.td (+4) 
- (modified) clang/lib/Driver/ToolChains/Gnu.cpp (+29) 
- (modified) cross-project-tests/lit.cfg.py (+13-1) 
- (modified) cross-project-tests/lit.site.cfg.py.in (+4) 
- (modified) lldb/test/API/lit.cfg.py (+5) 
- (modified) lldb/test/API/lit.site.cfg.py.in (+8) 
- (modified) lldb/test/Shell/helper/toolchain.py (+5) 
- (modified) lldb/test/Shell/lit.site.cfg.py.in (+9) 
- (modified) llvm/CMakeLists.txt (+4) 
- (modified) llvm/include/llvm/MC/MCFragment.h (+22) 
- (modified) llvm/include/llvm/MC/MCObjectStreamer.h (+2) 
- (modified) llvm/include/llvm/MC/MCStreamer.h (+6) 
- (modified) llvm/lib/MC/MCAssembler.cpp (+81-37) 
- (modified) llvm/lib/MC/MCExpr.cpp (+2-8) 
- (modified) llvm/lib/MC/MCFragment.cpp (+12) 
- (modified) llvm/lib/MC/MCObjectStreamer.cpp (+5) 
- (modified) llvm/lib/MC/MCStreamer.cpp (+2) 
- (modified) llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp (+24) 
- (added) llvm/test/MC/X86/directive-avoid_end_align.s (+208) 


``````````diff
diff --git a/bolt/include/bolt/Rewrite/DWARFRewriter.h b/bolt/include/bolt/Rewrite/DWARFRewriter.h
index 3cc9d823c815b..4559ff5ff5159 100644
--- a/bolt/include/bolt/Rewrite/DWARFRewriter.h
+++ b/bolt/include/bolt/Rewrite/DWARFRewriter.h
@@ -150,9 +150,6 @@ class DWARFRewriter {
   /// blocks) to be updated.
   void updateDebugAddressRanges();
 
-  /// Rewrite .gdb_index section if present.
-  void updateGdbIndexSection(CUOffsetMap &CUMap, uint32_t NumCUs);
-
   /// DWARFDie contains a pointer to a DIE and hence gets invalidated once the
   /// embedded DIE is destroyed. This wrapper class stores a DIE internally and
   /// could be cast to a DWARFDie that is valid even after the initial DIE is
@@ -194,14 +191,6 @@ class DWARFRewriter {
     DwoRangesBase[DWOId] = RangesBase;
   }
 
-  /// Adds an GDBIndexTUEntry if .gdb_index seciton exists.
-  void addGDBTypeUnitEntry(const GDBIndexTUEntry &&Entry);
-
-  /// Returns all entries needed for Types CU list
-  const GDBIndexTUEntryType &getGDBIndexTUEntryVector() const {
-    return GDBIndexTUEntryVector;
-  }
-
   using OverriddenSectionsMap = std::unordered_map<DWARFSectionKind, StringRef>;
   /// Output .dwo files.
   void writeDWOFiles(DWARFUnit &, const OverriddenSectionsMap &,
diff --git a/bolt/lib/Core/BinaryEmitter.cpp b/bolt/lib/Core/BinaryEmitter.cpp
index 5793963f9b80d..c231fffa0d5ff 100644
--- a/bolt/lib/Core/BinaryEmitter.cpp
+++ b/bolt/lib/Core/BinaryEmitter.cpp
@@ -487,6 +487,7 @@ void BinaryEmitter::emitFunctionBody(BinaryFunction &BF, FunctionFragment &FF,
         // This assumes the second instruction in the macro-op pair will get
         // assigned to its own MCRelaxableFragment. Since all JCC instructions
         // are relaxable, we should be safe.
+        Streamer.emitNeverAlignCodeAtEnd(/*Alignment to avoid=*/64, *BC.STI);
       }
 
       if (!EmitCodeOnly) {
diff --git a/bolt/lib/Rewrite/DWARFRewriter.cpp b/bolt/lib/Rewrite/DWARFRewriter.cpp
index 7b62999dfb2b6..04dc7e94e6031 100644
--- a/bolt/lib/Rewrite/DWARFRewriter.cpp
+++ b/bolt/lib/Rewrite/DWARFRewriter.cpp
@@ -2062,177 +2062,6 @@ void DWARFRewriter::writeDWOFiles(
   TempOut->keep();
 }
 
-void DWARFRewriter::addGDBTypeUnitEntry(const GDBIndexTUEntry &&Entry) {
-  std::lock_guard<std::mutex> Lock(DWARFRewriterMutex);
-  if (!BC.getGdbIndexSection())
-    return;
-  GDBIndexTUEntryVector.emplace_back(Entry);
-}
-
-void DWARFRewriter::updateGdbIndexSection(CUOffsetMap &CUMap, uint32_t NumCUs) {
-  if (!BC.getGdbIndexSection())
-    return;
-
-  // See https://sourceware.org/gdb/onlinedocs/gdb/Index-Section-Format.html
-  // for .gdb_index section format.
-
-  StringRef GdbIndexContents = BC.getGdbIndexSection()->getContents();
-
-  const char *Data = GdbIndexContents.data();
-
-  // Parse the header.
-  const uint32_t Version = read32le(Data);
-  if (Version != 7 && Version != 8) {
-    errs() << "BOLT-ERROR: can only process .gdb_index versions 7 and 8\n";
-    exit(1);
-  }
-
-  // Some .gdb_index generators use file offsets while others use section
-  // offsets. Hence we can only rely on offsets relative to each other,
-  // and ignore their absolute values.
-  const uint32_t CUListOffset = read32le(Data + 4);
-  const uint32_t CUTypesOffset = read32le(Data + 8);
-  const uint32_t AddressTableOffset = read32le(Data + 12);
-  const uint32_t SymbolTableOffset = read32le(Data + 16);
-  const uint32_t ConstantPoolOffset = read32le(Data + 20);
-  Data += 24;
-
-  // Map CUs offsets to indices and verify existing index table.
-  std::map<uint32_t, uint32_t> OffsetToIndexMap;
-  const uint32_t CUListSize = CUTypesOffset - CUListOffset;
-  const uint32_t TUListSize = AddressTableOffset - CUTypesOffset;
-  const unsigned NUmCUsEncoded = CUListSize / 16;
-  unsigned MaxDWARFVersion = BC.DwCtx->getMaxVersion();
-  unsigned NumDWARF5TUs =
-      getGDBIndexTUEntryVector().size() - BC.DwCtx->getNumTypeUnits();
-  bool SkipTypeUnits = false;
-  // For DWARF5 Types are in .debug_info.
-  // LLD doesn't generate Types CU List, and in CU list offset
-  // only includes CUs.
-  // GDB 11+ includes only CUs in CU list and generates Types
-  // list.
-  // GDB 9 includes CUs and TUs in CU list and generates TYpes
-  // list. The NumCUs is CUs + TUs, so need to modify the check.
-  // For split-dwarf
-  // GDB-11, DWARF5: TU units from dwo are not included.
-  // GDB-11, DWARF4: TU units from dwo are included.
-  if (MaxDWARFVersion >= 5)
-    SkipTypeUnits = !TUListSize ? true
-                                : ((NUmCUsEncoded + NumDWARF5TUs) ==
-                                   BC.DwCtx->getNumCompileUnits());
-
-  if (!((CUListSize == NumCUs * 16) ||
-        (CUListSize == (NumCUs + NumDWARF5TUs) * 16))) {
-    errs() << "BOLT-ERROR: .gdb_index: CU count mismatch\n";
-    exit(1);
-  }
-  DenseSet<uint64_t> OriginalOffsets;
-  for (unsigned Index = 0, Units = BC.DwCtx->getNumCompileUnits();
-       Index < Units; ++Index) {
-    const DWARFUnit *CU = BC.DwCtx->getUnitAtIndex(Index);
-    if (SkipTypeUnits && CU->isTypeUnit())
-      continue;
-    const uint64_t Offset = read64le(Data);
-    Data += 16;
-    if (CU->getOffset() != Offset) {
-      errs() << "BOLT-ERROR: .gdb_index CU offset mismatch\n";
-      exit(1);
-    }
-
-    OriginalOffsets.insert(Offset);
-    OffsetToIndexMap[Offset] = Index;
-  }
-
-  // Ignore old address table.
-  const uint32_t OldAddressTableSize = SymbolTableOffset - AddressTableOffset;
-  // Move Data to the beginning of symbol table.
-  Data += SymbolTableOffset - CUTypesOffset;
-
-  // Calculate the size of the new address table.
-  uint32_t NewAddressTableSize = 0;
-  for (const auto &CURangesPair : ARangesSectionWriter->getCUAddressRanges()) {
-    const SmallVector<DebugAddressRange, 2> &Ranges = CURangesPair.second;
-    NewAddressTableSize += Ranges.size() * 20;
-  }
-
-  // Difference between old and new table (and section) sizes.
-  // Could be negative.
-  int32_t Delta = NewAddressTableSize - OldAddressTableSize;
-
-  size_t NewGdbIndexSize = GdbIndexContents.size() + Delta;
-
-  // Free'd by ExecutableFileMemoryManager.
-  auto *NewGdbIndexContents = new uint8_t[NewGdbIndexSize];
-  uint8_t *Buffer = NewGdbIndexContents;
-
-  write32le(Buffer, Version);
-  write32le(Buffer + 4, CUListOffset);
-  write32le(Buffer + 8, CUTypesOffset);
-  write32le(Buffer + 12, AddressTableOffset);
-  write32le(Buffer + 16, SymbolTableOffset + Delta);
-  write32le(Buffer + 20, ConstantPoolOffset + Delta);
-  Buffer += 24;
-
-  using MapEntry = std::pair<uint32_t, CUInfo>;
-  std::vector<MapEntry> CUVector(CUMap.begin(), CUMap.end());
-  // Need to sort since we write out all of TUs in .debug_info before CUs.
-  std::sort(CUVector.begin(), CUVector.end(),
-            [](const MapEntry &E1, const MapEntry &E2) -> bool {
-              return E1.second.Offset < E2.second.Offset;
-            });
-  // Writing out CU List <Offset, Size>
-  for (auto &CUInfo : CUVector) {
-    // Skipping TU for DWARF5 when they are not included in CU list.
-    if (!OriginalOffsets.count(CUInfo.first))
-      continue;
-    write64le(Buffer, CUInfo.second.Offset);
-    // Length encoded in CU doesn't contain first 4 bytes that encode length.
-    write64le(Buffer + 8, CUInfo.second.Length + 4);
-    Buffer += 16;
-  }
-
-  // Rewrite TU CU List, since abbrevs can be different.
-  // Entry example:
-  // 0: offset = 0x00000000, type_offset = 0x0000001e, type_signature =
-  // 0x418503b8111e9a7b Spec says " triplet, the first value is the CU offset,
-  // the second value is the type offset in the CU, and the third value is the
-  // type signature" Looking at what is being generated by gdb-add-index. The
-  // first entry is TU offset, second entry is offset from it, and third entry
-  // is the type signature.
-  if (TUListSize)
-    for (const GDBIndexTUEntry &Entry : getGDBIndexTUEntryVector()) {
-      write64le(Buffer, Entry.UnitOffset);
-      write64le(Buffer + 8, Entry.TypeDIERelativeOffset);
-      write64le(Buffer + 16, Entry.TypeHash);
-      Buffer += sizeof(GDBIndexTUEntry);
-    }
-
-  // Generate new address table.
-  for (const std::pair<const uint64_t, DebugAddressRangesVector> &CURangesPair :
-       ARangesSectionWriter->getCUAddressRanges()) {
-    const uint32_t CUIndex = OffsetToIndexMap[CURangesPair.first];
-    const DebugAddressRangesVector &Ranges = CURangesPair.second;
-    for (const DebugAddressRange &Range : Ranges) {
-      write64le(Buffer, Range.LowPC);
-      write64le(Buffer + 8, Range.HighPC);
-      write32le(Buffer + 16, CUIndex);
-      Buffer += 20;
-    }
-  }
-
-  const size_t TrailingSize =
-      GdbIndexContents.data() + GdbIndexContents.size() - Data;
-  assert(Buffer + TrailingSize == NewGdbIndexContents + NewGdbIndexSize &&
-         "size calculation error");
-
-  // Copy over the rest of the original data.
-  memcpy(Buffer, Data, TrailingSize);
-
-  // Register the new section.
-  BC.registerOrUpdateNoteSection(".gdb_index", NewGdbIndexContents,
-                                 NewGdbIndexSize);
-}
-
 std::unique_ptr<DebugBufferVector>
 DWARFRewriter::makeFinalLocListsSection(DWARFVersion Version) {
   auto LocBuffer = std::make_unique<DebugBufferVector>();
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index d44faa55c456f..63bb86717bb14 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -5483,6 +5483,10 @@ def pg : Flag<["-"], "pg">, HelpText<"Enable mcount instrumentation">,
   MarshallingInfoFlag<CodeGenOpts<"InstrumentForProfiling">>;
 def pipe : Flag<["-", "--"], "pipe">,
   HelpText<"Use pipes between commands, when possible">;
+// Facebook T92898286
+def post_link_optimize : Flag<["--"], "post-link-optimize">,
+  HelpText<"Apply post-link optimizations using BOLT">;
+// End Facebook T92898286
 def prebind__all__twolevel__modules : Flag<["-"], "prebind_all_twolevel_modules">;
 def prebind : Flag<["-"], "prebind">;
 def preload : Flag<["-"], "preload">;
diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp
index b141e5f2adfab..f7611af5763ab 100644
--- a/clang/lib/Driver/ToolChains/Gnu.cpp
+++ b/clang/lib/Driver/ToolChains/Gnu.cpp
@@ -672,12 +672,41 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
     }
   }
 
+  // Facebook T92898286
+  if (Args.hasArg(options::OPT_post_link_optimize))
+    CmdArgs.push_back("-q");
+  // End Facebook T92898286
+
   Args.AddAllArgs(CmdArgs, options::OPT_T);
 
   const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
   C.addCommand(std::make_unique<Command>(JA, *this,
                                          ResponseFileSupport::AtFileCurCP(),
                                          Exec, CmdArgs, Inputs, Output));
+  // Facebook T92898286
+  if (!Args.hasArg(options::OPT_post_link_optimize) || !Output.isFilename())
+    return;
+
+  const char *MvExec = Args.MakeArgString(ToolChain.GetProgramPath("mv"));
+  ArgStringList MoveCmdArgs;
+  MoveCmdArgs.push_back(Output.getFilename());
+  const char *PreBoltBin =
+      Args.MakeArgString(Twine(Output.getFilename()) + ".pre-bolt");
+  MoveCmdArgs.push_back(PreBoltBin);
+  C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
+                                         MvExec, MoveCmdArgs, std::nullopt));
+
+  ArgStringList BoltCmdArgs;
+  const char *BoltExec =
+      Args.MakeArgString(ToolChain.GetProgramPath("llvm-bolt"));
+  BoltCmdArgs.push_back(PreBoltBin);
+  BoltCmdArgs.push_back("-reorder-blocks=reverse");
+  BoltCmdArgs.push_back("-update-debug-sections");
+  BoltCmdArgs.push_back("-o");
+  BoltCmdArgs.push_back(Output.getFilename());
+  C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
+                                         BoltExec, BoltCmdArgs, std::nullopt));
+  // End Facebook T92898286
 }
 
 void tools::gnutools::Assembler::ConstructJob(Compilation &C,
diff --git a/cross-project-tests/lit.cfg.py b/cross-project-tests/lit.cfg.py
index 774c4eaf4d976..619634578dfe6 100644
--- a/cross-project-tests/lit.cfg.py
+++ b/cross-project-tests/lit.cfg.py
@@ -84,7 +84,13 @@ def get_required_attr(config, attr_name):
 # use_clang() and use_lld() respectively, so set them to "", if needed.
 if not hasattr(config, "clang_src_dir"):
     config.clang_src_dir = ""
-llvm_config.use_clang(required=("clang" in config.llvm_enabled_projects))
+# Facebook T92898286
+should_test_bolt = get_required_attr(config, "llvm_test_bolt")
+if should_test_bolt:
+    llvm_config.use_clang(required=("clang" in config.llvm_enabled_projects), additional_flags=["--post-link-optimize"])
+else:
+    llvm_config.use_clang(required=("clang" in config.llvm_enabled_projects))
+# End Facebook T92898286
 
 if not hasattr(config, "lld_src_dir"):
     config.lld_src_dir = ""
@@ -293,3 +299,9 @@ def get_clang_default_dwarf_version_string(triple):
 # Allow 'REQUIRES: XXX-registered-target' in tests.
 for arch in config.targets_to_build:
     config.available_features.add(arch.lower() + "-registered-target")
+
+# Facebook T92898286
+# Ensure the user's PYTHONPATH is included.
+if "PYTHONPATH" in os.environ:
+    config.environment["PYTHONPATH"] = os.environ["PYTHONPATH"]
+# End Facebook T92898286
diff --git a/cross-project-tests/lit.site.cfg.py.in b/cross-project-tests/lit.site.cfg.py.in
index 39458dfc79afd..2d53cd377f033 100644
--- a/cross-project-tests/lit.site.cfg.py.in
+++ b/cross-project-tests/lit.site.cfg.py.in
@@ -21,6 +21,10 @@ config.mlir_src_root = "@MLIR_SOURCE_DIR@"
 
 config.llvm_use_sanitizer = "@LLVM_USE_SANITIZER@"
 
+# Facebook T92898286
+config.llvm_test_bolt = lit.util.pythonize_bool("@LLVM_TEST_BOLT@")
+# End Facebook T92898286
+
 import lit.llvm
 lit.llvm.initialize(lit_config, config)
 
diff --git a/lldb/test/API/lit.cfg.py b/lldb/test/API/lit.cfg.py
index d934349fe3ca3..d4a62c51458cc 100644
--- a/lldb/test/API/lit.cfg.py
+++ b/lldb/test/API/lit.cfg.py
@@ -248,6 +248,11 @@ def delete_module_cache(path):
 if is_configured("lldb_framework_dir"):
     dotest_cmd += ["--framework", config.lldb_framework_dir]
 
+# Facebook T92898286
+if is_configured("llvm_test_bolt"):
+    dotest_cmd += ["-E", '"--post-link-optimize"']
+# End Facebook T92898286
+
 if (
     "lldb-repro-capture" in config.available_features
     or "lldb-repro-replay" in config.available_features
diff --git a/lldb/test/API/lit.site.cfg.py.in b/lldb/test/API/lit.site.cfg.py.in
index 8b2d09ae41cd2..602f45759e48f 100644
--- a/lldb/test/API/lit.site.cfg.py.in
+++ b/lldb/test/API/lit.site.cfg.py.in
@@ -1,5 +1,9 @@
 @LIT_SITE_CFG_IN_HEADER@
 
+#Facebook T92898286
+import lit.util
+#End Facebook T92898286
+
 config.llvm_src_root = "@LLVM_SOURCE_DIR@"
 config.llvm_obj_root = "@LLVM_BINARY_DIR@"
 config.llvm_tools_dir = lit_config.substitute("@LLVM_TOOLS_DIR@")
@@ -39,6 +43,10 @@ config.libcxx_include_target_dir = "@LIBCXX_GENERATED_INCLUDE_TARGET_DIR@"
 config.lldb_module_cache = os.path.join("@LLDB_TEST_MODULE_CACHE_LLDB@", "lldb-api")
 config.clang_module_cache = os.path.join("@LLDB_TEST_MODULE_CACHE_CLANG@", "lldb-api")
 
+# Facebook T92898286
+config.llvm_test_bolt = lit.util.pythonize_bool("@LLVM_TEST_BOLT@")
+# End Facebook T92898286
+
 # Plugins
 lldb_build_intel_pt = '@LLDB_BUILD_INTEL_PT@'
 if lldb_build_intel_pt == '1':
diff --git a/lldb/test/Shell/helper/toolchain.py b/lldb/test/Shell/helper/toolchain.py
index 255955fc70d8c..7b7be06643166 100644
--- a/lldb/test/Shell/helper/toolchain.py
+++ b/lldb/test/Shell/helper/toolchain.py
@@ -165,6 +165,11 @@ def use_support_substitutions(config):
     if config.cmake_sysroot:
         host_flags += ["--sysroot={}".format(config.cmake_sysroot)]
 
+    # Facebook T92898286
+    if config.llvm_test_bolt:
+        host_flags += ["--post-link-optimize"]
+    # End Facebook T92898286
+
     host_flags = " ".join(host_flags)
     config.substitutions.append(("%clang_host", "%clang " + host_flags))
     config.substitutions.append(("%clangxx_host", "%clangxx " + host_flags))
diff --git a/lldb/test/Shell/lit.site.cfg.py.in b/lldb/test/Shell/lit.site.cfg.py.in
index b69e7bce1bc0b..fe8323734b7db 100644
--- a/lldb/test/Shell/lit.site.cfg.py.in
+++ b/lldb/test/Shell/lit.site.cfg.py.in
@@ -1,5 +1,10 @@
 @LIT_SITE_CFG_IN_HEADER@
 
+#Facebook T92898286
+import lit.util
+#End Facebook T92898286
+
+
 config.llvm_src_root = "@LLVM_SOURCE_DIR@"
 config.llvm_obj_root = "@LLVM_BINARY_DIR@"
 config.llvm_tools_dir = lit_config.substitute("@LLVM_TOOLS_DIR@")
@@ -31,6 +36,10 @@ config.llvm_use_sanitizer = "@LLVM_USE_SANITIZER@"
 config.lldb_module_cache = os.path.join("@LLDB_TEST_MODULE_CACHE_LLDB@", "lldb-shell")
 config.clang_module_cache = os.path.join("@LLDB_TEST_MODULE_CACHE_CLANG@", "lldb-shell")
 
+# Facebook T92898286
+config.llvm_test_bolt = lit.util.pythonize_bool("@LLVM_TEST_BOLT@")
+# End Facebook T92898286
+
 import lit.llvm
 lit.llvm.initialize(lit_config, config)
 
diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt
index 3208147101c0d..ecd36d2564e4f 100644
--- a/llvm/CMakeLists.txt
+++ b/llvm/CMakeLists.txt
@@ -709,6 +709,10 @@ set(LLVM_LIB_FUZZING_ENGINE "" CACHE PATH
 option(LLVM_USE_SPLIT_DWARF
   "Use -gsplit-dwarf when compiling llvm and --gdb-index when linking." OFF)
 
+# Facebook T92898286
+option(LLVM_TEST_BOLT "Enable BOLT testing in non-BOLT tests that use clang" OFF)
+# End Facebook T92898286
+
 # Define an option controlling whether we should build for 32-bit on 64-bit
 # platforms, where supported.
 if( CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT (WIN32 OR ${CMAKE_SYSTEM_NAME} MATCHES "AIX"))
diff --git a/llvm/include/llvm/MC/MCFragment.h b/llvm/include/llvm/MC/MCFragment.h
index 67e10c3589495..1adb8a67009d1 100644
--- a/llvm/include/llvm/MC/MCFragment.h
+++ b/llvm/include/llvm/MC/MCFragment.h
@@ -33,6 +33,7 @@ class MCFragment : public ilist_node_with_parent<MCFragment, MCSection> {
 public:
   enum FragmentType : uint8_t {
     FT_Align,
+    FT_NeverAlign,
     FT_Data,
     FT_CompactEncodedInst,
     FT_Fill,
@@ -341,6 +342,27 @@ class MCAlignFragment : public MCFragment {
   }
 };
 
+class MCNeverAlignFragment : public MCFragment {
+  /// The alignment the end of the next fragment should avoid.
+  unsigned Alignment;
+
+  /// When emitting Nops some subtargets have specific nop encodings.
+  const MCSubtargetInfo &STI;
+
+public:
+  MCNeverAlignFragment(unsigned Alignment, const MCSubtargetInfo &STI,
+                       MCSection *Sec = nullptr)
+      : MCFragment(FT_NeverAlign, false, Sec), Alignment(Alignment), STI(STI) {}
+
+  unsigned getAlignment() const { return Alignment; }
+
+  const MCSubtargetInfo &getSubtargetInfo() const { return STI; }
+
+  static bool classof(const MCFragment *F) {
+    return F->getKind() == MCFragment::FT_NeverAlign;
+  }
+};
+
 class MCFillFragment : public MCFragment {
   uint8_t ValueSize;
   /// Value to use for filling bytes.
diff --git a/llvm/include/llvm/MC/MCObjectStreamer.h b/llvm/include/llvm/MC/MCObjectStreamer.h
index e212d54613980..c7d760721e369 100644
--- a/llvm/include/llvm/MC/MCObjectStreamer.h
+++ b/llvm/include/llvm/MC/MCObjectStreamer.h
@@ -157,6 +157,8 @@ class MCObjectStreamer : public MCStreamer {
                             unsigned MaxBytesToEmit = 0) override;
   void emitCodeAlignment(Align ByteAlignment, const MCSubtargetInfo *STI,
                          unsigned MaxBytesToEmit = 0) override;
+  void emitNeverAlignCodeAtEnd(unsigned ByteAlignment,
+                               const MCSubtargetInfo &STI) override;
   void emitValueToOffset(const MCExpr *Offset, unsigned char Value,
                          SMLoc Loc) override;
   void emitDwarfLocDirective(unsigned FileNo, unsigned Line, unsigned Column,
diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h
index b7468cf70a664..dd813192d9ca0 100644
--- a/llvm/include/llvm/MC/MCStreamer.h
+++ b/llvm/include/llvm/MC/MCStreamer.h
@@ -887,6 +887,12 @@ class MCStreamer {
   virtual void emitCodeAlignment(Align Alignment, const MCSubtargetInfo *STI,
                                  unsigned MaxBytesToEmit = 0);
 
+  /// If the end of the fragment following this NeverAlign fragment ever gets
+  /// aligned to \p ByteAlignment, this fragment emits a single nop before the
+  /// following fragment to break this end-alignment.
+  virtual void emitNeverAlignCodeAtEnd(unsigned ByteAlignment,
+                                       const MCSubtargetInfo &STI);
+
   /// Em...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/95019


More information about the cfe-commits mailing list