[llvm] [CHERI][RISCV][MC] Add support for aligning and tail-padding globals for precise bounds tracking on CHERI targets. (PR #203872)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 15 07:29:04 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-directx

Author: Owen Anderson (resistor)

<details>
<summary>Changes</summary>

On CHERI targets, bounds are generally stored in a compressed format which imposes alignment requirements based on allocation size. When emitting globals, we need to align and tail-pad them as appropriate to ensure that the pointer to the global will have bounds that are precise, i.e. not covering any non-padding bytes that either precede or follow it.

While this patch adds the plumbing necessary to support this feature on arbitrary targets, it only concretely implements it on RISCV for ELF objects, both the RVY base and XCheriot. Support for other targets (such as AArch64/Morello) or other object formats exists in downstreams, but is left as future work here.

Co-authored-by: Alex Richardson <alexrichardson@<!-- -->google.com>



---

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


36 Files Affected:

- (modified) llvm/include/llvm/CodeGen/AsmPrinter.h (+5-2) 
- (modified) llvm/include/llvm/DWARFCFIChecker/DWARFCFIFunctionFrameStreamer.h (+2-2) 
- (modified) llvm/include/llvm/MC/MCAsmInfo.h (+5) 
- (modified) llvm/include/llvm/MC/MCDXContainerStreamer.h (+2-1) 
- (modified) llvm/include/llvm/MC/MCELFStreamer.h (+5-3) 
- (modified) llvm/include/llvm/MC/MCGOFFStreamer.h (+2-2) 
- (modified) llvm/include/llvm/MC/MCSPIRVStreamer.h (+2-2) 
- (modified) llvm/include/llvm/MC/MCStreamer.h (+10-4) 
- (modified) llvm/include/llvm/MC/MCWasmStreamer.h (+4-3) 
- (modified) llvm/include/llvm/MC/MCWinCOFFStreamer.h (+4-3) 
- (modified) llvm/include/llvm/MC/MCXCOFFStreamer.h (+2-2) 
- (modified) llvm/include/llvm/Support/CHERICapabilityFormat.h (+6) 
- (modified) llvm/include/llvm/Target/TargetLoweringObjectFile.h (+22) 
- (modified) llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp (+22-7) 
- (modified) llvm/lib/MC/MCAsmStreamer.cpp (+26-6) 
- (modified) llvm/lib/MC/MCELFStreamer.cpp (+6-4) 
- (modified) llvm/lib/MC/MCMachOStreamer.cpp (+9-5) 
- (modified) llvm/lib/MC/MCNullStreamer.cpp (+2-2) 
- (modified) llvm/lib/MC/MCStreamer.cpp (+2-1) 
- (modified) llvm/lib/MC/MCWasmStreamer.cpp (+4-2) 
- (modified) llvm/lib/MC/MCWinCOFFStreamer.cpp (+4-2) 
- (modified) llvm/lib/MC/MCXCOFFStreamer.cpp (+3-2) 
- (modified) llvm/lib/Object/RecordStreamer.cpp (+2-1) 
- (modified) llvm/lib/Object/RecordStreamer.h (+2-2) 
- (modified) llvm/lib/Support/CHERICapabilityFormat.cpp (+8) 
- (modified) llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp (+1-1) 
- (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h (+27) 
- (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp (+5) 
- (modified) llvm/lib/Target/RISCV/RISCVISelLowering.cpp (+1) 
- (modified) llvm/lib/Target/RISCV/RISCVTargetObjectFile.cpp (+40) 
- (modified) llvm/lib/Target/RISCV/RISCVTargetObjectFile.h (+7) 
- (modified) llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.h (+3-2) 
- (added) llvm/test/CodeGen/RISCV/cheri-global-bounds.ll (+26) 
- (modified) llvm/tools/llvm-exegesis/lib/SnippetFile.cpp (+2-2) 
- (modified) llvm/tools/llvm-mca/CodeRegionGenerator.h (+2-2) 
- (modified) llvm/unittests/CodeGen/TestAsmPrinter.h (+3-2) 


``````````diff
diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h
index f6f0f7348836e..484b8f8d224d7 100644
--- a/llvm/include/llvm/CodeGen/AsmPrinter.h
+++ b/llvm/include/llvm/CodeGen/AsmPrinter.h
@@ -27,6 +27,7 @@
 #include "llvm/CodeGen/StackMaps.h"
 #include "llvm/DebugInfo/CodeView/CodeView.h"
 #include "llvm/IR/InlineAsm.h"
+#include "llvm/Support/CHERICapabilityFormat.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/ErrorHandling.h"
 #include <cstdint>
@@ -582,8 +583,10 @@ class LLVM_ABI AsmPrinter : public MachineFunctionPass {
   /// On AIX, when an alias refers to a sub-element of a global variable, the
   /// label of that alias needs to be emitted before the corresponding element.
   using AliasMapTy = DenseMap<uint64_t, SmallVector<const GlobalAlias *, 1>>;
-  void emitGlobalConstant(const DataLayout &DL, const Constant *CV,
-                          AliasMapTy *AliasList = nullptr);
+  void
+  emitGlobalConstant(const DataLayout &DL, const Constant *CV,
+                     TailPaddingAmount TailPadding = TailPaddingAmount::None,
+                     AliasMapTy *AliasList = nullptr);
 
   /// Unnamed constant global variables solely contaning a pointer to
   /// another globals variable act like a global variable "proxy", or GOT
diff --git a/llvm/include/llvm/DWARFCFIChecker/DWARFCFIFunctionFrameStreamer.h b/llvm/include/llvm/DWARFCFIChecker/DWARFCFIFunctionFrameStreamer.h
index 5a3cf4ab64a1f..cf76027fc3599 100644
--- a/llvm/include/llvm/DWARFCFIChecker/DWARFCFIFunctionFrameStreamer.h
+++ b/llvm/include/llvm/DWARFCFIChecker/DWARFCFIFunctionFrameStreamer.h
@@ -46,8 +46,8 @@ class LLVM_ABI CFIFunctionFrameStreamer : public MCStreamer {
     return true;
   }
 
-  void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
-                        Align ByteAlignment) override {}
+  void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size, Align ByteAlignment,
+                        TailPaddingAmount TailPadding) override {}
   void emitSubsectionsViaSymbols() override {};
   void beginCOFFSymbolDef(const MCSymbol *Symbol) override {}
   void emitCOFFSymbolStorageClass(int StorageClass) override {}
diff --git a/llvm/include/llvm/MC/MCAsmInfo.h b/llvm/include/llvm/MC/MCAsmInfo.h
index e46b565ddb6d4..6d39372aa0583 100644
--- a/llvm/include/llvm/MC/MCAsmInfo.h
+++ b/llvm/include/llvm/MC/MCAsmInfo.h
@@ -215,6 +215,9 @@ class LLVM_ABI MCAsmInfo {
   /// True if full register names are printed.
   bool PPCUseFullRegisterNames = false;
 
+  /// True if a CHERI pure capability ABI is in use.
+  bool IsCheriPureCapabilityABI = false;
+
   //===--- Data Emission Directives -------------------------------------===//
 
   /// This should be set to the directive used to get some number of zero (and
@@ -601,6 +604,8 @@ class LLVM_ABI MCAsmInfo {
   bool useFullRegisterNames() const { return PPCUseFullRegisterNames; }
   void setFullRegisterNames(bool V) { PPCUseFullRegisterNames = V; }
 
+  bool isCheriPureCapabilityABI() const { return IsCheriPureCapabilityABI; }
+
   const char *getZeroDirective() const { return ZeroDirective; }
   const char *getAsciiDirective() const { return AsciiDirective; }
   const char *getAscizDirective() const { return AscizDirective; }
diff --git a/llvm/include/llvm/MC/MCDXContainerStreamer.h b/llvm/include/llvm/MC/MCDXContainerStreamer.h
index 37e3c7ddaad2c..123bfd85f140d 100644
--- a/llvm/include/llvm/MC/MCDXContainerStreamer.h
+++ b/llvm/include/llvm/MC/MCDXContainerStreamer.h
@@ -34,7 +34,8 @@ class MCDXContainerStreamer : public MCObjectStreamer {
                          std::move(Emitter)) {}
 
   bool emitSymbolAttribute(MCSymbol *, MCSymbolAttr) override { return false; }
-  void emitCommonSymbol(MCSymbol *, uint64_t, Align) override {}
+  void emitCommonSymbol(MCSymbol *, uint64_t, Align,
+                        TailPaddingAmount TailPadding) override {}
 };
 
 } // end namespace llvm
diff --git a/llvm/include/llvm/MC/MCELFStreamer.h b/llvm/include/llvm/MC/MCELFStreamer.h
index e1c86d8b12715..01a7d852d36bb 100644
--- a/llvm/include/llvm/MC/MCELFStreamer.h
+++ b/llvm/include/llvm/MC/MCELFStreamer.h
@@ -54,15 +54,17 @@ class LLVM_ABI MCELFStreamer : public MCObjectStreamer {
                       uint64_t Offset) override;
   void emitWeakReference(MCSymbol *Alias, const MCSymbol *Target) override;
   bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
-  void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
-                        Align ByteAlignment) override;
+  void emitCommonSymbol(
+      MCSymbol *Symbol, uint64_t Size, Align ByteAlignment,
+      TailPaddingAmount TailPadding = TailPaddingAmount::None) override;
 
   void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override;
   void emitELFSymverDirective(const MCSymbol *OriginalSym, StringRef Name,
                               bool KeepOriginalSym) override;
 
   void emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
-                             Align ByteAlignment) override;
+                             Align ByteAlignment,
+                             TailPaddingAmount TailPadding) override;
 
   void emitIdent(StringRef IdentString) override;
 
diff --git a/llvm/include/llvm/MC/MCGOFFStreamer.h b/llvm/include/llvm/MC/MCGOFFStreamer.h
index 756574d1caaf3..b8af787b46d35 100644
--- a/llvm/include/llvm/MC/MCGOFFStreamer.h
+++ b/llvm/include/llvm/MC/MCGOFFStreamer.h
@@ -36,8 +36,8 @@ class LLVM_ABI MCGOFFStreamer : public MCObjectStreamer {
 
   bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
 
-  void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
-                        Align ByteAlignment) override {}
+  void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size, Align ByteAlignment,
+                        TailPaddingAmount TailPadding) override {}
 };
 
 } // end namespace llvm
diff --git a/llvm/include/llvm/MC/MCSPIRVStreamer.h b/llvm/include/llvm/MC/MCSPIRVStreamer.h
index 42559f7522b50..0babc4c648c5f 100644
--- a/llvm/include/llvm/MC/MCSPIRVStreamer.h
+++ b/llvm/include/llvm/MC/MCSPIRVStreamer.h
@@ -33,8 +33,8 @@ class MCSPIRVStreamer : public MCObjectStreamer {
   bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override {
     return false;
   }
-  void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
-                        Align ByteAlignment) override {}
+  void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size, Align ByteAlignment,
+                        TailPaddingAmount TailPadding) override {}
 };
 
 } // end namespace llvm
diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h
index 955a48705f15c..ccb1b359374f1 100644
--- a/llvm/include/llvm/MC/MCStreamer.h
+++ b/llvm/include/llvm/MC/MCStreamer.h
@@ -23,6 +23,7 @@
 #include "llvm/MC/MCPseudoProbe.h"
 #include "llvm/MC/MCSection.h"
 #include "llvm/MC/MCWinEH.h"
+#include "llvm/Support/CHERICapabilityFormat.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/MD5.h"
@@ -691,16 +692,21 @@ class LLVM_ABI MCStreamer {
   /// \param Symbol - The common symbol to emit.
   /// \param Size - The size of the common symbol.
   /// \param ByteAlignment - The alignment of the symbol.
-  virtual void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
-                                Align ByteAlignment) = 0;
+  /// \param TailPadding - The number of tail padding bytes required to maintain
+  /// precise CHERI bounds.
+  virtual void
+  emitCommonSymbol(MCSymbol *Symbol, uint64_t Size, Align ByteAlignment,
+                   TailPaddingAmount TailPadding = TailPaddingAmount::None) = 0;
 
   /// Emit a local common (.lcomm) symbol.
   ///
   /// \param Symbol - The common symbol to emit.
   /// \param Size - The size of the common symbol.
   /// \param ByteAlignment - The alignment of the common symbol in bytes.
-  virtual void emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
-                                     Align ByteAlignment);
+  /// \param TailPadding - The number of bytes to pad for precise bounds.
+  virtual void emitLocalCommonSymbol(
+      MCSymbol *Symbol, uint64_t Size, Align ByteAlignment,
+      TailPaddingAmount TailPadding = TailPaddingAmount::None);
 
   /// Emit the zerofill section and an optional symbol.
   ///
diff --git a/llvm/include/llvm/MC/MCWasmStreamer.h b/llvm/include/llvm/MC/MCWasmStreamer.h
index fe5cdc4156eb2..3c627c2b96ea8 100644
--- a/llvm/include/llvm/MC/MCWasmStreamer.h
+++ b/llvm/include/llvm/MC/MCWasmStreamer.h
@@ -45,13 +45,14 @@ class LLVM_ABI MCWasmStreamer : public MCObjectStreamer {
   void emitLabelAtPos(MCSymbol *Symbol, SMLoc Loc, MCFragment &F,
                       uint64_t Offset) override;
   bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
-  void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
-                        Align ByteAlignment) override;
+  void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size, Align ByteAlignment,
+                        TailPaddingAmount TailPadding) override;
 
   void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override;
 
   void emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
-                             Align ByteAlignment) override;
+                             Align ByteAlignment,
+                             TailPaddingAmount TailPadding) override;
 
   void emitIdent(StringRef IdentString) override;
 
diff --git a/llvm/include/llvm/MC/MCWinCOFFStreamer.h b/llvm/include/llvm/MC/MCWinCOFFStreamer.h
index c6047cb309dd9..9a374263efd34 100644
--- a/llvm/include/llvm/MC/MCWinCOFFStreamer.h
+++ b/llvm/include/llvm/MC/MCWinCOFFStreamer.h
@@ -58,10 +58,11 @@ class LLVM_ABI MCWinCOFFStreamer : public MCObjectStreamer {
   void emitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) override;
   void emitCOFFSecNumber(MCSymbol const *Symbol) override;
   void emitCOFFSecOffset(MCSymbol const *Symbol) override;
-  void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
-                        Align ByteAlignment) override;
+  void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size, Align ByteAlignment,
+                        TailPaddingAmount TailPadding) override;
   void emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
-                             Align ByteAlignment) override;
+                             Align ByteAlignment,
+                             TailPaddingAmount TailPadding) override;
   void emitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override;
   void emitIdent(StringRef IdentString) override;
   void emitWinEHHandlerData(SMLoc Loc) override;
diff --git a/llvm/include/llvm/MC/MCXCOFFStreamer.h b/llvm/include/llvm/MC/MCXCOFFStreamer.h
index 884f6ed69a664..d3882e444aa3b 100644
--- a/llvm/include/llvm/MC/MCXCOFFStreamer.h
+++ b/llvm/include/llvm/MC/MCXCOFFStreamer.h
@@ -24,8 +24,8 @@ class LLVM_ABI MCXCOFFStreamer : public MCObjectStreamer {
 
   void changeSection(MCSection *Section, uint32_t Subsection = 0) override;
   bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
-  void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
-                        Align ByteAlignment) override;
+  void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size, Align ByteAlignment,
+                        TailPaddingAmount TailPadding) override;
   void emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym, uint64_t Size,
                                   MCSymbol *CsectSym, Align Alignment) override;
   void emitXCOFFSymbolLinkageWithVisibility(MCSymbol *Symbol,
diff --git a/llvm/include/llvm/Support/CHERICapabilityFormat.h b/llvm/include/llvm/Support/CHERICapabilityFormat.h
index 4b7afce9b8b7f..f0c74cbdb62a7 100644
--- a/llvm/include/llvm/Support/CHERICapabilityFormat.h
+++ b/llvm/include/llvm/Support/CHERICapabilityFormat.h
@@ -14,6 +14,8 @@
 
 namespace llvm {
 
+enum class TailPaddingAmount : uint64_t { None = 0u };
+
 template <typename Derived, typename AddressType>
 struct CHERICapabilityFormatBase {
   CHERICapabilityFormatBase() = delete;
@@ -28,6 +30,10 @@ struct CHERICapabilityFormatBase {
   /// Returns the required alignment for an allocation of size \p Length.
   LLVM_ABI static Align getRequiredAlignment(AddressType Length);
 
+  /// Returns the amount of padding bytes required to have precise bounds on an
+  /// allocation of size \p Length.
+  static TailPaddingAmount getRequiredTailPadding(AddressType Length);
+
   /// Returns \p Length rounded up to the nearest representable allocation
   /// length.
   LLVM_ABI static AddressType getRepresentableLength(AddressType Length);
diff --git a/llvm/include/llvm/Target/TargetLoweringObjectFile.h b/llvm/include/llvm/Target/TargetLoweringObjectFile.h
index 800bbe45c6a97..944de2e04d3c7 100644
--- a/llvm/include/llvm/Target/TargetLoweringObjectFile.h
+++ b/llvm/include/llvm/Target/TargetLoweringObjectFile.h
@@ -16,6 +16,7 @@
 
 #include "llvm/MC/MCObjectFileInfo.h"
 #include "llvm/MC/MCRegister.h"
+#include "llvm/Support/CHERICapabilityFormat.h"
 #include "llvm/Support/Compiler.h"
 #include <cstdint>
 
@@ -306,6 +307,27 @@ class LLVM_ABI TargetLoweringObjectFile : public MCObjectFileInfo {
     return nullptr;
   }
 
+  //===--------------------------------------------------------------------===//
+  // CHERI-related hooks
+  //
+
+  /// CHERI targets have compressed bounds, which place requirements on the
+  /// alignment of allocations based on their size. To guarantee non-overlapping
+  /// bounds for all global symbols we must over-align the symbol if the size is
+  /// not precisely representable. We also add padding at the end to ensure that
+  /// we cannot access another variable that happens to be located in the bytes
+  /// that are accessible after the end of the object due to the bounds having
+  /// been rounded up.
+  virtual TailPaddingAmount
+  getTailPaddingForPreciseBounds(uint64_t Size, const TargetMachine &TM) const {
+    return TailPaddingAmount::None;
+  }
+
+  virtual Align getAlignmentForPreciseBounds(uint64_t Size,
+                                             const TargetMachine &TM) const {
+    return {};
+  }
+
 protected:
   virtual MCSection *SelectSectionForGlobal(const GlobalObject *GO,
                                             SectionKind Kind,
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index cdb9d760606f6..ee0a3ad426abf 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -848,7 +848,17 @@ void AsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
   // If the alignment is specified, we *must* obey it.  Overaligning a global
   // with a specified alignment is a prompt way to break globals emitted to
   // sections and expected to be contiguous (e.g. ObjC metadata).
-  const Align Alignment = getGVAlignment(GV, DL);
+  Align Alignment = getGVAlignment(GV, DL);
+
+  const TailPaddingAmount TailPadding =
+      getObjFileLowering().getTailPaddingForPreciseBounds(Size, TM);
+  const Align PreciseAlignment =
+      getObjFileLowering().getAlignmentForPreciseBounds(Size, TM);
+
+  if (PreciseAlignment > Alignment && !GV->hasSection()) {
+    // Don't increase alignment if a custom section has been specified:
+    Alignment = PreciseAlignment;
+  }
 
   for (auto &Handler : Handlers)
     Handler->setSymbolSize(GVSym, Size);
@@ -857,7 +867,7 @@ void AsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
   if (GVKind.isCommon()) {
     if (Size == 0) Size = 1;   // .comm Foo, 0 is undefined, avoid it.
     // .comm _foo, 42, 4
-    OutStreamer->emitCommonSymbol(GVSym, Size, Alignment);
+    OutStreamer->emitCommonSymbol(GVSym, Size, Alignment, TailPadding);
     return;
   }
 
@@ -890,14 +900,14 @@ void AsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
     // Prefer to simply fall back to .local / .comm in this case.
     if (MAI.getLCOMMDirectiveAlignmentType() != LCOMM::NoAlignment) {
       // .lcomm _foo, 42
-      OutStreamer->emitLocalCommonSymbol(GVSym, Size, Alignment);
+      OutStreamer->emitLocalCommonSymbol(GVSym, Size, Alignment, TailPadding);
       return;
     }
 
     // .local _foo
     OutStreamer->emitSymbolAttribute(GVSym, MCSA_Local);
     // .comm _foo, 42, 4
-    OutStreamer->emitCommonSymbol(GVSym, Size, Alignment);
+    OutStreamer->emitCommonSymbol(GVSym, Size, Alignment, TailPadding);
     return;
   }
 
@@ -925,8 +935,8 @@ void AsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
       emitAlignment(Alignment, GV);
       OutStreamer->emitLabel(MangSym);
 
-      emitGlobalConstant(GV->getDataLayout(),
-                         GV->getInitializer());
+      emitGlobalConstant(GV->getDataLayout(), GV->getInitializer(),
+                         TailPadding);
     }
 
     OutStreamer->addBlankLine();
@@ -965,7 +975,7 @@ void AsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
   if (LocalAlias != EmittedInitSym)
     OutStreamer->emitLabel(LocalAlias);
 
-  emitGlobalConstant(GV->getDataLayout(), GV->getInitializer());
+  emitGlobalConstant(GV->getDataLayout(), GV->getInitializer(), TailPadding);
 
   if (MAI.hasDotTypeDotSizeDirective())
     // .size foo, 42
@@ -4573,6 +4583,7 @@ static void emitGlobalConstantImpl(const DataLayout &DL, const Constant *CV,
 
 /// EmitGlobalConstant - Print a general LLVM constant to the .s file.
 void AsmPrinter::emitGlobalConstant(const DataLayout &DL, const Constant *CV,
+                                    TailPaddingAmount TailPadding,
                                     AliasMapTy *AliasList) {
   uint64_t Size = DL.getTypeAllocSize(CV->getType());
   if (Size)
@@ -4582,6 +4593,10 @@ void AsmPrinter::emitGlobalConstant(const DataLayout &DL, const Constant *CV,
     // look like they are at the same location.
     OutStreamer->emitIntValue(0, 1);
   }
+  if (TailPadding != TailPaddingAmount::None) {
+    OutStreamer->AddComment("Tail padding to ensure precise bounds");
+    OutStreamer->emitZeros(static_cast<uint64_t>(TailPadding));
+  }
   if (!AliasList)
     return;
   // TODO: These remaining aliases are not emitted in the correct location. Need
diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp
index 68929ddc135f3..4b577863d5cdd 100644
--- a/llvm/lib/MC/MCAsmStreamer.cpp
+++ b/llvm/lib/MC/MCAsmStreamer.cpp
@@ -238,16 +238,18 @@ class MCAsmStreamer final : public MCAsmBaseStreamer {
   void emitXCOFFCInfoSym(StringRef Name, StringRef Metadata) override;
 
   void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override;
-  void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
-                        Align ByteAlignment) override;
+  void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size, Align ByteAlignment,
+                        TailPaddingAmount TailPadding) override;
 
   /// Emit a local common (.lcomm) symbol.
   ///
   /// @param Symbol - The common symbol to emit.
   /// @param Size - The size of the common symbol.
   /// @param ByteAlignment - The alignment of the common symbol in bytes.
+  /// @param TailPadding - The number of bytes to pad for precise bounds.
   void emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
-                             Align ByteAlignment) override;
+                             Align ByteAlignment,
+                             TailPaddingAmount TailPadding) override;
 
   void emitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
                     uint64_t Size = 0, Align ByteAlignment = Align(1),
@@ -1098,10 +1100,11 @@ void MCAsmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
 }
 
 void MCAsmStreamer::emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
-                                     Align ByteAlignment) {
+                                     Align ByteAlignment,
+                                     TailPaddingAmount TailPadding) {
   OS << "\t.comm\t";
   Symbol->print(OS, MAI);
-  OS << ',' << Size;
+  OS << ',' << (Size + static_cast<uint64_t>(TailPadding));
 
   if (MAI->getCOMMDirectiveAlignmentIsInBytes())
     OS << ',' << ByteAlignment.value();
@@ -1109,6 +1112,14 @@ void MCAsmStreamer::emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
     OS << ',' << Log2(ByteAlignment);
   EmitEOL();
 
+  if (TailPadding != TailPaddingAmount::None) {
+    // If we added padding, we need to emit an explicit symbol size directive
+    AddComment("explicit size direct...
[truncated]

``````````

</details>


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


More information about the llvm-commits mailing list