Skip to content

Commit

Permalink
[CIR][CIRGen] Null init some inheritance components
Browse files Browse the repository at this point in the history
  • Loading branch information
bcardosolopes authored and lanza committed Oct 19, 2024
1 parent 92c7d8f commit cb0cb34
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 1 deletion.
4 changes: 4 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenCXXABI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,8 @@ mlir::cir::GlobalLinkageKind CIRGenCXXABI::getCXXDestructorLinkage(
// Delegate back to CGM by default.
return CGM.getCIRLinkageForDeclarator(Dtor, Linkage,
/*IsConstantVariable=*/false);
}

std::vector<CharUnits> CIRGenCXXABI::getVBPtrOffsets(const CXXRecordDecl *RD) {
return std::vector<CharUnits>();
}
3 changes: 3 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenCXXABI.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<CharUnits> 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.
Expand Down
48 changes: 47 additions & 1 deletion clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::pair<CharUnits, CharUnits>, 1> Stores;
Stores.emplace_back(CharUnits::Zero(), NVSize);

// Each store is split by the existence of a vbptr.
CharUnits VBPtrWidth = CGF.getPointerSize();
std::vector<CharUnits> 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<CharUnits, CharUnits> 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!");
Expand All @@ -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;
}
}
Expand Down
11 changes: 11 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenExprConst.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
4 changes: 4 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit cb0cb34

Please sign in to comment.