[clang] [Clang] Verify data layout consistency (PR #144720)
Nikita Popov via cfe-commits
cfe-commits at lists.llvm.org
Tue Jul 1 00:18:03 PDT 2025
https://github.com/nikic updated https://github.com/llvm/llvm-project/pull/144720
>From af31642573b26c0f987b89148b65854ea2f5919a Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Wed, 18 Jun 2025 14:48:19 +0200
Subject: [PATCH 1/2] [Clang] Verify data layout consistency
Verify that the alignments specified by clang TargetInfo match
the alignments specified by LLVM data layout, which will hopefully
prevent accidental mismatches in the future.
This currently contains opt-outs for a lot of existing mismatches.
I'm also skipping the verification if options like `-malign-double`
are used, or a language that mandates sizes/alignments that differ
from C.
---
clang/lib/CodeGen/CodeGenModule.cpp | 73 +++++++++++++++++++++++++++++
1 file changed, 73 insertions(+)
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 96fdab212beb1..e546b0c643643 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -332,6 +332,76 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
return *TheTargetCodeGenInfo;
}
+static void checkDataLayoutConsistency(const TargetInfo &Target,
+ llvm::LLVMContext &Context,
+ const LangOptions &Opts) {
+#ifndef NDEBUG
+ // Don't verify non-standard ABI configurations.
+ if (Opts.AlignDouble || Opts.OpenCL || Opts.HLSL)
+ return;
+
+ llvm::Triple Triple = Target.getTriple();
+ llvm::DataLayout DL(Target.getDataLayoutString());
+ auto Check = [&](const char *Name, llvm::Type *Ty, unsigned Alignment) {
+ llvm::Align DLAlign = DL.getABITypeAlign(Ty);
+ llvm::Align ClangAlign(Alignment / 8);
+ if (DLAlign != ClangAlign) {
+ llvm::errs() << "For target " << Triple.str() << " type " << Name
+ << " mapping to " << *Ty << " has data layout alignment "
+ << DLAlign.value() << " while clang specifies "
+ << ClangAlign.value() << "\n";
+ abort();
+ }
+ };
+
+ Check("bool", llvm::Type::getIntNTy(Context, Target.BoolWidth),
+ Target.BoolAlign);
+ Check("short", llvm::Type::getIntNTy(Context, Target.ShortWidth),
+ Target.ShortAlign);
+ // FIXME: M68k specifies incorrect wrong int and long alignments in Clang
+ // and incorrect long long alignment in both LLVM and Clang.
+ if (Triple.getArch() != llvm::Triple::m68k) {
+ Check("int", llvm::Type::getIntNTy(Context, Target.IntWidth),
+ Target.IntAlign);
+ Check("long", llvm::Type::getIntNTy(Context, Target.LongWidth),
+ Target.LongAlign);
+ Check("long long", llvm::Type::getIntNTy(Context, Target.LongLongWidth),
+ Target.LongLongAlign);
+ }
+ // FIXME: There are int128 alignment mismatches on multiple targets.
+ if (Target.hasInt128Type() && !Target.getTargetOpts().ForceEnableInt128 &&
+ !Triple.isAMDGPU() && !Triple.isSPIRV() &&
+ Triple.getArch() != llvm::Triple::ve)
+ Check("__int128", llvm::Type::getIntNTy(Context, 128), Target.Int128Align);
+
+ if (Target.hasFloat16Type())
+ Check("half", llvm::Type::getFloatingPointTy(Context, *Target.HalfFormat),
+ Target.HalfAlign);
+ if (Target.hasBFloat16Type())
+ Check("bfloat", llvm::Type::getBFloatTy(Context), Target.BFloat16Align);
+ Check("float", llvm::Type::getFloatingPointTy(Context, *Target.FloatFormat),
+ Target.FloatAlign);
+ // FIXME: AIX specifies wrong double alignment in DataLayout
+ if (!Triple.isOSAIX()) {
+ Check("double",
+ llvm::Type::getFloatingPointTy(Context, *Target.DoubleFormat),
+ Target.DoubleAlign);
+ Check("long double",
+ llvm::Type::getFloatingPointTy(Context, *Target.LongDoubleFormat),
+ Target.LongDoubleAlign);
+ }
+ // FIXME: Wasm has a mismatch in f128 alignment between Clang and LLVM.
+ if (Target.hasFloat128Type() && !Triple.isWasm())
+ Check("__float128", llvm::Type::getFP128Ty(Context), Target.Float128Align);
+ if (Target.hasIbm128Type())
+ Check("__ibm128", llvm::Type::getPPC_FP128Ty(Context), Target.Ibm128Align);
+
+ // FIXME: Clang specifies incorrect pointer alignment for m68k.
+ if (Triple.getArch() != llvm::Triple::m68k)
+ Check("void*", llvm::PointerType::getUnqual(Context), Target.PointerAlign);
+#endif
+}
+
CodeGenModule::CodeGenModule(ASTContext &C,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
const HeaderSearchOptions &HSO,
@@ -487,6 +557,9 @@ CodeGenModule::CodeGenModule(ASTContext &C,
llvm::sort(this->MSHotPatchFunctions);
}
+
+ if (!Context.getAuxTargetInfo())
+ checkDataLayoutConsistency(Context.getTargetInfo(), LLVMContext, LangOpts);
}
CodeGenModule::~CodeGenModule() {}
>From e0b1d80e09a1818e9ef2da76ca2e928dfe92c0a7 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Tue, 1 Jul 2025 09:08:40 +0200
Subject: [PATCH 2/2] m68k alignments have been (partially) fixed
---
clang/lib/CodeGen/CodeGenModule.cpp | 18 +++++++-----------
1 file changed, 7 insertions(+), 11 deletions(-)
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index e546b0c643643..e6d150f7e13d6 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -358,16 +358,14 @@ static void checkDataLayoutConsistency(const TargetInfo &Target,
Target.BoolAlign);
Check("short", llvm::Type::getIntNTy(Context, Target.ShortWidth),
Target.ShortAlign);
- // FIXME: M68k specifies incorrect wrong int and long alignments in Clang
- // and incorrect long long alignment in both LLVM and Clang.
- if (Triple.getArch() != llvm::Triple::m68k) {
- Check("int", llvm::Type::getIntNTy(Context, Target.IntWidth),
- Target.IntAlign);
- Check("long", llvm::Type::getIntNTy(Context, Target.LongWidth),
- Target.LongAlign);
+ Check("int", llvm::Type::getIntNTy(Context, Target.IntWidth),
+ Target.IntAlign);
+ Check("long", llvm::Type::getIntNTy(Context, Target.LongWidth),
+ Target.LongAlign);
+ // FIXME: M68k specifies incorrect long long alignment in both LLVM and Clang.
+ if (Triple.getArch() != llvm::Triple::m68k)
Check("long long", llvm::Type::getIntNTy(Context, Target.LongLongWidth),
Target.LongLongAlign);
- }
// FIXME: There are int128 alignment mismatches on multiple targets.
if (Target.hasInt128Type() && !Target.getTargetOpts().ForceEnableInt128 &&
!Triple.isAMDGPU() && !Triple.isSPIRV() &&
@@ -396,9 +394,7 @@ static void checkDataLayoutConsistency(const TargetInfo &Target,
if (Target.hasIbm128Type())
Check("__ibm128", llvm::Type::getPPC_FP128Ty(Context), Target.Ibm128Align);
- // FIXME: Clang specifies incorrect pointer alignment for m68k.
- if (Triple.getArch() != llvm::Triple::m68k)
- Check("void*", llvm::PointerType::getUnqual(Context), Target.PointerAlign);
+ Check("void*", llvm::PointerType::getUnqual(Context), Target.PointerAlign);
#endif
}
More information about the cfe-commits
mailing list