[clang] [libcxx] [clang] Add builtin to clear padding bytes (prework for P0528R3) (PR #75371)
Eli Friedman via cfe-commits
cfe-commits at lists.llvm.org
Mon Jul 15 23:10:38 PDT 2024
================
@@ -2538,6 +2541,311 @@ static RValue EmitHipStdParUnsupportedBuiltin(CodeGenFunction *CGF,
return RValue::get(CGF->Builder.CreateCall(UBF, Args));
}
+namespace {
+
+struct PaddingClearer {
+ PaddingClearer(CodeGenFunction &F)
+ : CGF(F), CharWidth(CGF.getContext().getCharWidth()) {}
+
+ void run(Value *Ptr, QualType Ty) {
+ OccuppiedIntervals.clear();
+ Queue.clear();
+
+ Queue.push_back(Data{0, Ty, true});
+ while (!Queue.empty()) {
+ auto Current = Queue.front();
+ Queue.pop_front();
+ Visit(Current);
+ }
+
+ MergeOccuppiedIntervals();
+ auto PaddingIntervals =
+ GetPaddingIntervals(CGF.getContext().getTypeSize(Ty));
+ llvm::dbgs() << "Occuppied Bits:\n";
+ for (auto [first, last] : OccuppiedIntervals) {
+ llvm::dbgs() << "[" << first << ", " << last << ")\n";
+ }
+ llvm::dbgs() << "Padding Bits:\n";
+ for (auto [first, last] : PaddingIntervals) {
+ llvm::dbgs() << "[" << first << ", " << last << ")\n";
+ }
+
+ for (const auto &Interval : PaddingIntervals) {
+ ClearPadding(Ptr, Interval);
+ }
+ }
+
+private:
+ struct BitInterval {
+ // [First, Last)
+ uint64_t First;
+ uint64_t Last;
+ };
+
+ struct Data {
+ uint64_t StartBitOffset;
+ QualType Ty;
+ bool VisitVirtualBase;
+ };
+
+ void Visit(Data const &D) {
+ if (auto *AT = dyn_cast<ConstantArrayType>(D.Ty)) {
+ VisitArray(AT, D.StartBitOffset);
+ return;
+ }
+
+ if (auto *Record = D.Ty->getAsCXXRecordDecl()) {
+ VisitStruct(Record, D.StartBitOffset, D.VisitVirtualBase);
+ return;
+ }
+
+ if (D.Ty->isAtomicType()) {
+ auto Unwrapped = D;
+ Unwrapped.Ty = D.Ty.getAtomicUnqualifiedType();
+ Queue.push_back(Unwrapped);
+ return;
+ }
+
+ if (const auto *Complex = D.Ty->getAs<ComplexType>()) {
+ VisitComplex(Complex, D.StartBitOffset);
+ return;
+ }
+
+ auto *Type = CGF.ConvertTypeForMem(D.Ty);
+ auto SizeBit = CGF.CGM.getModule()
+ .getDataLayout()
+ .getTypeSizeInBits(Type)
+ .getKnownMinValue();
+ llvm::dbgs() << "clear_padding primitive type. adding Interval ["
+ << D.StartBitOffset << ", " << D.StartBitOffset + SizeBit
+ << ")\n";
+ OccuppiedIntervals.push_back(
+ BitInterval{D.StartBitOffset, D.StartBitOffset + SizeBit});
+ }
+
+ void VisitArray(const ConstantArrayType *AT, uint64_t StartBitOffset) {
+ llvm::dbgs() << "clear_padding visiting constant array starting from "
+ << StartBitOffset << "\n";
+ 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);
+
+ Queue.push_back(
+ Data{StartBitOffset + ArrIndex * Offset.getQuantity() * CharWidth,
+ ElementQualType, true});
+ }
+ }
+
+ void VisitStruct(const CXXRecordDecl *R, uint64_t StartBitOffset,
+ bool VisitVirtualBase) {
+ llvm::dbgs() << "clear_padding visiting struct: "
+ << R->getQualifiedNameAsString() << " starting from offset "
+ << StartBitOffset << '\n';
+ const auto &DL = CGF.CGM.getModule().getDataLayout();
+
+ const ASTRecordLayout &ASTLayout = CGF.getContext().getASTRecordLayout(R);
+ if (ASTLayout.hasOwnVFPtr()) {
+ llvm::dbgs()
+ << "clear_padding found vtable ptr. Adding occuppied interval ["
+ << StartBitOffset << ", "
+ << (StartBitOffset + DL.getPointerSizeInBits()) << ")\n";
+ OccuppiedIntervals.push_back(BitInterval{
+ StartBitOffset, StartBitOffset + DL.getPointerSizeInBits()});
+ }
+
+ const auto VisitBase = [&ASTLayout, StartBitOffset, this](
+ const CXXBaseSpecifier &Base, auto GetOffset) {
+ auto *BaseRecord = Base.getType()->getAsCXXRecordDecl();
+ if (!BaseRecord) {
+ llvm::dbgs() << "Base is not a CXXRecord!\n";
+ return;
+ }
+ auto BaseOffset =
+ std::invoke(GetOffset, ASTLayout, BaseRecord).getQuantity();
+
+ llvm::dbgs() << "visiting base at offset " << StartBitOffset << " + "
+ << BaseOffset * CharWidth << '\n';
+ Queue.push_back(
+ Data{StartBitOffset + BaseOffset * CharWidth, Base.getType(), false});
----------------
efriedma-quic wrote:
```suggestion
Data{StartBitOffset + BaseOffset * CharWidth, Base.getType(), /*VisitVirtualBase*/false});
```
https://github.com/llvm/llvm-project/pull/75371
More information about the cfe-commits
mailing list