Skip to content

Commit 8276fcf

Browse files
committed
[CIR][Codegen] VTT support for virtual class inheritance
1 parent 5364b31 commit 8276fcf

File tree

8 files changed

+215
-34
lines changed

8 files changed

+215
-34
lines changed

clang/lib/CIR/CodeGen/CIRGenCXXABI.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,11 @@ class CIRGenCXXABI {
188188
/// Emits the VTable definitions required for the given record type.
189189
virtual void emitVTableDefinitions(CIRGenVTables &CGVT,
190190
const CXXRecordDecl *RD) = 0;
191+
192+
/// Emit any tables needed to implement virtual inheritance. For Itanium,
193+
/// this emits virtual table tables.
194+
virtual void emitVirtualInheritanceTables(const CXXRecordDecl *RD) = 0;
195+
191196
virtual mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc,
192197
QualType Ty) = 0;
193198
virtual CatchTypeInfo
@@ -280,6 +285,12 @@ class CIRGenCXXABI {
280285
// directly or require access through a thread wrapper function.
281286
virtual bool usesThreadWrapperFunction(const VarDecl *VD) const = 0;
282287

288+
/// Emit the code to initialize hidden members required to handle virtual
289+
/// inheritance, if needed by the ABI.
290+
virtual void
291+
initializeHiddenVirtualInheritanceMembers(CIRGenFunction &CGF,
292+
const CXXRecordDecl *RD) {}
293+
283294
/// Emit a single constructor/destructor with the gien type from a C++
284295
/// constructor Decl.
285296
virtual void buildCXXStructor(clang::GlobalDecl GD) = 0;

clang/lib/CIR/CodeGen/CIRGenClass.cpp

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,8 @@ bool CIRGenFunction::IsConstructorDelegationValid(
3939
// };
4040
// ...although even this example could in principle be emitted as a delegation
4141
// since the address of the parameter doesn't escape.
42-
if (Ctor->getParent()->getNumVBases()) {
43-
llvm_unreachable("NYI");
44-
}
42+
if (Ctor->getParent()->getNumVBases())
43+
return false;
4544

4645
// We also disable the optimization for variadic functions because it's
4746
// impossible to "re-pass" varargs.
@@ -235,7 +234,7 @@ static void buildMemberInitializer(CIRGenFunction &CGF,
235234
if (CGF.CurGD.getCtorType() == Ctor_Base)
236235
LHS = CGF.MakeNaturalAlignPointeeAddrLValue(ThisPtr, RecordTy);
237236
else
238-
llvm_unreachable("NYI");
237+
LHS = CGF.MakeNaturalAlignAddrLValue(ThisPtr, RecordTy);
239238

240239
buildLValueForAnyFieldInitialization(CGF, MemberInit, LHS);
241240

@@ -523,9 +522,10 @@ Address CIRGenFunction::getAddressOfDirectBaseInCompleteClass(
523522
// TODO: for complete types, this should be possible with a GEP.
524523
Address V = This;
525524
if (!Offset.isZero()) {
526-
// TODO(cir): probably create a new operation to account for
527-
// down casting when the offset isn't zero.
528-
llvm_unreachable("NYI");
525+
mlir::Value OffsetVal = builder.getSInt32(Offset.getQuantity(), loc);
526+
mlir::Value VBaseThisPtr = builder.create<mlir::cir::PtrStrideOp>(
527+
loc, This.getPointer().getType(), This.getPointer(), OffsetVal);
528+
V = Address(VBaseThisPtr, CXXABIThisAlignment);
529529
}
530530
V = builder.createElementBitCast(loc, V, ConvertType(Base));
531531
return V;
@@ -604,7 +604,11 @@ void CIRGenFunction::buildCtorPrologue(const CXXConstructorDecl *CD,
604604
for (; B != E && (*B)->isBaseInitializer() && (*B)->isBaseVirtual(); B++) {
605605
if (!ConstructVBases)
606606
continue;
607-
llvm_unreachable("NYI");
607+
if (CGM.getCodeGenOpts().StrictVTablePointers &&
608+
CGM.getCodeGenOpts().OptimizationLevel > 0 &&
609+
isInitializerOfDynamicClass(*B))
610+
llvm_unreachable("NYI");
611+
buildBaseInitializer(getLoc(CD->getBeginLoc()), *this, ClassDecl, *B);
608612
}
609613

610614
if (BaseCtorContinueBB) {
@@ -698,7 +702,7 @@ void CIRGenFunction::initializeVTablePointers(mlir::Location loc,
698702
initializeVTablePointer(loc, Vptr);
699703

700704
if (RD->getNumVBases())
701-
llvm_unreachable("NYI");
705+
CGM.getCXXABI().initializeHiddenVirtualInheritanceMembers(*this, RD);
702706
}
703707

704708
CIRGenFunction::VPtrsVector
@@ -1286,4 +1290,4 @@ mlir::Value CIRGenFunction::getVTablePtr(SourceLocation Loc, Address This,
12861290
}
12871291

12881292
return VTable;
1289-
}
1293+
}

clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -358,8 +358,8 @@ void CIRGenFunction::buildCXXConstructExpr(const CXXConstructExpr *E,
358358
llvm_unreachable("NYI");
359359
break;
360360
case CXXConstructExpr::CK_VirtualBase:
361-
llvm_unreachable("NYI");
362-
break;
361+
ForVirtualBase = true;
362+
[[fallthrough]];
363363
case CXXConstructExpr::CK_NonVirtualBase:
364364
Type = Ctor_Base;
365365
break;

clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ class CIRGenItaniumCXXABI : public cir::CIRGenCXXABI {
197197
const CXXRecordDecl *NearestVBase) override;
198198
void emitVTableDefinitions(CIRGenVTables &CGVT,
199199
const CXXRecordDecl *RD) override;
200+
void emitVirtualInheritanceTables(const CXXRecordDecl *RD) override;
200201
mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc,
201202
QualType Ty) override;
202203
bool useThunkForDtorVariant(const CXXDestructorDecl *Dtor,
@@ -821,10 +822,10 @@ class CIRGenItaniumRTTIBuilder {
821822
/// to the Itanium C++ ABI, 2.9.5p6b.
822823
void BuildSIClassTypeInfo(mlir::Location loc, const CXXRecordDecl *RD);
823824

824-
// /// Build an abi::__vmi_class_type_info, used for
825-
// /// classes with bases that do not satisfy the abi::__si_class_type_info
826-
// /// constraints, according ti the Itanium C++ ABI, 2.9.5p5c.
827-
// void BuildVMIClassTypeInfo(const CXXRecordDecl *RD);
825+
/// Build an abi::__vmi_class_type_info, used for
826+
/// classes with bases that do not satisfy the abi::__si_class_type_info
827+
/// constraints, according ti the Itanium C++ ABI, 2.9.5p5c.
828+
void BuildVMIClassTypeInfo(const CXXRecordDecl *RD);
828829

829830
// /// Build an abi::__pointer_type_info struct, used
830831
// /// for pointer types.
@@ -1432,6 +1433,10 @@ void CIRGenItaniumRTTIBuilder::BuildSIClassTypeInfo(mlir::Location loc,
14321433
Fields.push_back(BaseTypeInfo);
14331434
}
14341435

1436+
void CIRGenItaniumRTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) {
1437+
// TODO: Implement this function.
1438+
}
1439+
14351440
mlir::Attribute
14361441
CIRGenItaniumRTTIBuilder::GetAddrOfExternalRTTIDescriptor(mlir::Location loc,
14371442
QualType Ty) {
@@ -1554,8 +1559,7 @@ mlir::Attribute CIRGenItaniumRTTIBuilder::BuildTypeInfo(
15541559
if (CanUseSingleInheritance(RD)) {
15551560
BuildSIClassTypeInfo(loc, RD);
15561561
} else {
1557-
llvm_unreachable("NYI");
1558-
// BuildVMIClassTypeInfo(RD);
1562+
BuildVMIClassTypeInfo(RD);
15591563
}
15601564

15611565
break;
@@ -1724,6 +1728,13 @@ void CIRGenItaniumCXXABI::emitVTableDefinitions(CIRGenVTables &CGVT,
17241728
llvm_unreachable("NYI");
17251729
}
17261730

1731+
void CIRGenItaniumCXXABI::emitVirtualInheritanceTables(
1732+
const CXXRecordDecl *RD) {
1733+
CIRGenVTables &VTables = CGM.getVTables();
1734+
auto VTT = VTables.getAddrOfVTT(RD);
1735+
VTables.buildVTTDefinition(VTT, CGM.getVTableLinkage(RD), RD);
1736+
}
1737+
17271738
/// What sort of uniqueness rules should we use for the RTTI for the
17281739
/// given type?
17291740
CIRGenItaniumCXXABI::RTTIUniquenessKind
@@ -1836,4 +1847,4 @@ void CIRGenItaniumCXXABI::buildThrow(CIRGenFunction &CGF,
18361847
// Now throw the exception.
18371848
builder.create<mlir::cir::ThrowOp>(CGF.getLoc(E->getSourceRange()),
18381849
exceptionPtr, typeInfo.getSymbol(), dtor);
1839-
}
1850+
}

clang/lib/CIR/CodeGen/CIRGenVTables.cpp

Lines changed: 119 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,17 @@
1313
#include "CIRGenCXXABI.h"
1414
#include "CIRGenFunction.h"
1515
#include "CIRGenModule.h"
16+
#include "mlir/IR/Attributes.h"
1617
#include "clang/AST/Attr.h"
1718
#include "clang/AST/CXXInheritance.h"
1819
#include "clang/AST/RecordLayout.h"
20+
#include "clang/AST/VTTBuilder.h"
1921
#include "clang/Basic/CodeGenOptions.h"
2022
#include "clang/CIR/Dialect/IR/CIRAttrs.h"
2123
#include "clang/CIR/Dialect/IR/CIRTypes.h"
2224
#include "clang/CodeGen/CGFunctionInfo.h"
2325
#include "clang/CodeGen/ConstantInitBuilder.h"
26+
#include "llvm/Support/ErrorHandling.h"
2427
#include "llvm/Support/Format.h"
2528
#include "llvm/Transforms/Utils/Cloning.h"
2629
#include <algorithm>
@@ -151,17 +154,17 @@ void CIRGenVTables::GenerateClassData(const CXXRecordDecl *RD) {
151154
assert(!UnimplementedFeature::generateDebugInfo());
152155

153156
if (RD->getNumVBases())
154-
llvm_unreachable("NYI");
157+
CGM.getCXXABI().emitVirtualInheritanceTables(RD);
155158

156159
CGM.getCXXABI().emitVTableDefinitions(*this, RD);
157160
}
158161

159162
static void AddPointerLayoutOffset(CIRGenModule &CGM,
160163
ConstantArrayBuilder &builder,
161164
CharUnits offset) {
162-
assert(offset.getQuantity() == 0 && "NYI");
163-
builder.add(mlir::cir::ConstPtrAttr::get(
164-
CGM.getBuilder().getContext(), CGM.getBuilder().getUInt8PtrTy(), 0));
165+
builder.add(mlir::cir::ConstPtrAttr::get(CGM.getBuilder().getContext(),
166+
CGM.getBuilder().getUInt8PtrTy(),
167+
offset.getQuantity()));
165168
}
166169

167170
static void AddRelativeLayoutOffset(CIRGenModule &CGM,
@@ -415,6 +418,118 @@ CIRGenModule::getVTableLinkage(const CXXRecordDecl *RD) {
415418
llvm_unreachable("Invalid TemplateSpecializationKind!");
416419
}
417420

421+
mlir::cir::GlobalOp
422+
getAddrOfVTTVTable(CIRGenVTables &CGVT, CIRGenModule &CGM,
423+
const CXXRecordDecl *MostDerivedClass,
424+
const VTTVTable &vtable,
425+
mlir::cir::GlobalLinkageKind linkage,
426+
VTableLayout::AddressPointsMapTy &addressPoints) {
427+
if (vtable.getBase() == MostDerivedClass) {
428+
assert(vtable.getBaseOffset().isZero() &&
429+
"Most derived class vtable must have a zero offset!");
430+
// This is a regular vtable.
431+
return CGM.getCXXABI().getAddrOfVTable(MostDerivedClass, CharUnits());
432+
}
433+
434+
llvm_unreachable("generateConstructionVTable NYI");
435+
}
436+
437+
mlir::cir::GlobalOp CIRGenVTables::getAddrOfVTT(const CXXRecordDecl *RD)
438+
{
439+
assert(RD->getNumVBases() && "Only classes with virtual bases need a VTT");
440+
441+
SmallString<256> OutName;
442+
llvm::raw_svector_ostream Out(OutName);
443+
cast<ItaniumMangleContext>(CGM.getCXXABI().getMangleContext())
444+
.mangleCXXVTT(RD, Out);
445+
StringRef Name = OutName.str();
446+
447+
// This will also defer the definition of the VTT.
448+
(void)CGM.getCXXABI().getAddrOfVTable(RD, CharUnits());
449+
450+
VTTBuilder Builder(CGM.getASTContext(), RD, /*GenerateDefinition=*/false);
451+
452+
auto ArrayType = mlir::cir::ArrayType::get(CGM.getBuilder().getContext(),
453+
CGM.getBuilder().getUInt8PtrTy(),
454+
Builder.getVTTComponents().size());
455+
auto Align =
456+
CGM.getDataLayout().getABITypeAlign(CGM.getBuilder().getUInt8PtrTy());
457+
auto VTT = CGM.createOrReplaceCXXRuntimeVariable(
458+
CGM.getLoc(RD->getSourceRange()), Name, ArrayType,
459+
mlir::cir::GlobalLinkageKind::ExternalLinkage,
460+
CharUnits::fromQuantity(Align));
461+
CGM.setGVProperties(VTT, RD);
462+
return VTT;
463+
}
464+
465+
/// Emit the definition of the given vtable.
466+
void CIRGenVTables::buildVTTDefinition(mlir::cir::GlobalOp VTT,
467+
mlir::cir::GlobalLinkageKind Linkage,
468+
const CXXRecordDecl *RD) {
469+
VTTBuilder Builder(CGM.getASTContext(), RD, /*GenerateDefinition=*/true);
470+
471+
auto ArrayType = mlir::cir::ArrayType::get(CGM.getBuilder().getContext(),
472+
CGM.getBuilder().getUInt8PtrTy(),
473+
Builder.getVTTComponents().size());
474+
475+
SmallVector<mlir::cir::GlobalOp, 8> VTables;
476+
SmallVector<VTableAddressPointsMapTy, 8> VTableAddressPoints;
477+
for (const VTTVTable *i = Builder.getVTTVTables().begin(),
478+
*e = Builder.getVTTVTables().end();
479+
i != e; ++i) {
480+
VTableAddressPoints.push_back(VTableAddressPointsMapTy());
481+
VTables.push_back(getAddrOfVTTVTable(*this, CGM, RD, *i, Linkage,
482+
VTableAddressPoints.back()));
483+
}
484+
485+
SmallVector<mlir::Attribute, 8> VTTComponents;
486+
for (const VTTComponent *i = Builder.getVTTComponents().begin(),
487+
*e = Builder.getVTTComponents().end();
488+
i != e; ++i) {
489+
const VTTVTable &VTTVT = Builder.getVTTVTables()[i->VTableIndex];
490+
mlir::cir::GlobalOp VTable = VTables[i->VTableIndex];
491+
VTableLayout::AddressPointLocation AddressPoint;
492+
if (VTTVT.getBase() == RD) {
493+
// Just get the address point for the regular vtable.
494+
AddressPoint =
495+
getItaniumVTableContext().getVTableLayout(RD).getAddressPoint(
496+
i->VTableBase);
497+
} else {
498+
AddressPoint = VTableAddressPoints[i->VTableIndex].lookup(i->VTableBase);
499+
assert(AddressPoint.AddressPointIndex != 0 &&
500+
"Did not find ctor vtable address point!");
501+
}
502+
503+
mlir::Attribute Idxs[3] = {
504+
CGM.getBuilder().getI32IntegerAttr(0),
505+
CGM.getBuilder().getI32IntegerAttr(AddressPoint.VTableIndex),
506+
CGM.getBuilder().getI32IntegerAttr(AddressPoint.AddressPointIndex),
507+
};
508+
509+
auto Init = mlir::cir::GlobalViewAttr::get(
510+
CGM.getBuilder().getUInt8PtrTy(),
511+
mlir::FlatSymbolRefAttr::get(VTable.getSymNameAttr()),
512+
mlir::ArrayAttr::get(CGM.getBuilder().getContext(), Idxs));
513+
514+
VTTComponents.push_back(Init);
515+
}
516+
517+
auto Init = CGM.getBuilder().getConstArray(
518+
mlir::ArrayAttr::get(CGM.getBuilder().getContext(), VTTComponents),
519+
ArrayType);
520+
521+
VTT.setInitialValueAttr(Init);
522+
523+
// Set the correct linkage.
524+
VTT.setLinkage(Linkage);
525+
mlir::SymbolTable::setSymbolVisibility(VTT,
526+
CIRGenModule::getMLIRVisibility(VTT));
527+
528+
if (CGM.supportsCOMDAT() && VTT.isWeakForLinker()) {
529+
assert(!UnimplementedFeature::setComdat());
530+
}
531+
}
532+
418533
void CIRGenVTables::buildThunks(GlobalDecl GD) {
419534
const CXXMethodDecl *MD =
420535
cast<CXXMethodDecl>(GD.getDecl())->getCanonicalDecl();

clang/lib/CIR/CodeGen/CIRGenVTables.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -138,13 +138,13 @@ class CIRGenVTables {
138138
// llvm::GlobalVariable::LinkageTypes Linkage,
139139
// VTableAddressPointsMapTy &AddressPoints);
140140

141-
// /// GetAddrOfVTT - Get the address of the VTT for the given record decl.
142-
// llvm::GlobalVariable *GetAddrOfVTT(const CXXRecordDecl *RD);
141+
/// Get the address of the VTT for the given record decl.
142+
mlir::cir::GlobalOp getAddrOfVTT(const CXXRecordDecl *RD);
143143

144-
// /// EmitVTTDefinition - Emit the definition of the given vtable.
145-
// void EmitVTTDefinition(llvm::GlobalVariable *VTT,
146-
// llvm::GlobalVariable::LinkageTypes Linkage,
147-
// const CXXRecordDecl *RD);
144+
/// Emit the definition of the given vtable.
145+
void buildVTTDefinition(mlir::cir::GlobalOp VTT,
146+
mlir::cir::GlobalLinkageKind Linkage,
147+
const CXXRecordDecl *RD);
148148

149149
/// Emit the associated thunks for the given global decl.
150150
void buildThunks(GlobalDecl GD);

0 commit comments

Comments
 (0)