-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[CIR] Add initial support for virtual base classes #155534
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -238,31 +238,44 @@ void CIRGenFunction::emitCtorPrologue(const CXXConstructorDecl *cd, | |
| bool constructVBases = ctorType != Ctor_Base && | ||
| classDecl->getNumVBases() != 0 && | ||
| !classDecl->isAbstract(); | ||
| if (constructVBases) { | ||
| cgm.errorNYI(cd->getSourceRange(), "emitCtorPrologue: virtual base"); | ||
| return; | ||
| } | ||
|
|
||
| const mlir::Value oldThisValue = cxxThisValue; | ||
| if (!constructVBases && b != e && (*b)->isBaseInitializer() && | ||
| (*b)->isBaseVirtual()) { | ||
| if (constructVBases && | ||
| !cgm.getTarget().getCXXABI().hasConstructorVariants()) { | ||
| cgm.errorNYI(cd->getSourceRange(), | ||
| "emitCtorPrologue: virtual base initializer"); | ||
| "emitCtorPrologue: virtual base without variants"); | ||
| return; | ||
| } | ||
|
|
||
| // Handle non-virtual base initializers. | ||
| for (; b != e && (*b)->isBaseInitializer(); b++) { | ||
| assert(!(*b)->isBaseVirtual()); | ||
| const mlir::Value oldThisValue = cxxThisValue; | ||
|
|
||
| // Initialize virtual bases. | ||
| auto emitInitializer = [&](CXXCtorInitializer *baseInit) { | ||
| if (cgm.getCodeGenOpts().StrictVTablePointers && | ||
| cgm.getCodeGenOpts().OptimizationLevel > 0 && | ||
| isInitializerOfDynamicClass(*b)) { | ||
| isInitializerOfDynamicClass(baseInit)) { | ||
| // It's OK to continue after emitting the error here. The missing code | ||
| // just "launders" the 'this' pointer. | ||
| cgm.errorNYI(cd->getSourceRange(), | ||
| "emitCtorPrologue: strict vtable pointers"); | ||
| return; | ||
| "emitCtorPrologue: strict vtable pointers for vbase"); | ||
| } | ||
| emitBaseInitializer(getLoc(cd->getBeginLoc()), classDecl, *b); | ||
| emitBaseInitializer(getLoc(cd->getBeginLoc()), classDecl, baseInit); | ||
| }; | ||
|
|
||
| for (; b != e && (*b)->isBaseInitializer() && (*b)->isBaseVirtual(); b++) { | ||
| if (!constructVBases) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this inside the loop rather than preventing this loop from happening at all? Also, is there any sort of range loop we can use here? Thisis awful ugly...
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is inside the loop because if we are not constructing vbases we need to update the iterator to move past them. The initializers are ordered such that all virtual bases occur before the first non-virtual base. This loop is necessary to position the iterator for the loop below. The MS CXXABI throws a bit of a wrench into the possibility of a range loop, because we need to insert a branch to a continue block between the virtual initializers and the non-virtual initializers, but we can probably use a flag to check for the conditions to do that. I'll play around with this loop in OGCG and see if I can simplify it without breaking anything.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, right! I missed the same iterators. Anything you can do to make this less awful would be appreciated :)
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm proceeding with the implementation change modeled after the classic codegen change proposed in #155668. If that ends up being rejected, I'll update this accordingly. |
||
| continue; | ||
| emitInitializer(*b); | ||
| } | ||
|
|
||
| // The loop above and the loop below could obviously be merged in their | ||
| // current form, but when we implement support for the MS C++ ABI, we will | ||
| // need to insert a branch after the last virtual base initializer, so | ||
| // separate loops will be useful then. The missing code is covered by the | ||
| // "virtual base without variants" diagnostic above. | ||
|
|
||
| // Handle non-virtual base initializers. | ||
| for (; b != e && (*b)->isBaseInitializer(); b++) { | ||
| assert(!(*b)->isBaseVirtual()); | ||
| emitInitializer(*b); | ||
| } | ||
|
|
||
| cxxThisValue = oldThisValue; | ||
|
|
@@ -370,7 +383,7 @@ void CIRGenFunction::initializeVTablePointers(mlir::Location loc, | |
| initializeVTablePointer(loc, vptr); | ||
|
|
||
| if (rd->getNumVBases()) | ||
| cgm.errorNYI(loc, "initializeVTablePointers: virtual base"); | ||
| cgm.getCXXABI().initializeHiddenVirtualInheritanceMembers(*this, rd); | ||
| } | ||
|
|
||
| CIRGenFunction::VPtrsVector | ||
|
|
@@ -418,8 +431,17 @@ void CIRGenFunction::getVTablePointers(BaseSubobject base, | |
| const CXXRecordDecl *nextBaseDecl; | ||
|
|
||
| if (nextBase.isVirtual()) { | ||
| cgm.errorNYI(rd->getSourceRange(), "getVTablePointers: virtual base"); | ||
| return; | ||
| // Check if we've visited this virtual base before. | ||
| if (!vbases.insert(baseDecl).second) | ||
| continue; | ||
|
|
||
| const ASTRecordLayout &layout = | ||
| getContext().getASTRecordLayout(vtableClass); | ||
|
|
||
| nextBaseDecl = nearestVBase; | ||
| baseOffset = layout.getVBaseClassOffset(baseDecl); | ||
| baseOffsetFromNearestVBase = CharUnits::Zero(); | ||
| baseDeclIsNonVirtualPrimaryBase = false; | ||
| } else { | ||
| const ASTRecordLayout &layout = getContext().getASTRecordLayout(rd); | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.