[clang] [NFC] Split PaddingClearer out into a CodeGenUtils shared directory (PR #215823)
Erich Keane via cfe-commits
cfe-commits at lists.llvm.org
Wed Aug 12 08:23:07 PDT 2026
https://github.com/erichkeane created https://github.com/llvm/llvm-project/pull/215823
We have plenty of stuff that needs to be shared between Classic-Codegen and CIR, that we've been copy/pasting too often. This patch proposes/produces a shared directory of CodeGenUtils that will be for things that don't really belong elsewhere. This functionality (calculating padding for __builtin_clear_padding) is both too complex to copy/paste, and doesn't really have reason to live anywhere except CodeGen/CIR-CodeGen.
The type has been split out as faithfully as possible, with only minor changes to make it LLVM-agnostic. The part of it that is required to generate the LLVM-IR is left in CGBuiltin.cpp, but takes the list of padding-intervals as an input, which will be useful for CIR's representation.
>From 3518d08a4d299cbfb528864c22e1b2a2dc645e0a Mon Sep 17 00:00:00 2001
From: erichkeane <ekeane at nvidia.com>
Date: Wed, 12 Aug 2026 06:38:46 -0700
Subject: [PATCH] [NFC] Split PaddingClearer out into a CodeGenUtils shared
directory
We have plenty of stuff that needs to be shared between Classic-Codegen
and CIR, that we've been copy/pasting too often. This patch
proposes/produces a shared directory of CodeGenUtils that will be for
things that don't really belong elsewhere. This functionality
(calculating padding for __builtin_clear_padding) is both too complex to
copy/paste, and doesn't really have reason to live anywhere except
CodeGen/CIR-CodeGen.
The type has been split out as faithfully as possible, with only minor
changes to make it LLVM-agnostic. The part of it that is required to
generate the LLVM-IR is left in CGBuiltin.cpp, but takes the list of
padding-intervals as an input, which will be useful for CIR's
representation.
---
.../include/clang/CodeGenUtils/CodeGenUtils.h | 283 +++++++++++++
clang/lib/CodeGen/CGBuiltin.cpp | 395 +++---------------
2 files changed, 352 insertions(+), 326 deletions(-)
create mode 100644 clang/include/clang/CodeGenUtils/CodeGenUtils.h
diff --git a/clang/include/clang/CodeGenUtils/CodeGenUtils.h b/clang/include/clang/CodeGenUtils/CodeGenUtils.h
new file mode 100644
index 0000000000000..2da4ddc5aea36
--- /dev/null
+++ b/clang/include/clang/CodeGenUtils/CodeGenUtils.h
@@ -0,0 +1,283 @@
+//===--- CodeGenUtils.h - Shared Classic CodeGen/CIR CodeGen Utils--C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/APFloat.h"
+
+#include <algorithm>
+#include <utility>
+
+namespace clang::CodeGenUtils {
+// A type that helps represent a padding interval.
+struct BitInterval {
+ // [First, Last)
+ uint64_t First;
+ uint64_t Last;
+};
+
+// PaddingCalculator is a utility class that calculates the padding bits in a
+// c/c++ type. It traverses the type recursively, collecting occupied
+// bit intervals, and then computes the padding intervals.
+// If a byte only contains some padding bits, it gets intervals for only those
+// bits. This is the case for bit-fields.
+struct PaddingCalculator {
+ PaddingCalculator(const ASTContext &Ctx, const TargetInfo &TI,
+ unsigned PointerSizeInBits)
+ : Ctx(Ctx), TI(TI), PointerSizeInBits(PointerSizeInBits) {}
+
+ void run(QualType Ty) {
+ OccuppiedIntervals.clear();
+ Stack.clear();
+
+ TySizeInBits = Ctx.getTypeSize(Ty);
+
+ Stack.push_back(Data{0, Ty, true});
+ while (!Stack.empty()) {
+ Data Current = Stack.back();
+ Stack.pop_back();
+ Visit(Current);
+ }
+ MergeOccuppiedIntervals();
+ }
+
+ llvm::SmallVector<BitInterval> GetPaddingIntervals() {
+ llvm::SmallVector<BitInterval> Results;
+ if (OccuppiedIntervals.size() == 1 &&
+ OccuppiedIntervals.front().First == 0 &&
+ OccuppiedIntervals.front().Last == TySizeInBits) {
+ return Results;
+ }
+ Results.reserve(OccuppiedIntervals.size() + 1);
+ uint64_t CurrentPos = 0;
+ for (const BitInterval &OccupiedInterval : OccuppiedIntervals) {
+ if (OccupiedInterval.First > CurrentPos) {
+ Results.push_back(BitInterval{CurrentPos, OccupiedInterval.First});
+ }
+ CurrentPos = OccupiedInterval.Last;
+ }
+ if (TySizeInBits > CurrentPos) {
+ Results.push_back(BitInterval{CurrentPos, TySizeInBits});
+ }
+ return Results;
+ }
+
+private:
+ struct Data {
+ uint64_t StartBitOffset;
+ QualType Ty;
+ bool VisitVirtualBase;
+ };
+
+ // Return the number of non padding bits of a scalar type.
+ //
+ // The property that we specifically care about here is whether the scalar
+ // type has padding bits, i.e. are there bits in the type which are not
+ // specified by the ABI.
+ //
+ // We currently don't care about this anywhere else in clang: layout cares
+ // about the ABI size, calling convention code cares about specific types,
+ // but nothing cares about padding specifically. And it's not something we can
+ // easily query from LLVM due to the type system mismatches.
+ // DL.getTypeSizeInBits(convertTypeForLoadStore(T)) is probably close, but the
+ // DataLayout methods aren't really designed for this usage.
+ //
+ // Therefore, it is better to explicitly list all the scalar types
+ // containing padding bits that we know of, namely, _BitInt(N) and x87 long
+ // double.
+ uint64_t getScalarOccupiedSizeInBits(QualType Ty) const {
+ if (const auto *BIT = Ty->getAs<BitIntType>())
+ return BIT->getNumBits();
+
+ if (const auto *BT = Ty->getAs<BuiltinType>()) {
+ if (BT->getKind() == BuiltinType::LongDouble &&
+ &TI.getLongDoubleFormat() == &llvm::APFloat::x87DoubleExtended())
+ return llvm::APFloat::getSizeInBits(TI.getLongDoubleFormat());
+ }
+
+ return Ctx.getTypeSize(Ty);
+ }
+
+ void Visit(const Data &D) {
+ if (auto *AT = dyn_cast<ConstantArrayType>(D.Ty)) {
+ VisitArray(AT, D.StartBitOffset);
+ return;
+ }
+
+ if (auto *Record = D.Ty->getAsRecordDecl()) {
+ VisitStruct(Record, D.StartBitOffset, D.VisitVirtualBase);
+ return;
+ }
+
+ if (D.Ty->isAtomicType()) {
+ auto Unwrapped = D;
+ Unwrapped.Ty = D.Ty.getAtomicUnqualifiedType();
+ Stack.push_back(Unwrapped);
+ return;
+ }
+
+ if (const auto *Complex = D.Ty->getAs<ComplexType>()) {
+ VisitComplex(Complex, D.StartBitOffset);
+ return;
+ }
+
+ if (const auto *VT = D.Ty->getAs<clang::VectorType>()) {
+ VisitVector(VT, D.StartBitOffset);
+ return;
+ }
+
+ uint64_t SizeBit = getScalarOccupiedSizeInBits(D.Ty);
+ OccuppiedIntervals.push_back(
+ BitInterval{D.StartBitOffset, D.StartBitOffset + SizeBit});
+ }
+
+ void VisitArray(const ConstantArrayType *AT, uint64_t StartBitOffset) {
+ for (uint64_t ArrIndex = 0; ArrIndex < AT->getSize().getLimitedValue();
+ ++ArrIndex) {
+
+ QualType ElementQualType = AT->getElementType();
+ auto ElementSize = Ctx.getTypeSizeInChars(ElementQualType);
+ auto ElementAlign = Ctx.getTypeAlignInChars(ElementQualType);
+ auto Offset = ElementSize.alignTo(ElementAlign);
+
+ Stack.push_back(Data{StartBitOffset + ArrIndex * Offset.getQuantity() *
+ Ctx.getCharWidth(),
+ ElementQualType, /*VisitVirtualBase*/ true});
+ }
+ }
+
+ void VisitStruct(const RecordDecl *R, uint64_t StartBitOffset,
+ bool VisitVirtualBase) {
+ const ASTRecordLayout &ASTLayout = Ctx.getASTRecordLayout(R);
+ auto *CXXRecord = dyn_cast<CXXRecordDecl>(R);
+
+ if (CXXRecord) {
+ if (ASTLayout.hasOwnVFPtr()) {
+ OccuppiedIntervals.push_back(
+ BitInterval{StartBitOffset, StartBitOffset + PointerSizeInBits});
+ }
+
+ if (ASTLayout.hasOwnVBPtr()) {
+ auto Offset = ASTLayout.getVBPtrOffset().getQuantity();
+ auto StartVBPtr = StartBitOffset + Offset * Ctx.getCharWidth();
+ OccuppiedIntervals.push_back(
+ BitInterval{StartVBPtr, StartVBPtr + PointerSizeInBits});
+ }
+
+ const auto VisitBase = [&ASTLayout, StartBitOffset, this](
+ const CXXBaseSpecifier &Base, auto GetOffset) {
+ auto *BaseRecord = Base.getType()->getAsCXXRecordDecl();
+ if (!BaseRecord) {
+ return;
+ }
+ auto BaseOffset =
+ std::invoke(GetOffset, ASTLayout, BaseRecord).getQuantity();
+
+ Stack.push_back(Data{StartBitOffset + BaseOffset * Ctx.getCharWidth(),
+ Base.getType(), /*VisitVirtualBase*/ false});
+ };
+
+ for (auto Base : CXXRecord->bases()) {
+ if (!Base.isVirtual()) {
+ VisitBase(Base, &ASTRecordLayout::getBaseClassOffset);
+ }
+ }
+
+ if (VisitVirtualBase) {
+ for (auto VBase : CXXRecord->vbases()) {
+ VisitBase(VBase, &ASTRecordLayout::getVBaseClassOffset);
+ }
+ }
+ }
+
+ for (auto *Field : R->fields()) {
+ // Treat unnamed bitfields as padding.
+ if (Field->isUnnamedBitField())
+ continue;
+
+ auto FieldOffset = ASTLayout.getFieldOffset(Field->getFieldIndex());
+ if (Field->isBitField()) {
+ OccuppiedIntervals.push_back(BitInterval{
+ StartBitOffset + FieldOffset,
+ StartBitOffset + FieldOffset + Field->getBitWidthValue()});
+ } else {
+ Stack.push_back(Data{StartBitOffset + FieldOffset, Field->getType(),
+ /*VisitVirtualBase*/ true});
+ }
+ }
+ }
+
+ void VisitComplex(const ComplexType *CT, uint64_t StartBitOffset) {
+ QualType ElementQualType = CT->getElementType();
+ auto ElementSize = Ctx.getTypeSizeInChars(ElementQualType);
+ auto ElementAlign = Ctx.getTypeAlignInChars(ElementQualType);
+ auto ImgOffset = ElementSize.alignTo(ElementAlign);
+
+ Stack.push_back(
+ Data{StartBitOffset, ElementQualType, /*VisitVirtualBase*/ true});
+ Stack.push_back(
+ Data{StartBitOffset + ImgOffset.getQuantity() * Ctx.getCharWidth(),
+ ElementQualType, /*VisitVirtualBase*/ true});
+ }
+
+ void VisitVector(const clang::VectorType *VT, uint64_t StartBitOffset) {
+ uint64_t SizeBit = [&]() -> uint64_t {
+ if (VT->isPackedVectorBoolType(Ctx))
+ return VT->getNumElements();
+ return getScalarOccupiedSizeInBits(VT->getElementType()) *
+ VT->getNumElements();
+ }();
+ OccuppiedIntervals.push_back(
+ BitInterval{StartBitOffset, StartBitOffset + SizeBit});
+ }
+
+ void MergeOccuppiedIntervals() {
+ std::sort(OccuppiedIntervals.begin(), OccuppiedIntervals.end(),
+ [](const BitInterval &lhs, const BitInterval &rhs) {
+ return std::tie(lhs.First, lhs.Last) <
+ std::tie(rhs.First, rhs.Last);
+ });
+
+ llvm::SmallVector<BitInterval> Merged;
+ Merged.reserve(OccuppiedIntervals.size());
+
+ for (const BitInterval &NextInterval : OccuppiedIntervals) {
+ if (Merged.empty()) {
+ Merged.push_back(NextInterval);
+ continue;
+ }
+ auto &LastInterval = Merged.back();
+
+ if (NextInterval.First > LastInterval.Last) {
+ Merged.push_back(NextInterval);
+ } else {
+ LastInterval.Last = std::max(LastInterval.Last, NextInterval.Last);
+ }
+ }
+
+ OccuppiedIntervals = Merged;
+ }
+
+ const ASTContext &Ctx;
+ const TargetInfo &TI;
+ unsigned PointerSizeInBits;
+ uint64_t TySizeInBits = 0;
+ llvm::SmallVector<Data> Stack;
+ llvm::SmallVector<BitInterval> OccuppiedIntervals;
+};
+
+// Calculate and gets the 'padding intervals' inside of a type.
+llvm::SmallVector<BitInterval>
+CalculatePaddingIntervals(const ASTContext &Ctx, const TargetInfo &TI,
+ QualType Ty, unsigned PointerSizeInBits) {
+ PaddingCalculator pc{Ctx, TI, PointerSizeInBits};
+ pc.run(Ty);
+ return pc.GetPaddingIntervals();
+}
+} // namespace clang::CodeGenUtils
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 3521fc10f1387..9fa54b8f18b13 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -28,6 +28,7 @@
#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/DiagnosticFrontend.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/CodeGenUtils/CodeGenUtils.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/Instruction.h"
@@ -2598,277 +2599,40 @@ RValue CodeGenFunction::emitStdcFirstBit(const CallExpr *E, Intrinsic::ID IntID,
return RValue::get(Result);
}
-namespace {
-
-// PaddingClearer is a utility class that clears padding bits in a
-// c/c++ type. It traverses the type recursively, collecting occupied
-// bit intervals, and then computes the padding intervals.
-// In the end, it clears the padding bits by writing zeros
-// to the padding intervals bytes-by-bytes. If a byte only contains
-// some padding bits, it writes zeros to only those bits. This is
-// the case for bit-fields.
-struct PaddingClearer {
- PaddingClearer(CodeGenFunction &F)
- : CGF(F), CharWidth(CGF.getContext().getCharWidth()) {}
-
- void run(Address Src, QualType Ty) {
- OccuppiedIntervals.clear();
- Stack.clear();
-
- Stack.push_back(Data{0, Ty, true});
- while (!Stack.empty()) {
- auto Current = Stack.back();
- Stack.pop_back();
- Visit(Current);
- }
-
- MergeOccuppiedIntervals();
- auto PaddingIntervals =
- GetPaddingIntervals(CGF.getContext().getTypeSize(Ty));
- for (const auto &Interval : PaddingIntervals) {
- ClearPadding(Src, Interval);
- }
- }
-
-private:
- struct BitInterval {
- // [First, Last)
- uint64_t First;
- uint64_t Last;
- };
-
- struct Data {
- uint64_t StartBitOffset;
- QualType Ty;
- bool VisitVirtualBase;
- };
-
- // Return the number of non padding bits of a scalar type.
- //
- // The property that we specifically care about here is whether the scalar
- // type has padding bits, i.e. are there bits in the type which are not
- // specified by the ABI.
- //
- // We currently don't care about this anywhere else in clang: layout cares
- // about the ABI size, calling convention code cares about specific types, but
- // nothing cares about padding specifically. And it's not something we can
- // easily query from LLVM due to the type system mismatches.
- // DL.getTypeSizeInBits(convertTypeForLoadStore(T)) is probably close, but the
- // DataLayout methods aren't really designed for this usage.
- //
- // Therefore, it is better to explicitly list all the scalar types containing
- // padding bits that we know of, namely, _BitInt(N) and x87 long double.
- uint64_t getScalarOccupiedSizeInBits(QualType Ty) const {
- if (const auto *BIT = Ty->getAs<BitIntType>())
- return BIT->getNumBits();
-
- if (const auto *BT = Ty->getAs<BuiltinType>()) {
- if (BT->getKind() == BuiltinType::LongDouble &&
- &CGF.getTarget().getLongDoubleFormat() ==
- &APFloat::x87DoubleExtended())
- return APFloat::getSizeInBits(CGF.getTarget().getLongDoubleFormat());
- }
-
- return CGF.getContext().getTypeSize(Ty);
- }
-
- void Visit(const Data &D) {
- if (auto *AT = dyn_cast<ConstantArrayType>(D.Ty)) {
- VisitArray(AT, D.StartBitOffset);
- return;
- }
-
- if (auto *Record = D.Ty->getAsRecordDecl()) {
- VisitStruct(Record, D.StartBitOffset, D.VisitVirtualBase);
- return;
- }
-
- if (D.Ty->isAtomicType()) {
- auto Unwrapped = D;
- Unwrapped.Ty = D.Ty.getAtomicUnqualifiedType();
- Stack.push_back(Unwrapped);
- return;
- }
-
- if (const auto *Complex = D.Ty->getAs<ComplexType>()) {
- VisitComplex(Complex, D.StartBitOffset);
- return;
- }
-
- if (const auto *VT = D.Ty->getAs<clang::VectorType>()) {
- VisitVector(VT, D.StartBitOffset);
- return;
- }
-
- uint64_t SizeBit = getScalarOccupiedSizeInBits(D.Ty);
- OccuppiedIntervals.push_back(
- BitInterval{D.StartBitOffset, D.StartBitOffset + SizeBit});
- }
-
- void VisitArray(const ConstantArrayType *AT, uint64_t StartBitOffset) {
- for (uint64_t ArrIndex = 0; ArrIndex < AT->getSize().getLimitedValue();
- ++ArrIndex) {
-
- QualType ElementQualType = AT->getElementType();
- auto ElementSize = CGF.getContext().getTypeSizeInChars(ElementQualType);
- auto ElementAlign = CGF.getContext().getTypeAlignInChars(ElementQualType);
- auto Offset = ElementSize.alignTo(ElementAlign);
-
- Stack.push_back(
- Data{StartBitOffset + ArrIndex * Offset.getQuantity() * CharWidth,
- ElementQualType, /*VisitVirtualBase*/ true});
- }
- }
-
- void VisitStruct(const RecordDecl *R, uint64_t StartBitOffset,
- bool VisitVirtualBase) {
- const auto &DL = CGF.CGM.getModule().getDataLayout();
- const ASTRecordLayout &ASTLayout = CGF.getContext().getASTRecordLayout(R);
-
- auto *CXXRecord = dyn_cast<CXXRecordDecl>(R);
-
- if (CXXRecord) {
- if (ASTLayout.hasOwnVFPtr()) {
- OccuppiedIntervals.push_back(BitInterval{
- StartBitOffset, StartBitOffset + DL.getPointerSizeInBits()});
- }
-
- if (ASTLayout.hasOwnVBPtr()) {
- auto Offset = ASTLayout.getVBPtrOffset().getQuantity();
- auto StartVBPtr = StartBitOffset + Offset * CharWidth;
- OccuppiedIntervals.push_back(
- BitInterval{StartVBPtr, StartVBPtr + DL.getPointerSizeInBits()});
- }
-
- const auto VisitBase = [&ASTLayout, StartBitOffset, this](
- const CXXBaseSpecifier &Base, auto GetOffset) {
- auto *BaseRecord = Base.getType()->getAsCXXRecordDecl();
- if (!BaseRecord) {
- return;
- }
- auto BaseOffset =
- std::invoke(GetOffset, ASTLayout, BaseRecord).getQuantity();
-
- Stack.push_back(Data{StartBitOffset + BaseOffset * CharWidth,
- Base.getType(), /*VisitVirtualBase*/ false});
- };
-
- for (auto Base : CXXRecord->bases()) {
- if (!Base.isVirtual()) {
- VisitBase(Base, &ASTRecordLayout::getBaseClassOffset);
- }
- }
-
- if (VisitVirtualBase) {
- for (auto VBase : CXXRecord->vbases()) {
- VisitBase(VBase, &ASTRecordLayout::getVBaseClassOffset);
- }
- }
- }
-
- for (auto *Field : R->fields()) {
- // Treat unnamed bitfields as padding.
- if (Field->isUnnamedBitField())
- continue;
-
- auto FieldOffset = ASTLayout.getFieldOffset(Field->getFieldIndex());
- if (Field->isBitField()) {
- OccuppiedIntervals.push_back(BitInterval{
- StartBitOffset + FieldOffset,
- StartBitOffset + FieldOffset + Field->getBitWidthValue()});
- } else {
- Stack.push_back(Data{StartBitOffset + FieldOffset, Field->getType(),
- /*VisitVirtualBase*/ true});
- }
- }
- }
-
- void VisitComplex(const ComplexType *CT, uint64_t StartBitOffset) {
- QualType ElementQualType = CT->getElementType();
- auto ElementSize = CGF.getContext().getTypeSizeInChars(ElementQualType);
- auto ElementAlign = CGF.getContext().getTypeAlignInChars(ElementQualType);
- auto ImgOffset = ElementSize.alignTo(ElementAlign);
-
- Stack.push_back(
- Data{StartBitOffset, ElementQualType, /*VisitVirtualBase*/ true});
- Stack.push_back(Data{StartBitOffset + ImgOffset.getQuantity() * CharWidth,
- ElementQualType, /*VisitVirtualBase*/ true});
- }
-
- void VisitVector(const clang::VectorType *VT, uint64_t StartBitOffset) {
- ASTContext &Ctx = CGF.getContext();
- uint64_t SizeBit = [&]() -> uint64_t {
- if (VT->isPackedVectorBoolType(Ctx))
- return VT->getNumElements();
- return getScalarOccupiedSizeInBits(VT->getElementType()) *
- VT->getNumElements();
- }();
- OccuppiedIntervals.push_back(
- BitInterval{StartBitOffset, StartBitOffset + SizeBit});
- }
-
- void MergeOccuppiedIntervals() {
- std::sort(OccuppiedIntervals.begin(), OccuppiedIntervals.end(),
- [](const BitInterval &lhs, const BitInterval &rhs) {
- return std::tie(lhs.First, lhs.Last) <
- std::tie(rhs.First, rhs.Last);
- });
-
- llvm::SmallVector<BitInterval> Merged;
- Merged.reserve(OccuppiedIntervals.size());
-
- for (const BitInterval &NextInterval : OccuppiedIntervals) {
- if (Merged.empty()) {
- Merged.push_back(NextInterval);
- continue;
- }
- auto &LastInterval = Merged.back();
-
- if (NextInterval.First > LastInterval.Last) {
- Merged.push_back(NextInterval);
- } else {
- LastInterval.Last = std::max(LastInterval.Last, NextInterval.Last);
- }
- }
-
- OccuppiedIntervals = Merged;
- }
-
- llvm::SmallVector<BitInterval>
- GetPaddingIntervals(uint64_t SizeInBits) const {
- llvm::SmallVector<BitInterval> Results;
- if (OccuppiedIntervals.size() == 1 &&
- OccuppiedIntervals.front().First == 0 &&
- OccuppiedIntervals.front().Last == SizeInBits) {
- return Results;
- }
- Results.reserve(OccuppiedIntervals.size() + 1);
- uint64_t CurrentPos = 0;
- for (const BitInterval &OccupiedInterval : OccuppiedIntervals) {
- if (OccupiedInterval.First > CurrentPos) {
- Results.push_back(BitInterval{CurrentPos, OccupiedInterval.First});
- }
- CurrentPos = OccupiedInterval.Last;
- }
- if (SizeInBits > CurrentPos) {
- Results.push_back(BitInterval{CurrentPos, SizeInBits});
- }
- return Results;
- }
-
- void ClearPadding(Address Src, const BitInterval &PaddingInterval) {
- auto *I8Ptr =
- CGF.Builder.CreateBitCast(Src.getBasePointer(), CGF.Int8PtrTy);
- auto *Zero = ConstantInt::get(CGF.Int8Ty, 0);
-
- // Calculate byte indices and bit positions
- auto StartByte = PaddingInterval.First / CharWidth;
- auto StartBit = PaddingInterval.First % CharWidth;
- auto EndByte = PaddingInterval.Last / CharWidth;
- auto EndBit = PaddingInterval.Last % CharWidth;
-
- if (StartByte == EndByte) {
- // Interval is within a single byte
+static void ClearPadding(CodeGenFunction &CGF, Address Src,
+ const CodeGenUtils::BitInterval &PaddingInterval) {
+ uint64_t CharWidth = CGF.getContext().getCharWidth();
+
+ auto *I8Ptr = CGF.Builder.CreateBitCast(Src.getBasePointer(), CGF.Int8PtrTy);
+ auto *Zero = ConstantInt::get(CGF.Int8Ty, 0);
+
+ // Calculate byte indices and bit positions
+ auto StartByte = PaddingInterval.First / CharWidth;
+ auto StartBit = PaddingInterval.First % CharWidth;
+ auto EndByte = PaddingInterval.Last / CharWidth;
+ auto EndBit = PaddingInterval.Last % CharWidth;
+
+ if (StartByte == EndByte) {
+ // Interval is within a single byte
+ auto *Index = ConstantInt::get(CGF.IntTy, StartByte);
+ auto *Element = CGF.Builder.CreateGEP(CGF.Int8Ty, I8Ptr, Index);
+ Address ElementAddr(Element, CGF.Int8Ty,
+ Src.getAlignment().alignmentAtOffset(
+ CharUnits::fromQuantity(StartByte)));
+
+ auto *Value = CGF.Builder.CreateLoad(ElementAddr);
+
+ // Create mask to clear bits within the byte
+ // We want to clear bits from StartBit to EndBit-1
+ uint8_t bitsToClear = ((1 << EndBit) - 1) & ~((1 << StartBit) - 1);
+ uint8_t bitsToKeep = ~bitsToClear;
+ auto *MaskValue = ConstantInt::get(CGF.Int8Ty, bitsToKeep);
+ auto *NewValue = CGF.Builder.CreateAnd(Value, MaskValue);
+
+ CGF.Builder.CreateStore(NewValue, ElementAddr);
+ } else {
+ // Handle the start byte
+ if (StartBit != 0) {
auto *Index = ConstantInt::get(CGF.IntTy, StartByte);
auto *Element = CGF.Builder.CreateGEP(CGF.Int8Ty, I8Ptr, Index);
Address ElementAddr(Element, CGF.Int8Ty,
@@ -2877,72 +2641,45 @@ struct PaddingClearer {
auto *Value = CGF.Builder.CreateLoad(ElementAddr);
- // Create mask to clear bits within the byte
- // We want to clear bits from StartBit to EndBit-1
- uint8_t bitsToClear = ((1 << EndBit) - 1) & ~((1 << StartBit) - 1);
+ uint8_t bitsToClear = ((1 << (CharWidth - StartBit)) - 1) << StartBit;
uint8_t bitsToKeep = ~bitsToClear;
auto *MaskValue = ConstantInt::get(CGF.Int8Ty, bitsToKeep);
auto *NewValue = CGF.Builder.CreateAnd(Value, MaskValue);
CGF.Builder.CreateStore(NewValue, ElementAddr);
- } else {
- // Handle the start byte
- if (StartBit != 0) {
- auto *Index = ConstantInt::get(CGF.IntTy, StartByte);
- auto *Element = CGF.Builder.CreateGEP(CGF.Int8Ty, I8Ptr, Index);
- Address ElementAddr(Element, CGF.Int8Ty,
- Src.getAlignment().alignmentAtOffset(
- CharUnits::fromQuantity(StartByte)));
-
- auto *Value = CGF.Builder.CreateLoad(ElementAddr);
-
- uint8_t bitsToClear = ((1 << (CharWidth - StartBit)) - 1) << StartBit;
- uint8_t bitsToKeep = ~bitsToClear;
- auto *MaskValue = ConstantInt::get(CGF.Int8Ty, bitsToKeep);
- auto *NewValue = CGF.Builder.CreateAnd(Value, MaskValue);
-
- CGF.Builder.CreateStore(NewValue, ElementAddr);
- ++StartByte;
- }
+ ++StartByte;
+ }
- // Handle full bytes in the middle
- for (auto Offset = StartByte; Offset < EndByte; ++Offset) {
- auto *Index = ConstantInt::get(CGF.IntTy, Offset);
- auto *Element = CGF.Builder.CreateGEP(CGF.Int8Ty, I8Ptr, Index);
- Address ElementAddr(Element, CGF.Int8Ty,
- Src.getAlignment().alignmentAtOffset(
- CharUnits::fromQuantity(Offset)));
+ // Handle full bytes in the middle
+ for (auto Offset = StartByte; Offset < EndByte; ++Offset) {
+ auto *Index = ConstantInt::get(CGF.IntTy, Offset);
+ auto *Element = CGF.Builder.CreateGEP(CGF.Int8Ty, I8Ptr, Index);
+ Address ElementAddr(Element, CGF.Int8Ty,
+ Src.getAlignment().alignmentAtOffset(
+ CharUnits::fromQuantity(Offset)));
- CGF.Builder.CreateStore(Zero, ElementAddr);
- }
+ CGF.Builder.CreateStore(Zero, ElementAddr);
+ }
- // Handle the end byte
- if (EndBit != 0) {
- auto *Index = ConstantInt::get(CGF.IntTy, EndByte);
- auto *Element = CGF.Builder.CreateGEP(CGF.Int8Ty, I8Ptr, Index);
- Address ElementAddr(Element, CGF.Int8Ty,
- Src.getAlignment().alignmentAtOffset(
- CharUnits::fromQuantity(EndByte)));
+ // Handle the end byte
+ if (EndBit != 0) {
+ auto *Index = ConstantInt::get(CGF.IntTy, EndByte);
+ auto *Element = CGF.Builder.CreateGEP(CGF.Int8Ty, I8Ptr, Index);
+ Address ElementAddr(Element, CGF.Int8Ty,
+ Src.getAlignment().alignmentAtOffset(
+ CharUnits::fromQuantity(EndByte)));
- auto *Value = CGF.Builder.CreateLoad(ElementAddr);
+ auto *Value = CGF.Builder.CreateLoad(ElementAddr);
- uint8_t bitsToClear = (1 << EndBit) - 1;
- uint8_t bitsToKeep = ~bitsToClear;
- auto *MaskValue = ConstantInt::get(CGF.Int8Ty, bitsToKeep);
- auto *NewValue = CGF.Builder.CreateAnd(Value, MaskValue);
+ uint8_t bitsToClear = (1 << EndBit) - 1;
+ uint8_t bitsToKeep = ~bitsToClear;
+ auto *MaskValue = ConstantInt::get(CGF.Int8Ty, bitsToKeep);
+ auto *NewValue = CGF.Builder.CreateAnd(Value, MaskValue);
- CGF.Builder.CreateStore(NewValue, ElementAddr);
- }
+ CGF.Builder.CreateStore(NewValue, ElementAddr);
}
}
-
- CodeGenFunction &CGF;
- const uint64_t CharWidth;
- llvm::SmallVector<Data> Stack;
- llvm::SmallVector<BitInterval> OccuppiedIntervals;
-};
-
-} // namespace
+}
RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
const CallExpr *E,
@@ -5473,8 +5210,14 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
case Builtin::BI__builtin_clear_padding: {
Address Src = EmitPointerWithAlignment(E->getArg(0));
auto PointeeTy = E->getArg(0)->getType()->getPointeeType();
- PaddingClearer clearer{*this};
- clearer.run(Src, PointeeTy);
+
+ llvm::SmallVector<CodeGenUtils::BitInterval> Padding =
+ CodeGenUtils::CalculatePaddingIntervals(
+ getContext(), getTarget(), PointeeTy,
+ CGM.getDataLayout().getPointerSizeInBits());
+ for (const auto &Interval : Padding)
+ ClearPadding(*this, Src, Interval);
+
return RValue::get(nullptr);
}
case Builtin::BI__sync_fetch_and_add:
More information about the cfe-commits
mailing list