From af31642573b26c0f987b89148b65854ea2f5919a Mon Sep 17 00:00:00 2001 From: Nikita Popov 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 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 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 }