[clang] [llvm] [CHERI][RISCV][MC] Add support for aligning and tail-padding globals for precise bounds tracking on CHERI targets. (PR #203872)
Owen Anderson via cfe-commits
cfe-commits at lists.llvm.org
Mon Jul 6 07:59:31 PDT 2026
https://github.com/resistor updated https://github.com/llvm/llvm-project/pull/203872
>From b9e9dee9d6ff719e40f1599096114ccc4e3f4e8d Mon Sep 17 00:00:00 2001
From: Owen Anderson <resistor at mac.com>
Date: Wed, 10 Jun 2026 14:53:59 +0200
Subject: [PATCH 1/2] [CHERI][MTE][MC] Add shared support for aligning globals
to an "alignment granule", which is applied to both the alignment and the
allocated size.
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 for AArch64/MTE, and for RISCV Y-base and XCheriot. Support for other targets (such as AArch64/Morello) but is left as future work here.
Based on https://github.com/llvm/llvm-project/pull/121957
Co-authored-by: Florian Mayer <fmayer at google.com>
---
clang/test/CodeGen/memtag-globals-asm.cpp | 61 +++++++++++--------
llvm/include/llvm/CodeGen/AsmPrinter.h | 14 +++++
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 60 +++++++-----------
llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp | 7 +++
llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp | 3 +-
llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp | 21 +++++++
.../test/CodeGen/RISCV/cheri-global-bounds.ll | 26 ++++++++
llvm/test/MC/AArch64/global-tagging.ll | 4 +-
8 files changed, 129 insertions(+), 67 deletions(-)
create mode 100644 llvm/test/CodeGen/RISCV/cheri-global-bounds.ll
diff --git a/clang/test/CodeGen/memtag-globals-asm.cpp b/clang/test/CodeGen/memtag-globals-asm.cpp
index fb3958dd8bcb6..30e43beec1073 100644
--- a/clang/test/CodeGen/memtag-globals-asm.cpp
+++ b/clang/test/CodeGen/memtag-globals-asm.cpp
@@ -53,12 +53,12 @@
// CHECK-A: .memtag global_int
// CHECK-A: .globl global_int
// CHECK-A: .p2align 4, 0x0
-// CHECK-A: .zero 16
-// CHECK-A: .size global_int, 16
+// CHECK-A: .size global_int, 4
+// CHECK-A: .p2align 4, 0x0
int global_int;
// CHECK-B: .memtag _ZL9local_int
// CHECK-B: .local _ZL9local_int
-// CHECK-B: .comm _ZL9local_int,16,16
+// CHECK-B: .comm _ZL9local_int,4,16
static int local_int;
// CHECK-C: .memtag _ZL12local_buffer
@@ -69,16 +69,16 @@ static char local_buffer[16];
// CHECK-D: .p2align 4, 0x0
// CHECK-D: _ZL22local_buffer_local_end:
// CHECK-D: .xword _ZL12local_buffer+16
-// CHECK-D: .zero 8
-// CHECK-D: .size _ZL22local_buffer_local_end, 16
+// CHECK-D: .size _ZL22local_buffer_local_end, 8
+// CHECK-D: .p2align 4, 0x0
static char* local_buffer_local_end = &local_buffer[16];
// CHECK-E: .memtag local_buffer_global_end
// CHECK-E: .globl local_buffer_global_end
// CHECK-E .p2align 4, 0x0
// CHECK-E: local_buffer_global_end:
// CHECK-E: .xword _ZL12local_buffer+16
-// CHECK-E: .zero 8
-// CHECK-E: .size local_buffer_global_end, 16
+// CHECK-E: .size local_buffer_global_end, 8
+// CHECK-E: .p2align 4, 0x0
char* local_buffer_global_end = &local_buffer[16];
// CHECK-F: .memtag global_buffer
@@ -91,14 +91,15 @@ char global_buffer[16];
// CHECK-G: .p2align 4, 0x0
// CHECK-G: _ZL23global_buffer_local_end:
// CHECK-G: .xword global_buffer+16
-// CHECK-G: .zero 8
-// CHECK-G: .size _ZL23global_buffer_local_end, 16
+// CHECK-G: .size _ZL23global_buffer_local_end, 8
+// CHECK-F: .p2align 4, 0x0
static char* global_buffer_local_end = &global_buffer[16];
// CHECK-H: .memtag global_buffer_global_end
// CHECK-H: .p2align 4, 0x0
// CHECK-H: global_buffer_global_end:
// CHECK-H: .xword global_buffer+16
-// CHECK-H: .size global_buffer_global_end, 16
+// CHECK-H: .size global_buffer_global_end, 8
+// CHECK-H: .p2align 4, 0x0
char* global_buffer_global_end = &global_buffer[16];
// CHECK-S-NOT: .memtag zero_sized
@@ -115,8 +116,8 @@ class MyClass {
// CHECK-I: .memtag _ZN7MyClass12my_class_intE
// CHECK-I: .globl _ZN7MyClass12my_class_intE
// CHECK-I: .p2align 4, 0x0
-// CHECK-I: .zero 16
-// CHECK-I: .size _ZN7MyClass12my_class_intE, 16
+// CHECK-I: .size _ZN7MyClass12my_class_intE, 4
+// CHECK-I: .p2align 4, 0x0
int MyClass::my_class_int;
// CHECK-NOT: .memtag _ZN7MyClass18my_class_const_intE
const int MyClass::my_class_const_int = 1;
@@ -124,32 +125,33 @@ const int MyClass::my_class_const_int = 1;
// CHECK-J: .memtag global_my_class
// CHECK-J: .globl global_my_class
// CHECK-J: .p2align 4, 0x0
-// CHECK-J: .zero 8
-// CHECK-J: .size global_my_class, 16
+// CHECK-J: .size global_my_class, 8
+// CHECK-J: .p2align 4, 0x0
MyClass global_my_class;
// CHECK-K: .memtag _ZL14local_my_class
// CHECK-K: .p2align 4, 0x0
-// CHECK-K: .zero 8
-// CHECK-K: .size _ZL14local_my_class, 16
+// CHECK-K: .size _ZL14local_my_class, 8
+// CHECK-K: .p2align 4, 0x0
static MyClass local_my_class;
// CHECK-NOT: .memtag _ZL18local_const_string
static const char local_const_string[] = "this is a local string";
// CHECK-L: .memtag _ZL12local_string
// CHECK-L: .p2align 4, 0x0
-// CHECK-L: .zero 9
-// CHECK-L: .size _ZL12local_string, 32
+// CHECK-L: .size _ZL12local_string, 23
+// CHECK-L: .p2align 4, 0x0
static char local_string[] = "this is a local string";
// CHECK-M: .memtag global_atomic_int
// CHECK-M: .globl global_atomic_int
// CHECK-M: .p2align 4, 0x0
-// CHECK-M: .zero 16
-// CHECK-M: .size global_atomic_int, 16
+// CHECK-M: .size global_atomic_int, 4
+// CHECK-M: .p2align 4, 0x0
_Atomic(int) global_atomic_int;
// CHECK-N: .memtag _ZL16local_atomic_int
// CHECK-N: .local _ZL16local_atomic_int
-// CHECK-N: .comm _ZL16local_atomic_int,16,16
+// CHECK-N: .comm _ZL16local_atomic_int,4,16
+// CHECK-N: .p2align 4, 0x0
static _Atomic(int) local_atomic_int;
union MyUnion {
@@ -160,12 +162,13 @@ union MyUnion {
// CHECK-O: .memtag global_union
// CHECK-O: .globl global_union
// CHECK-O: .p2align 4, 0x0
-// CHECK-O: .zero 16
-// CHECK-O: .size global_union, 16
+// CHECK-O: .size global_union, 4
+// CHECK-O: .p2align 4, 0x0
MyUnion global_union;
// CHECK-P: .memtag _ZL11local_union
// CHECK-P: .local _ZL11local_union
-// CHECK-P: .comm _ZL11local_union,16,16
+// CHECK-P: .comm _ZL11local_union,4,16
+// CHECK-P: .p2align 4, 0x0
static MyUnion local_union;
// CHECK-NOT: .memtag {{.*}}global_tls
@@ -197,7 +200,8 @@ const void* export_pointers(int c) {
int f(int x) {
// CHECK-R: .memtag _ZZ1fiE12function_int
// CHECK-R: .local _ZZ1fiE12function_int
- // CHECK-R: .comm _ZZ1fiE12function_int,16,16
+ // CHECK-R: .comm _ZZ1fiE12function_int,4,16
+ // CHECK-R: .p2align 4, 0x0
static int function_int = 0;
/// Prevent non-const `f` from being promoted to a constant and inlined.
function_int += x;
@@ -277,6 +281,13 @@ int f(int x) {
function_int;
}
+// CHECK-R: .memtag global_overaligned_char
+// CHECK-R: .globl global_overaligned_char
+// CHECK-R: .p2align 4, 0x0
+// CHECK-R: .size global_overaligned_char, 1
+// CHECK-R: .p2align 4, 0x0
+alignas(16) char global_overaligned_char;
+
typedef void (*func_t)(void);
#define CONSTRUCTOR(section_name) \
__attribute__((used)) __attribute__((section(section_name)))
diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h
index f6f0f7348836e..6436b3a46d7d7 100644
--- a/llvm/include/llvm/CodeGen/AsmPrinter.h
+++ b/llvm/include/llvm/CodeGen/AsmPrinter.h
@@ -534,6 +534,11 @@ class LLVM_ABI AsmPrinter : public MachineFunctionPass {
/// Emit the specified global variable to the .s file.
virtual void emitGlobalVariable(const GlobalVariable *GV);
+ /// Emit the specified global variable to the .s file, with an explicit
+ /// alignment granule applied to both address and size.
+ virtual void emitGlobalVariable(const GlobalVariable *GV,
+ MaybeAlign AlignmentGranule);
+
/// Check to see if the specified global is a special global used by LLVM. If
/// so, emit it and return true, otherwise do nothing and return false.
bool emitSpecialLLVMGlobal(const GlobalVariable *GV);
@@ -1008,6 +1013,15 @@ class LLVM_ABI AsmPrinter : public MachineFunctionPass {
virtual bool shouldEmitWeakSwiftAsyncExtendedFramePointerFlags() const {
return false;
}
+
+ /// Returns a optional minimum alignment that applies to both the address and
+ /// the allocation size of the global. This is used for systems like CHERI and
+ /// MTE that impose a minimum alignment, and require globals to be padded to
+ /// that alignment.
+ virtual MaybeAlign
+ getRequiredGlobalAlignmentGranule(const GlobalVariable &GV) {
+ return std::nullopt;
+ };
};
LLVM_ABI void setupModuleAsmPrinter(Module &M, ModuleAnalysisManager &MAM,
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index aedc4956f1bd8..dd4a9ec51999e 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -783,6 +783,14 @@ MCSymbol *AsmPrinter::getSymbolPreferLocal(const GlobalValue &GV) const {
/// EmitGlobalVariable - Emit the specified global variable to the .s file.
void AsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
+ MaybeAlign AlignmentGranule = getRequiredGlobalAlignmentGranule(*GV);
+ emitGlobalVariable(GV, AlignmentGranule);
+ if (AlignmentGranule)
+ OutStreamer->emitValueToAlignment(*AlignmentGranule);
+}
+
+void AsmPrinter::emitGlobalVariable(const GlobalVariable *GV,
+ MaybeAlign AlignmentGranule) {
bool IsEmuTLSVar = TM.useEmulatedTLS() && GV->isThreadLocal();
assert(!(IsEmuTLSVar && GV->hasCommonLinkage()) &&
"No emulated TLS variables in the common section");
@@ -848,7 +856,16 @@ 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);
+ //
+ // If we get passed in an explicit alignment granule, it is up to the caller
+ // to ensure that is not the case (i.e. that the GV is not in a section).
+ Align Alignment = getGVAlignment(GV, DL);
+
+ if (AlignmentGranule) {
+ assert(!GV->hasSection());
+ if (Alignment < *AlignmentGranule)
+ Alignment = *AlignmentGranule;
+ }
for (auto &Handler : Handlers)
Handler->setSymbolSize(GVSym, Size);
@@ -925,8 +942,7 @@ void AsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
emitAlignment(Alignment, GV);
OutStreamer->emitLabel(MangSym);
- emitGlobalConstant(GV->getDataLayout(),
- GV->getInitializer());
+ emitGlobalConstant(GV->getDataLayout(), GV->getInitializer());
}
OutStreamer->addBlankLine();
@@ -2837,37 +2853,6 @@ static bool shouldTagGlobal(const llvm::GlobalVariable &G) {
return globalSize(G) > 0;
}
-static void tagGlobalDefinition(Module &M, GlobalVariable *G) {
- uint64_t SizeInBytes = globalSize(*G);
-
- uint64_t NewSize = alignTo(SizeInBytes, 16);
- if (SizeInBytes != NewSize) {
- // Pad the initializer out to the next multiple of 16 bytes.
- llvm::SmallVector<uint8_t> Init(NewSize - SizeInBytes, 0);
- Constant *Padding = ConstantDataArray::get(M.getContext(), Init);
- Constant *Initializer = G->getInitializer();
- Initializer = ConstantStruct::getAnon({Initializer, Padding});
- auto *NewGV = new GlobalVariable(
- M, Initializer->getType(), G->isConstant(), G->getLinkage(),
- Initializer, "", G, G->getThreadLocalMode(), G->getAddressSpace());
- NewGV->copyAttributesFrom(G);
- NewGV->setComdat(G->getComdat());
- NewGV->copyMetadata(G, 0);
-
- NewGV->takeName(G);
- G->replaceAllUsesWith(NewGV);
- G->eraseFromParent();
- G = NewGV;
- }
-
- if (G->getAlign().valueOrOne() < 16)
- G->setAlignment(Align(16));
-
- // Ensure that tagged globals don't get merged by ICF - as they should have
- // different tags at runtime.
- G->setUnnamedAddr(GlobalValue::UnnamedAddr::None);
-}
-
static void removeMemtagFromGlobal(GlobalVariable &G) {
auto Meta = G.getSanitizerMetadata();
Meta.Memtag = false;
@@ -2881,7 +2866,6 @@ bool AsmPrinter::doFinalization(Module &M) {
MF = nullptr;
const Triple &Target = TM.getTargetTriple();
- std::vector<GlobalVariable *> GlobalsToTag;
for (GlobalVariable &G : M.globals()) {
if (G.isDeclaration() || !G.isTagged())
continue;
@@ -2891,10 +2875,10 @@ bool AsmPrinter::doFinalization(Module &M) {
assert(!G.isTagged());
continue;
}
- GlobalsToTag.push_back(&G);
+ // Ensure that tagged globals don't get merged by ICF - as they should have
+ // different tags at runtime.
+ G.setUnnamedAddr(GlobalValue::UnnamedAddr::None);
}
- for (GlobalVariable *G : GlobalsToTag)
- tagGlobalDefinition(M, G);
// Gather all GOT equivalent globals in the module. We really need two
// passes over the globals: one to compute and another to avoid its emission
diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index 156c12c5ab8dd..7206bc464c022 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -347,6 +347,8 @@ class AArch64AsmPrinter : public AsmPrinter {
void emitFunctionBodyEnd() override;
void emitGlobalAlias(const Module &M, const GlobalAlias &GA) override;
+ MaybeAlign
+ getRequiredGlobalAlignmentGranule(const GlobalVariable &GV) override;
MCSymbol *GetCPISymbol(unsigned CPID) const override;
void emitEndOfAsmFile(Module &M) override;
@@ -4031,6 +4033,11 @@ const MCExpr *AArch64AsmPrinter::lowerConstant(const Constant *CV,
return AsmPrinter::lowerConstant(CV, BaseCV, Offset);
}
+MaybeAlign
+AArch64AsmPrinter::getRequiredGlobalAlignmentGranule(const GlobalVariable &GV) {
+ return GV.isTagged() ? MaybeAlign(16) : std::nullopt;
+}
+
char AArch64AsmPrinter::ID = 0;
INITIALIZE_PASS(AArch64AsmPrinter, "aarch64-asm-printer",
diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
index 51f2ff4a68be7..55691d2d694fa 100644
--- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -2880,8 +2880,7 @@ void PPCAIXAsmPrinter::emitGlobalVariableHelper(const GlobalVariable *GV) {
AliasList[getAliasOffset(GA->getAliasee())].push_back(GA);
// Emit alias label and element value for global variable.
- emitGlobalConstant(GV->getDataLayout(), GV->getInitializer(),
- &AliasList);
+ emitGlobalConstant(GV->getDataLayout(), GV->getInitializer(), &AliasList);
}
void PPCAIXAsmPrinter::emitFunctionDescriptor() {
diff --git a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
index dbda25c34cee0..8ad775db18197 100644
--- a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
+++ b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
@@ -39,6 +39,7 @@
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/CHERICapabilityFormat.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/RISCVISAInfo.h"
@@ -131,6 +132,9 @@ class RISCVAsmPrinter : public AsmPrinter {
void emitSled(const MachineInstr *MI, SledKind Kind);
void lowerToMCInst(const MachineInstr *MI, MCInst &OutMI);
+
+ MaybeAlign
+ getRequiredGlobalAlignmentGranule(const GlobalVariable &GV) override;
};
} // namespace
@@ -1315,6 +1319,23 @@ void RISCVAsmPrinter::emitMachineConstantPoolValue(
OutStreamer->emitValue(Expr, Size);
}
+MaybeAlign
+RISCVAsmPrinter::getRequiredGlobalAlignmentGranule(const GlobalVariable &GV) {
+ const MCSubtargetInfo &MCSTI = TM.getMCSubtargetInfo();
+ uint64_t Size = GV.getGlobalSize(getDataLayout());
+ if (MCSTI.hasFeature(RISCV::FeatureVendorXCheriot))
+ return CHERIoTCapabilityFormat::getRequiredAlignment(Size);
+
+ if (MCSTI.hasFeature(RISCV::FeatureStdExtY)) {
+ if (MCSTI.hasFeature(RISCV::Feature64Bit))
+ return RV64YCapabilityFormat::getRequiredAlignment(Size);
+ else
+ return RV32YCapabilityFormat::getRequiredAlignment(Size);
+ }
+
+ return std::nullopt;
+}
+
char RISCVAsmPrinter::ID = 0;
INITIALIZE_PASS(RISCVAsmPrinter, "riscv-asm-printer", "RISC-V Assembly Printer",
diff --git a/llvm/test/CodeGen/RISCV/cheri-global-bounds.ll b/llvm/test/CodeGen/RISCV/cheri-global-bounds.ll
new file mode 100644
index 0000000000000..4f0df7bbe20ec
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/cheri-global-bounds.ll
@@ -0,0 +1,26 @@
+; RUN: llc -mtriple riscv32 -mattr=+experimental-y -target-abi il32pc64 %s -o - | FileCheck -check-prefix=RVY32 %s
+; RUN: llc -mtriple riscv64 -mattr=+experimental-y -target-abi l64pc128 %s -o - | FileCheck -check-prefix=RVY64 %s
+; RUN: llc -mtriple riscv64 -mattr=+xcheriot -target-abi cheriot %s -o - | FileCheck -check-prefix=CHERIOT %s
+
+ at global1 = global [6995 x i8] zeroinitializer, align 1
+
+; RVY32-LABEL: .globl global1
+; RVY32-NEXT: .p2align 7, 0x0
+; RVY32-NEXT: global1:
+; RVY32-NEXT: .zero 6995
+; RVY32-NEXT: .size global1, 6995
+; RVY32: .p2align 7, 0x0
+
+; RVY64-LABEL: .globl global1
+; RVY64-NEXT: .p2align 3, 0x0
+; RVY64-NEXT: global1:
+; RVY64-NEXT: .zero 6995
+; RVY64-NEXT: .size global1, 6995
+; RVY64: .p2align 3, 0x0
+
+; CHERIOT-LABEL: .globl global1
+; CHERIOT-NEXT: .p2align 4, 0x0
+; CHERIOT-NEXT: global1:
+; CHERIOT-NEXT: .zero 6995
+; CHERIOT-NEXT: .size global1, 6995
+; CHERIOT: .p2align 4, 0x0
diff --git a/llvm/test/MC/AArch64/global-tagging.ll b/llvm/test/MC/AArch64/global-tagging.ll
index 29463b1b86ff4..19f4bd2a58596 100644
--- a/llvm/test/MC/AArch64/global-tagging.ll
+++ b/llvm/test/MC/AArch64/global-tagging.ll
@@ -47,10 +47,10 @@
; CHECK-ASM: .memtag internal_four
; CHECK-ASM .p2align 4
-; CHECK-ASM: .size internal_four, 16
+; CHECK-ASM: .size internal_four, 4
; CHECK-ASM: .memtag four
; CHECK-ASM .p2align 4
-; CHECK-ASM: .size four, 16
+; CHECK-ASM: .size four, 4
; CHECK-ASM: .memtag sixteen
; CHECK-ASM .p2align 4
; CHECK-ASM: .size sixteen, 16
>From dba849fefdcd702cf59e5aa063129467d271c026 Mon Sep 17 00:00:00 2001
From: Owen Anderson <resistor at mac.com>
Date: Mon, 6 Jul 2026 16:59:00 +0200
Subject: [PATCH 2/2] Restore original MTE behavior of increasing symbol size
to include padding.
---
clang/test/CodeGen/memtag-globals-asm.cpp | 30 +++++++++----------
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 1 +
.../test/CodeGen/RISCV/cheri-global-bounds.ll | 6 ++--
3 files changed, 19 insertions(+), 18 deletions(-)
diff --git a/clang/test/CodeGen/memtag-globals-asm.cpp b/clang/test/CodeGen/memtag-globals-asm.cpp
index 30e43beec1073..9d8b77fb06a64 100644
--- a/clang/test/CodeGen/memtag-globals-asm.cpp
+++ b/clang/test/CodeGen/memtag-globals-asm.cpp
@@ -53,12 +53,12 @@
// CHECK-A: .memtag global_int
// CHECK-A: .globl global_int
// CHECK-A: .p2align 4, 0x0
-// CHECK-A: .size global_int, 4
+// CHECK-A: .size global_int, 16
// CHECK-A: .p2align 4, 0x0
int global_int;
// CHECK-B: .memtag _ZL9local_int
// CHECK-B: .local _ZL9local_int
-// CHECK-B: .comm _ZL9local_int,4,16
+// CHECK-B: .comm _ZL9local_int,16,16
static int local_int;
// CHECK-C: .memtag _ZL12local_buffer
@@ -69,7 +69,7 @@ static char local_buffer[16];
// CHECK-D: .p2align 4, 0x0
// CHECK-D: _ZL22local_buffer_local_end:
// CHECK-D: .xword _ZL12local_buffer+16
-// CHECK-D: .size _ZL22local_buffer_local_end, 8
+// CHECK-D: .size _ZL22local_buffer_local_end, 16
// CHECK-D: .p2align 4, 0x0
static char* local_buffer_local_end = &local_buffer[16];
// CHECK-E: .memtag local_buffer_global_end
@@ -77,7 +77,7 @@ static char* local_buffer_local_end = &local_buffer[16];
// CHECK-E .p2align 4, 0x0
// CHECK-E: local_buffer_global_end:
// CHECK-E: .xword _ZL12local_buffer+16
-// CHECK-E: .size local_buffer_global_end, 8
+// CHECK-E: .size local_buffer_global_end, 16
// CHECK-E: .p2align 4, 0x0
char* local_buffer_global_end = &local_buffer[16];
@@ -91,14 +91,14 @@ char global_buffer[16];
// CHECK-G: .p2align 4, 0x0
// CHECK-G: _ZL23global_buffer_local_end:
// CHECK-G: .xword global_buffer+16
-// CHECK-G: .size _ZL23global_buffer_local_end, 8
+// CHECK-G: .size _ZL23global_buffer_local_end, 16
// CHECK-F: .p2align 4, 0x0
static char* global_buffer_local_end = &global_buffer[16];
// CHECK-H: .memtag global_buffer_global_end
// CHECK-H: .p2align 4, 0x0
// CHECK-H: global_buffer_global_end:
// CHECK-H: .xword global_buffer+16
-// CHECK-H: .size global_buffer_global_end, 8
+// CHECK-H: .size global_buffer_global_end, 16
// CHECK-H: .p2align 4, 0x0
char* global_buffer_global_end = &global_buffer[16];
@@ -116,7 +116,7 @@ class MyClass {
// CHECK-I: .memtag _ZN7MyClass12my_class_intE
// CHECK-I: .globl _ZN7MyClass12my_class_intE
// CHECK-I: .p2align 4, 0x0
-// CHECK-I: .size _ZN7MyClass12my_class_intE, 4
+// CHECK-I: .size _ZN7MyClass12my_class_intE, 16
// CHECK-I: .p2align 4, 0x0
int MyClass::my_class_int;
// CHECK-NOT: .memtag _ZN7MyClass18my_class_const_intE
@@ -125,12 +125,12 @@ const int MyClass::my_class_const_int = 1;
// CHECK-J: .memtag global_my_class
// CHECK-J: .globl global_my_class
// CHECK-J: .p2align 4, 0x0
-// CHECK-J: .size global_my_class, 8
+// CHECK-J: .size global_my_class, 16
// CHECK-J: .p2align 4, 0x0
MyClass global_my_class;
// CHECK-K: .memtag _ZL14local_my_class
// CHECK-K: .p2align 4, 0x0
-// CHECK-K: .size _ZL14local_my_class, 8
+// CHECK-K: .size _ZL14local_my_class, 16
// CHECK-K: .p2align 4, 0x0
static MyClass local_my_class;
@@ -138,19 +138,19 @@ static MyClass local_my_class;
static const char local_const_string[] = "this is a local string";
// CHECK-L: .memtag _ZL12local_string
// CHECK-L: .p2align 4, 0x0
-// CHECK-L: .size _ZL12local_string, 23
+// CHECK-L: .size _ZL12local_string, 32
// CHECK-L: .p2align 4, 0x0
static char local_string[] = "this is a local string";
// CHECK-M: .memtag global_atomic_int
// CHECK-M: .globl global_atomic_int
// CHECK-M: .p2align 4, 0x0
-// CHECK-M: .size global_atomic_int, 4
+// CHECK-M: .size global_atomic_int, 16
// CHECK-M: .p2align 4, 0x0
_Atomic(int) global_atomic_int;
// CHECK-N: .memtag _ZL16local_atomic_int
// CHECK-N: .local _ZL16local_atomic_int
-// CHECK-N: .comm _ZL16local_atomic_int,4,16
+// CHECK-N: .comm _ZL16local_atomic_int,16,16
// CHECK-N: .p2align 4, 0x0
static _Atomic(int) local_atomic_int;
@@ -162,12 +162,12 @@ union MyUnion {
// CHECK-O: .memtag global_union
// CHECK-O: .globl global_union
// CHECK-O: .p2align 4, 0x0
-// CHECK-O: .size global_union, 4
+// CHECK-O: .size global_union, 16
// CHECK-O: .p2align 4, 0x0
MyUnion global_union;
// CHECK-P: .memtag _ZL11local_union
// CHECK-P: .local _ZL11local_union
-// CHECK-P: .comm _ZL11local_union,4,16
+// CHECK-P: .comm _ZL11local_union,16,16
// CHECK-P: .p2align 4, 0x0
static MyUnion local_union;
@@ -200,7 +200,7 @@ const void* export_pointers(int c) {
int f(int x) {
// CHECK-R: .memtag _ZZ1fiE12function_int
// CHECK-R: .local _ZZ1fiE12function_int
- // CHECK-R: .comm _ZZ1fiE12function_int,4,16
+ // CHECK-R: .comm _ZZ1fiE12function_int,16,16
// CHECK-R: .p2align 4, 0x0
static int function_int = 0;
/// Prevent non-const `f` from being promoted to a constant and inlined.
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index dd4a9ec51999e..608674676c34c 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -863,6 +863,7 @@ void AsmPrinter::emitGlobalVariable(const GlobalVariable *GV,
if (AlignmentGranule) {
assert(!GV->hasSection());
+ Size = alignTo(Size, *AlignmentGranule);
if (Alignment < *AlignmentGranule)
Alignment = *AlignmentGranule;
}
diff --git a/llvm/test/CodeGen/RISCV/cheri-global-bounds.ll b/llvm/test/CodeGen/RISCV/cheri-global-bounds.ll
index 4f0df7bbe20ec..0443338855e62 100644
--- a/llvm/test/CodeGen/RISCV/cheri-global-bounds.ll
+++ b/llvm/test/CodeGen/RISCV/cheri-global-bounds.ll
@@ -8,19 +8,19 @@
; RVY32-NEXT: .p2align 7, 0x0
; RVY32-NEXT: global1:
; RVY32-NEXT: .zero 6995
-; RVY32-NEXT: .size global1, 6995
+; RVY32-NEXT: .size global1, 7040
; RVY32: .p2align 7, 0x0
; RVY64-LABEL: .globl global1
; RVY64-NEXT: .p2align 3, 0x0
; RVY64-NEXT: global1:
; RVY64-NEXT: .zero 6995
-; RVY64-NEXT: .size global1, 6995
+; RVY64-NEXT: .size global1, 7000
; RVY64: .p2align 3, 0x0
; CHERIOT-LABEL: .globl global1
; CHERIOT-NEXT: .p2align 4, 0x0
; CHERIOT-NEXT: global1:
; CHERIOT-NEXT: .zero 6995
-; CHERIOT-NEXT: .size global1, 6995
+; CHERIOT-NEXT: .size global1, 7008
; CHERIOT: .p2align 4, 0x0
More information about the cfe-commits
mailing list