@@ -689,9 +689,8 @@ static Address ApplyNonVirtualAndVirtualOffset(
689
689
CharUnits alignment;
690
690
if (virtualOffset) {
691
691
assert (nearestVBase && " virtual offset without vbase?" );
692
- llvm_unreachable (" NYI" );
693
- // alignment = CGF.CGM.getVBaseAlignment(addr.getAlignment(),
694
- // derivedClass, nearestVBase);
692
+ alignment = CGF.CGM .getVBaseAlignment (addr.getAlignment (), derivedClass,
693
+ nearestVBase);
695
694
} else {
696
695
alignment = addr.getAlignment ();
697
696
}
@@ -714,7 +713,11 @@ void CIRGenFunction::initializeVTablePointer(mlir::Location loc,
714
713
CharUnits NonVirtualOffset = CharUnits::Zero ();
715
714
716
715
if (CGM.getCXXABI ().isVirtualOffsetNeededForVTableField (*this , Vptr)) {
717
- llvm_unreachable (" NYI" );
716
+ // We need to use the virtual base offset offset because the virtual base
717
+ // might have a different offset in the most derived class.
718
+ VirtualOffset = CGM.getCXXABI ().getVirtualBaseClassOffset (
719
+ loc, *this , LoadCXXThisAddress (), Vptr.VTableClass , Vptr.NearestVBase );
720
+ NonVirtualOffset = Vptr.OffsetFromNearestVBase ;
718
721
} else {
719
722
// We can just use the base offset in the complete class.
720
723
NonVirtualOffset = Vptr.Base .getBaseOffset ();
@@ -797,7 +800,16 @@ void CIRGenFunction::getVTablePointers(BaseSubobject Base,
797
800
bool BaseDeclIsNonVirtualPrimaryBase;
798
801
799
802
if (I.isVirtual ()) {
800
- llvm_unreachable (" NYI" );
803
+ // Check if we've visited this virtual base before.
804
+ if (!VBases.insert (BaseDecl).second )
805
+ continue ;
806
+
807
+ const ASTRecordLayout &Layout =
808
+ getContext ().getASTRecordLayout (VTableClass);
809
+
810
+ BaseOffset = Layout.getVBaseClassOffset (BaseDecl);
811
+ BaseOffsetFromNearestVBase = CharUnits::Zero ();
812
+ BaseDeclIsNonVirtualPrimaryBase = false ;
801
813
} else {
802
814
const ASTRecordLayout &Layout = getContext ().getASTRecordLayout (RD);
803
815
@@ -1449,18 +1461,34 @@ mlir::Value CIRGenFunction::GetVTTParameter(GlobalDecl GD, bool ForVirtualBase,
1449
1461
const CXXRecordDecl *RD = cast<CXXMethodDecl>(CurCodeDecl)->getParent ();
1450
1462
const CXXRecordDecl *Base = cast<CXXMethodDecl>(GD.getDecl ())->getParent ();
1451
1463
1464
+ uint64_t SubVTTIndex;
1465
+
1452
1466
if (Delegating) {
1453
1467
llvm_unreachable (" NYI" );
1454
1468
} else if (RD == Base) {
1455
1469
llvm_unreachable (" NYI" );
1456
1470
} else {
1457
- llvm_unreachable (" NYI" );
1471
+ const ASTRecordLayout &Layout = getContext ().getASTRecordLayout (RD);
1472
+ CharUnits BaseOffset = ForVirtualBase ? Layout.getVBaseClassOffset (Base)
1473
+ : Layout.getBaseClassOffset (Base);
1474
+
1475
+ SubVTTIndex =
1476
+ CGM.getVTables ().getSubVTTIndex (RD, BaseSubobject (Base, BaseOffset));
1477
+ assert (SubVTTIndex != 0 && " Sub-VTT index must be greater than zero!" );
1458
1478
}
1459
1479
1480
+ auto Loc = CGM.getLoc (RD->getBeginLoc ());
1460
1481
if (CGM.getCXXABI ().NeedsVTTParameter (CurGD)) {
1461
- llvm_unreachable (" NYI" );
1482
+ // A VTT parameter was passed to the constructor, use it.
1483
+ auto VTT = LoadCXXVTT ();
1484
+ return CGM.getBuilder ().createVTTAddrPoint (Loc, VTT.getType (), VTT,
1485
+ SubVTTIndex);
1462
1486
} else {
1463
- llvm_unreachable (" NYI" );
1487
+ // We're the complete constructor, so get the VTT by name.
1488
+ auto VTT = CGM.getVTables ().getAddrOfVTT (RD);
1489
+ return CGM.getBuilder ().createVTTAddrPoint (
1490
+ Loc, CGM.getBuilder ().getPointerTo (CGM.VoidPtrTy ),
1491
+ mlir::FlatSymbolRefAttr::get (VTT.getSymNameAttr ()), SubVTTIndex);
1464
1492
}
1465
1493
}
1466
1494
@@ -1645,8 +1673,25 @@ CIRGenModule::getDynamicOffsetAlignment(clang::CharUnits actualBaseAlign,
1645
1673
return std::min (actualBaseAlign, expectedTargetAlign);
1646
1674
}
1647
1675
1648
- // / Emit a loop to call a particular constructor for each of several members of
1649
- // / an array.
1676
+ // / Return the best known alignment for a pointer to a virtual base,
1677
+ // / given the alignment of a pointer to the derived class.
1678
+ clang::CharUnits
1679
+ CIRGenModule::getVBaseAlignment (CharUnits actualDerivedAlign,
1680
+ const CXXRecordDecl *derivedClass,
1681
+ const CXXRecordDecl *vbaseClass) {
1682
+ // The basic idea here is that an underaligned derived pointer might
1683
+ // indicate an underaligned base pointer.
1684
+
1685
+ assert (vbaseClass->isCompleteDefinition ());
1686
+ auto &baseLayout = getASTContext ().getASTRecordLayout (vbaseClass);
1687
+ CharUnits expectedVBaseAlign = baseLayout.getNonVirtualAlignment ();
1688
+
1689
+ return getDynamicOffsetAlignment (actualDerivedAlign, derivedClass,
1690
+ expectedVBaseAlign);
1691
+ }
1692
+
1693
+ // / Emit a loop to call a particular constructor for each of several members
1694
+ // / of an array.
1650
1695
// /
1651
1696
// / \param ctor the constructor to call for each element
1652
1697
// / \param arrayType the type of the array to initialize
@@ -1663,8 +1708,8 @@ void CIRGenFunction::buildCXXAggrConstructorCall(
1663
1708
NewPointerIsChecked, zeroInitialize);
1664
1709
}
1665
1710
1666
- // / Emit a loop to call a particular constructor for each of several members of
1667
- // / an array.
1711
+ // / Emit a loop to call a particular constructor for each of several members
1712
+ // / of an array.
1668
1713
// /
1669
1714
// / \param ctor the constructor to call for each element
1670
1715
// / \param numElements the number of elements in the array;
@@ -1749,7 +1794,8 @@ void CIRGenFunction::buildCXXAggrConstructorCall(
1749
1794
AggValueSlot::DoesNotOverlap, AggValueSlot::IsNotZeroed,
1750
1795
NewPointerIsChecked ? AggValueSlot::IsSanitizerChecked
1751
1796
: AggValueSlot::IsNotSanitizerChecked);
1752
- buildCXXConstructorCall (ctor, Ctor_Complete, /* ForVirtualBase=*/ false ,
1797
+ buildCXXConstructorCall (ctor, Ctor_Complete,
1798
+ /* ForVirtualBase=*/ false ,
1753
1799
/* Delegating=*/ false , currAVS, E);
1754
1800
builder.create <mlir::cir::YieldOp>(loc);
1755
1801
});
0 commit comments