From cb0cb34b7d6a8fa22e6ca54b6f9783dbf938d271 Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Fri, 18 Oct 2024 16:59:37 -0700 Subject: [PATCH] [CIR][CIRGen] Null init some inheritance components --- clang/lib/CIR/CodeGen/CIRGenCXXABI.cpp | 4 ++ clang/lib/CIR/CodeGen/CIRGenCXXABI.h | 3 ++ clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp | 48 ++++++++++++++++++++++- clang/lib/CIR/CodeGen/CIRGenExprConst.cpp | 11 ++++++ clang/lib/CIR/CodeGen/CIRGenModule.h | 4 ++ 5 files changed, 69 insertions(+), 1 deletion(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenCXXABI.cpp b/clang/lib/CIR/CodeGen/CIRGenCXXABI.cpp index 27b04503d788..8f6040f8cea5 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCXXABI.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenCXXABI.cpp @@ -75,4 +75,8 @@ mlir::cir::GlobalLinkageKind CIRGenCXXABI::getCXXDestructorLinkage( // Delegate back to CGM by default. return CGM.getCIRLinkageForDeclarator(Dtor, Linkage, /*IsConstantVariable=*/false); +} + +std::vector CIRGenCXXABI::getVBPtrOffsets(const CXXRecordDecl *RD) { + return std::vector(); } \ No newline at end of file diff --git a/clang/lib/CIR/CodeGen/CIRGenCXXABI.h b/clang/lib/CIR/CodeGen/CIRGenCXXABI.h index 83da6ad3c49d..159b0e5e8e2b 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCXXABI.h +++ b/clang/lib/CIR/CodeGen/CIRGenCXXABI.h @@ -268,6 +268,9 @@ class CIRGenCXXABI { virtual RecordArgABI getRecordArgABI(const clang::CXXRecordDecl *RD) const = 0; + /// Gets the offsets of all the virtual base pointers in a given class. + virtual std::vector getVBPtrOffsets(const CXXRecordDecl *RD); + /// Insert any ABI-specific implicit parameters into the parameter list for a /// function. This generally involves extra data for constructors and /// destructors. diff --git a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp index 212991871dce..d1efeb0c77e1 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp @@ -344,6 +344,51 @@ CIRGenFunction::buildCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E, /*IsArrow=*/false, E->getArg(0)); } +static void buildNullBaseClassInitialization(CIRGenFunction &CGF, + Address DestPtr, + const CXXRecordDecl *Base) { + if (Base->isEmpty()) + return; + + DestPtr = DestPtr.withElementType(CGF.UInt8Ty); + + const ASTRecordLayout &Layout = CGF.getContext().getASTRecordLayout(Base); + CharUnits NVSize = Layout.getNonVirtualSize(); + + // We cannot simply zero-initialize the entire base sub-object if vbptrs are + // present, they are initialized by the most derived class before calling the + // constructor. + SmallVector, 1> Stores; + Stores.emplace_back(CharUnits::Zero(), NVSize); + + // Each store is split by the existence of a vbptr. + CharUnits VBPtrWidth = CGF.getPointerSize(); + std::vector VBPtrOffsets = + CGF.CGM.getCXXABI().getVBPtrOffsets(Base); + for (CharUnits VBPtrOffset : VBPtrOffsets) { + // Stop before we hit any virtual base pointers located in virtual bases. + if (VBPtrOffset >= NVSize) + break; + std::pair LastStore = Stores.pop_back_val(); + CharUnits LastStoreOffset = LastStore.first; + CharUnits LastStoreSize = LastStore.second; + + CharUnits SplitBeforeOffset = LastStoreOffset; + CharUnits SplitBeforeSize = VBPtrOffset - SplitBeforeOffset; + assert(!SplitBeforeSize.isNegative() && "negative store size!"); + if (!SplitBeforeSize.isZero()) + Stores.emplace_back(SplitBeforeOffset, SplitBeforeSize); + + CharUnits SplitAfterOffset = VBPtrOffset + VBPtrWidth; + CharUnits SplitAfterSize = LastStoreSize - SplitAfterOffset; + assert(!SplitAfterSize.isNegative() && "negative store size!"); + if (!SplitAfterSize.isZero()) + Stores.emplace_back(SplitAfterOffset, SplitAfterSize); + } + + llvm_unreachable("NYI"); +} + void CIRGenFunction::buildCXXConstructExpr(const CXXConstructExpr *E, AggValueSlot Dest) { assert(!Dest.isIgnored() && "Must have a destination!"); @@ -362,7 +407,8 @@ void CIRGenFunction::buildCXXConstructExpr(const CXXConstructExpr *E, break; case CXXConstructionKind::VirtualBase: case CXXConstructionKind::NonVirtualBase: - llvm_unreachable("NYI"); + buildNullBaseClassInitialization(*this, Dest.getAddress(), + CD->getParent()); break; } } diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConst.cpp b/clang/lib/CIR/CodeGen/CIRGenExprConst.cpp index c3683b3f0fd1..68832ec2b7ba 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprConst.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprConst.cpp @@ -1957,3 +1957,14 @@ mlir::Attribute ConstantEmitter::emitNullForMemory(mlir::Location loc, assert(cstOp && "expected cir.const op"); return emitForMemory(CGM, cstOp.getValue(), T); } + +static mlir::Value buildNullConstant(CIRGenModule &CGM, + const RecordDecl *record, + bool asCompleteObject) { + llvm_unreachable("NYI"); +} + +mlir::Value +CIRGenModule::buildNullConstantForBase(const CXXRecordDecl *Record) { + return ::buildNullConstant(*this, Record, false); +} \ No newline at end of file diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h index 16f95c164712..7dd265f9a785 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.h +++ b/clang/lib/CIR/CodeGen/CIRGenModule.h @@ -606,6 +606,10 @@ class CIRGenModule : public CIRGenTypeCache { /// null constant. mlir::Value buildNullConstant(QualType T, mlir::Location loc); + /// Return a null constant appropriate for zero-initializing a base class with + /// the given type. This is usually, but not always, an LLVM null constant. + mlir::Value buildNullConstantForBase(const CXXRecordDecl *Record); + mlir::Value buildMemberPointerConstant(const UnaryOperator *E); llvm::StringRef getMangledName(clang::GlobalDecl GD);