Skip to content

Commit cb0cb34

Browse files
bcardosolopeslanza
authored andcommitted
[CIR][CIRGen] Null init some inheritance components
1 parent 92c7d8f commit cb0cb34

File tree

5 files changed

+69
-1
lines changed

5 files changed

+69
-1
lines changed

clang/lib/CIR/CodeGen/CIRGenCXXABI.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -75,4 +75,8 @@ mlir::cir::GlobalLinkageKind CIRGenCXXABI::getCXXDestructorLinkage(
7575
// Delegate back to CGM by default.
7676
return CGM.getCIRLinkageForDeclarator(Dtor, Linkage,
7777
/*IsConstantVariable=*/false);
78+
}
79+
80+
std::vector<CharUnits> CIRGenCXXABI::getVBPtrOffsets(const CXXRecordDecl *RD) {
81+
return std::vector<CharUnits>();
7882
}

clang/lib/CIR/CodeGen/CIRGenCXXABI.h

+3
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,9 @@ class CIRGenCXXABI {
268268
virtual RecordArgABI
269269
getRecordArgABI(const clang::CXXRecordDecl *RD) const = 0;
270270

271+
/// Gets the offsets of all the virtual base pointers in a given class.
272+
virtual std::vector<CharUnits> getVBPtrOffsets(const CXXRecordDecl *RD);
273+
271274
/// Insert any ABI-specific implicit parameters into the parameter list for a
272275
/// function. This generally involves extra data for constructors and
273276
/// destructors.

clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp

+47-1
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,51 @@ CIRGenFunction::buildCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E,
344344
/*IsArrow=*/false, E->getArg(0));
345345
}
346346

347+
static void buildNullBaseClassInitialization(CIRGenFunction &CGF,
348+
Address DestPtr,
349+
const CXXRecordDecl *Base) {
350+
if (Base->isEmpty())
351+
return;
352+
353+
DestPtr = DestPtr.withElementType(CGF.UInt8Ty);
354+
355+
const ASTRecordLayout &Layout = CGF.getContext().getASTRecordLayout(Base);
356+
CharUnits NVSize = Layout.getNonVirtualSize();
357+
358+
// We cannot simply zero-initialize the entire base sub-object if vbptrs are
359+
// present, they are initialized by the most derived class before calling the
360+
// constructor.
361+
SmallVector<std::pair<CharUnits, CharUnits>, 1> Stores;
362+
Stores.emplace_back(CharUnits::Zero(), NVSize);
363+
364+
// Each store is split by the existence of a vbptr.
365+
CharUnits VBPtrWidth = CGF.getPointerSize();
366+
std::vector<CharUnits> VBPtrOffsets =
367+
CGF.CGM.getCXXABI().getVBPtrOffsets(Base);
368+
for (CharUnits VBPtrOffset : VBPtrOffsets) {
369+
// Stop before we hit any virtual base pointers located in virtual bases.
370+
if (VBPtrOffset >= NVSize)
371+
break;
372+
std::pair<CharUnits, CharUnits> LastStore = Stores.pop_back_val();
373+
CharUnits LastStoreOffset = LastStore.first;
374+
CharUnits LastStoreSize = LastStore.second;
375+
376+
CharUnits SplitBeforeOffset = LastStoreOffset;
377+
CharUnits SplitBeforeSize = VBPtrOffset - SplitBeforeOffset;
378+
assert(!SplitBeforeSize.isNegative() && "negative store size!");
379+
if (!SplitBeforeSize.isZero())
380+
Stores.emplace_back(SplitBeforeOffset, SplitBeforeSize);
381+
382+
CharUnits SplitAfterOffset = VBPtrOffset + VBPtrWidth;
383+
CharUnits SplitAfterSize = LastStoreSize - SplitAfterOffset;
384+
assert(!SplitAfterSize.isNegative() && "negative store size!");
385+
if (!SplitAfterSize.isZero())
386+
Stores.emplace_back(SplitAfterOffset, SplitAfterSize);
387+
}
388+
389+
llvm_unreachable("NYI");
390+
}
391+
347392
void CIRGenFunction::buildCXXConstructExpr(const CXXConstructExpr *E,
348393
AggValueSlot Dest) {
349394
assert(!Dest.isIgnored() && "Must have a destination!");
@@ -362,7 +407,8 @@ void CIRGenFunction::buildCXXConstructExpr(const CXXConstructExpr *E,
362407
break;
363408
case CXXConstructionKind::VirtualBase:
364409
case CXXConstructionKind::NonVirtualBase:
365-
llvm_unreachable("NYI");
410+
buildNullBaseClassInitialization(*this, Dest.getAddress(),
411+
CD->getParent());
366412
break;
367413
}
368414
}

clang/lib/CIR/CodeGen/CIRGenExprConst.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -1957,3 +1957,14 @@ mlir::Attribute ConstantEmitter::emitNullForMemory(mlir::Location loc,
19571957
assert(cstOp && "expected cir.const op");
19581958
return emitForMemory(CGM, cstOp.getValue(), T);
19591959
}
1960+
1961+
static mlir::Value buildNullConstant(CIRGenModule &CGM,
1962+
const RecordDecl *record,
1963+
bool asCompleteObject) {
1964+
llvm_unreachable("NYI");
1965+
}
1966+
1967+
mlir::Value
1968+
CIRGenModule::buildNullConstantForBase(const CXXRecordDecl *Record) {
1969+
return ::buildNullConstant(*this, Record, false);
1970+
}

clang/lib/CIR/CodeGen/CIRGenModule.h

+4
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,10 @@ class CIRGenModule : public CIRGenTypeCache {
606606
/// null constant.
607607
mlir::Value buildNullConstant(QualType T, mlir::Location loc);
608608

609+
/// Return a null constant appropriate for zero-initializing a base class with
610+
/// the given type. This is usually, but not always, an LLVM null constant.
611+
mlir::Value buildNullConstantForBase(const CXXRecordDecl *Record);
612+
609613
mlir::Value buildMemberPointerConstant(const UnaryOperator *E);
610614

611615
llvm::StringRef getMangledName(clang::GlobalDecl GD);

0 commit comments

Comments
 (0)