[clang] [CIR] Add initial Microsoft C++ ABI support in ClangIR (PR #233291)
Kazu Hirata via cfe-commits
cfe-commits at lists.llvm.org
Sun Oct 18 14:21:21 PDT 2026
================
@@ -114,210 +241,878 @@ class CIRGenMicrosoftCXXABI : public CIRGenCXXABI {
}
const CXXRecordDecl *
- getThisArgumentTypeForMethod(const CXXMethodDecl *md) override {
- cgm.errorNYI(md->getSourceRange(),
- "getThisArgumentTypeForMethod: MSVC ABI");
- return md->getParent();
- }
+ getThisArgumentTypeForMethod(const CXXMethodDecl *md) override;
Address adjustThisArgumentForVirtualFunctionCall(CIRGenFunction &cgf,
GlobalDecl gd,
- Address thisAddr,
- bool virtualCall) override {
- cgf.cgm.errorNYI(gd.getDecl()->getSourceRange(),
- "adjustThisArgumentForVirtualFunctionCall: MSVC ABI");
- return thisAddr;
- }
+ Address thisPtr,
+ bool virtualCall) override;
bool isVirtualOffsetNeededForVTableField(CIRGenFunction &cgf,
CIRGenFunction::VPtr vptr) override {
- cgf.cgm.errorNYI("isVirtualOffsetNeededForVTableField: MSVC ABI");
- return false;
+ return vptr.nearestVBase != nullptr;
}
cir::GlobalOp getAddrOfVTable(const CXXRecordDecl *rd,
- CharUnits vptrOffset) override {
- cgm.errorNYI(rd->getSourceRange(), "getAddrOfVTable: MSVC ABI");
- return nullptr;
- }
+ CharUnits vptrOffset) override;
mlir::Value getVTableAddressPoint(BaseSubobject base,
- const CXXRecordDecl *vtableClass) override {
- cgm.errorNYI(vtableClass->getSourceRange(),
- "getVTableAddressPoint: MSVC ABI");
- return nullptr;
- }
+ const CXXRecordDecl *vtableClass) override;
mlir::Value getVTableAddressPointInStructor(
CIRGenFunction &cgf, const CXXRecordDecl *vtableClass, BaseSubobject base,
- const CXXRecordDecl *nearestVBase) override {
- cgf.cgm.errorNYI(vtableClass->getSourceRange(),
- "getVTableAddressPointInStructor: MSVC ABI");
- return nullptr;
- }
+ const CXXRecordDecl *nearestVBase) override;
CIRGenCallee getVirtualFunctionPointer(CIRGenFunction &cgf, GlobalDecl gd,
Address thisAddr, mlir::Type ty,
- SourceLocation loc) override {
- cgf.cgm.errorNYI(loc, "getVirtualFunctionPointer: MSVC ABI");
- return CIRGenCallee();
- }
+ SourceLocation loc) override;
void emitVTableDefinitions(CIRGenVTables &cgvt,
- const CXXRecordDecl *rd) override {
- cgm.errorNYI(rd->getSourceRange(), "emitVTableDefinitions: MSVC ABI");
- }
+ const CXXRecordDecl *rd) override;
- void emitVirtualInheritanceTables(const CXXRecordDecl *rd) override {
- cgm.errorNYI(rd->getSourceRange(),
- "emitVirtualInheritanceTables: MSVC ABI");
- }
+ void emitVirtualInheritanceTables(const CXXRecordDecl *rd) override;
void
initializeHiddenVirtualInheritanceMembers(CIRGenFunction &cgf,
- const CXXRecordDecl *rd) override {
- cgf.cgm.errorNYI(rd->getSourceRange(),
- "initializeHiddenVirtualInheritanceMembers: MSVC ABI");
- }
+ const CXXRecordDecl *rd) override;
mlir::Value
getVirtualBaseClassOffset(mlir::Location loc, CIRGenFunction &cgf,
Address thisAddr, const CXXRecordDecl *classDecl,
- const CXXRecordDecl *baseClassDecl) override {
- cgf.cgm.errorNYI(loc, "getVirtualBaseClassOffset: MSVC ABI");
- return nullptr;
- }
+ const CXXRecordDecl *baseClassDecl) override;
cir::MethodAttr buildVirtualMethodAttr(cir::MethodType methodTy,
- const CXXMethodDecl *md) override {
- cgm.errorNYI(md->getSourceRange(), "buildVirtualMethodAttr: MSVC ABI");
- return cir::MethodAttr();
- }
+ const CXXMethodDecl *md) override;
mlir::Value performThisAdjustment(CIRGenFunction &cgf, Address thisAddr,
const CXXRecordDecl *unadjustedClass,
- const ThunkInfo &ti) override {
- cgf.cgm.errorNYI("performThisAdjustment: MSVC ABI");
- return thisAddr.emitRawPointer();
- }
+ const ThunkInfo &ti) override;
mlir::Value performReturnAdjustment(CIRGenFunction &cgf, Address ret,
const CXXRecordDecl *unadjustedClass,
- const ReturnAdjustment &ra) override {
- cgf.cgm.errorNYI("performReturnAdjustment: MSVC ABI");
- return ret.emitRawPointer();
+ const ReturnAdjustment &ra) override;
+
+ bool shouldTypeidBeNullChecked(QualType srcTy) override;
+ mlir::Value emitTypeid(CIRGenFunction &cgf, QualType srcTy, Address thisPtr,
+ mlir::Type typeInfoPtrTy) override;
+ void emitBadTypeidCall(CIRGenFunction &cgf, mlir::Location loc) override;
+ void emitBadCastCall(CIRGenFunction &cgf, mlir::Location loc) override;
+
+ mlir::Value emitDynamicCast(CIRGenFunction &cgf, mlir::Location loc,
+ QualType srcRecordTy, QualType destRecordTy,
+ cir::PointerType destCIRTy, bool isRefCast,
+ Address src) override;
+
+ mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc,
+ QualType ty) override;
+ CatchTypeInfo
+ getAddrOfCXXCatchHandlerType(mlir::Location loc, QualType ty,
+ QualType catchHandlerType) override;
+
+ void emitRethrow(CIRGenFunction &cgf, bool isNoReturn) override;
+ void emitThrow(CIRGenFunction &cgf, const CXXThrowExpr *e) override;
+ void registerGlobalDtor(const VarDecl *vd, cir::FuncOp dtor,
+ mlir::Value addr) override;
+};
+
+} // namespace
+
+CharUnits
+CIRGenMicrosoftCXXABI::getVirtualFunctionPrologueThisAdjustment(GlobalDecl gd) {
+ const auto *md = cast<CXXMethodDecl>(gd.getDecl());
+
+ if (const auto *dd = dyn_cast<CXXDestructorDecl>(md)) {
+ if (gd.getDtorType() == Dtor_Complete)
+ return CharUnits();
+
+ gd = GlobalDecl(dd,
+ cgm.getASTContext().getTargetInfo().emitVectorDeletingDtors(
+ cgm.getASTContext().getLangOpts())
+ ? Dtor_VectorDeleting
+ : Dtor_Deleting);
}
- bool canSpeculativelyEmitVTable(const CXXRecordDecl *rd) const override {
- return false;
+ MethodVFTableLocation ml =
+ cgm.getMicrosoftVTableContext().getMethodVFTableLocation(gd);
+ CharUnits adjustment = ml.VFPtrOffset;
+
+ if (isa<CXXDestructorDecl>(md))
+ adjustment = CharUnits::Zero();
+
+ if (ml.VBase) {
+ const ASTRecordLayout &derivedLayout =
+ cgm.getASTContext().getASTRecordLayout(md->getParent());
+ adjustment += derivedLayout.getVBaseClassOffset(ml.VBase);
}
- bool doStructorsInitializeVPtrs(const CXXRecordDecl *vtableClass) override {
- cgm.errorNYI(vtableClass->getSourceRange(),
- "doStructorsInitializeVPtrs: MSVC ABI");
- return false;
+ return adjustment;
+}
+
+mlir::Value CIRGenMicrosoftCXXABI::getVBaseOffsetFromVBPtr(
+ CIRGenFunction &cgf, mlir::Location loc, Address thisAddr,
+ int64_t vbPtrOffset, unsigned vbTableIndex, mlir::Value *vbPtrOut) {
+ CIRGenBuilderTy &builder = cgf.getBuilder();
+ cir::PointerType u8PtrTy = builder.getUInt8PtrTy();
+ mlir::Value thisBytePtr =
+ builder.createBitcast(thisAddr.getPointer(), u8PtrTy);
+
+ mlir::Value vbPtrOffsetVal = builder.getSInt32(vbPtrOffset, loc);
+ mlir::Value vbPtr = cir::PtrStrideOp::create(builder, loc, u8PtrTy,
+ thisBytePtr, vbPtrOffsetVal);
+ if (vbPtrOut)
+ *vbPtrOut = vbPtr;
+
+ CharUnits vbPtrAlign = cgf.getPointerAlign();
+ Address vbPtrAddr(builder.createBitcast(vbPtr, builder.getPointerTo(u8PtrTy)),
+ u8PtrTy, vbPtrAlign);
+ mlir::Value vbTable = builder.createLoad(loc, vbPtrAddr);
+
+ mlir::Type i32Ty = builder.getSInt32Ty();
+ cir::PointerType i32PtrTy = builder.getPointerTo(i32Ty);
+ mlir::Value vbTableI32Ptr = builder.createBitcast(vbTable, i32PtrTy);
+ mlir::Value vbTableIndexVal = builder.getSInt32(vbTableIndex, loc);
+ mlir::Value vbaseOffsPtr = cir::PtrStrideOp::create(
+ builder, loc, i32PtrTy, vbTableI32Ptr, vbTableIndexVal);
+ Address vbaseOffsAddr(vbaseOffsPtr, i32Ty, CharUnits::fromQuantity(4));
+ return builder.createLoad(loc, vbaseOffsAddr);
+}
+
+Address CIRGenMicrosoftCXXABI::initializeArrayCookie(CIRGenFunction &cgf,
+ Address newPtr,
+ mlir::Value numElements,
+ const CXXNewExpr *e,
+ QualType elementType) {
+ assert(requiresArrayCookie(e));
+ CharUnits cookieSize = getArrayCookieSizeImpl(elementType);
+ mlir::Location loc = cgf.getLoc(e->getSourceRange());
+
+ mlir::Type u8Ty = cgf.getBuilder().getUInt8Ty();
+ cir::PointerType u8PtrTy = cgf.getBuilder().getUInt8PtrTy();
+ mlir::Value baseBytePtr =
+ cgf.getBuilder().createBitcast(newPtr.getPointer(), u8PtrTy);
+
+ // In the MSVC ABI, the cookie is located at offset 0 of newPtr.
+ CharUnits baseAlignment = newPtr.getAlignment();
+ Address cookiePtr(baseBytePtr, u8Ty, baseAlignment);
+ Address numElementsPtr =
+ cookiePtr.withElementType(cgf.getBuilder(), cgf.sizeTy);
+ cgf.getBuilder().createStore(loc, numElements, numElementsPtr);
+
+ // Skip over the cookie to return the pointer to the element array.
+ mlir::Value dataOffset =
+ cgf.getBuilder().getSInt32(cookieSize.getQuantity(), loc);
+ mlir::Value dataPtr =
+ cgf.getBuilder().createPtrStride(loc, baseBytePtr, dataOffset);
+ mlir::Value finalPtr =
+ cgf.getBuilder().createPtrBitcast(dataPtr, newPtr.getElementType());
+ CharUnits finalAlignment = baseAlignment.alignmentAtOffset(cookieSize);
+ return Address(finalPtr, newPtr.getElementType(), finalAlignment);
+}
+
+CIRGenCXXABI::AddedStructorArgCounts
+CIRGenMicrosoftCXXABI::buildStructorSignature(
+ GlobalDecl gd, llvm::SmallVectorImpl<CanQualType> &argTys) {
+ AddedStructorArgCounts added;
+ if (isa<CXXDestructorDecl>(gd.getDecl()) &&
+ (gd.getDtorType() == Dtor_Deleting ||
+ gd.getDtorType() == Dtor_VectorDeleting)) {
+ argTys.push_back(cgm.getASTContext().IntTy);
+ ++added.suffix;
}
+ auto *cd = dyn_cast<CXXConstructorDecl>(gd.getDecl());
+ if (!cd)
+ return added;
- bool exportThunk() override { return false; }
+ const CXXRecordDecl *classDecl = cd->getParent();
+ const FunctionProtoType *fpt = cd->getType()->castAs<FunctionProtoType>();
+ if (classDecl->getNumVBases()) {
+ if (fpt->isVariadic()) {
+ argTys.insert(argTys.begin() + 1, cgm.getASTContext().IntTy);
+ ++added.prefix;
+ } else {
+ argTys.push_back(cgm.getASTContext().IntTy);
+ ++added.suffix;
+ }
+ }
- bool useThunkForDtorVariant(const CXXDestructorDecl *dtor,
- CXXDtorType dt) const override {
- cgm.errorNYI(dtor->getSourceRange(), "useThunkForDtorVariant: MSVC ABI");
- return false;
+ return added;
+}
+
+void CIRGenMicrosoftCXXABI::addImplicitStructorParams(CIRGenFunction &cgf,
+ QualType &resTy,
+ FunctionArgList ¶ms) {
+ ASTContext &context = cgm.getASTContext();
+ const auto *md = cast<CXXMethodDecl>(cgf.curGD.getDecl());
+ assert(isa<CXXConstructorDecl>(md) || isa<CXXDestructorDecl>(md));
+
+ if (isa<CXXConstructorDecl>(md) && md->getParent()->getNumVBases()) {
+ auto *isMostDerived = ImplicitParamDecl::Create(
+ context, /*DC=*/nullptr, cgf.curGD.getDecl()->getLocation(),
+ &context.Idents.get("is_most_derived"), context.IntTy,
+ ImplicitParamKind::Other);
+ const FunctionProtoType *fpt = md->getType()->castAs<FunctionProtoType>();
+ if (fpt->isVariadic())
+ params.insert(params.begin() + 1, isMostDerived);
+ else
+ params.push_back(isMostDerived);
+ getStructorImplicitParamDecl(cgf) = isMostDerived;
+ } else if (isDeletingDtor(cgf.curGD)) {
+ auto *shouldDelete = ImplicitParamDecl::Create(
+ context, /*DC=*/nullptr, cgf.curGD.getDecl()->getLocation(),
+ &context.Idents.get("should_call_delete"), context.IntTy,
+ ImplicitParamKind::Other);
+ params.push_back(shouldDelete);
+ getStructorImplicitParamDecl(cgf) = shouldDelete;
}
+}
- void setThunkLinkage(cir::FuncOp thunk, bool forVTable, GlobalDecl gd,
- bool returnAdjustment) override {
- cgm.errorNYI(gd.getDecl()->getSourceRange(), "setThunkLinkage: MSVC ABI");
+void CIRGenMicrosoftCXXABI::emitInstanceFunctionProlog(SourceLocation loc,
+ CIRGenFunction &cgf) {
+ if (cgf.curFuncDecl && cgf.curFuncDecl->hasAttr<NakedAttr>())
+ return;
+
+ mlir::Value thisVal = loadIncomingCXXThis(cgf);
+ const auto *md = cast<CXXMethodDecl>(cgf.curGD.getDecl());
+ if (!cgf.curFuncIsThunk && md->isVirtual()) {
+ CharUnits adjustment = getVirtualFunctionPrologueThisAdjustment(cgf.curGD);
+ if (!adjustment.isZero()) {
+ assert(adjustment.isPositive());
+ CIRGenBuilderTy &builder = cgf.getBuilder();
+ mlir::Location mlirLoc = cgf.getLoc(loc);
+ cir::PointerType u8PtrTy = builder.getUInt8PtrTy();
+ mlir::Value u8This = builder.createBitcast(thisVal, u8PtrTy);
+ mlir::Value negAdj =
+ builder.getSInt32(-adjustment.getQuantity(), mlirLoc);
+ mlir::Value adjusted =
+ cir::PtrStrideOp::create(builder, mlirLoc, u8PtrTy, u8This, negAdj);
+ thisVal = builder.createBitcast(adjusted, thisVal.getType());
+ }
}
+ setCXXABIThisValue(cgf, thisVal);
- StringRef getPureVirtualCallName() override { return "_purecall"; }
- StringRef getDeletedVirtualCallName() override { return "_purecall"; }
+ if (hasThisReturn(cgf.curGD) || hasMostDerivedReturn(cgf.curGD)) {
+ if (cgf.returnValue.isValid())
+ cgf.getBuilder().createStore(cgf.getLoc(loc), thisVal, cgf.returnValue);
+ }
- bool isZeroInitializable(const MemberPointerType *mpt) override {
- cgm.errorNYI("isZeroInitializable: MSVC ABI");
- return true;
+ if (isa<CXXConstructorDecl>(md) && md->getParent()->getNumVBases()) {
+ assert(getStructorImplicitParamDecl(cgf) &&
+ "no implicit parameter for a constructor with virtual bases?");
+ Address addr = cgf.getAddrOfLocalVar(getStructorImplicitParamDecl(cgf));
+ setStructorImplicitParamValue(
+ cgf, cgf.getBuilder().createLoad(cgf.getLoc(loc), addr));
}
- bool requiresArrayCookie(const CXXNewExpr *e) override {
- cgm.errorNYI(e->getSourceRange(), "requiresArrayCookie: MSVC ABI");
- return false;
+ if (isDeletingDtor(cgf.curGD)) {
+ assert(getStructorImplicitParamDecl(cgf) &&
+ "no implicit parameter for a deleting destructor?");
+ Address addr = cgf.getAddrOfLocalVar(getStructorImplicitParamDecl(cgf));
+ setStructorImplicitParamValue(
+ cgf, cgf.getBuilder().createLoad(cgf.getLoc(loc), addr));
}
+}
- CharUnits getArrayCookieSizeImpl(QualType elementType) override {
- cgm.errorNYI("getArrayCookieSizeImpl: MSVC ABI");
- return CharUnits::Zero();
+CIRGenCXXABI::AddedStructorArgs
+CIRGenMicrosoftCXXABI::getImplicitConstructorArgs(CIRGenFunction &cgf,
+ const CXXConstructorDecl *d,
+ CXXCtorType type,
+ bool forVirtualBase,
+ bool delegating) {
+ assert(type == Ctor_Complete || type == Ctor_Base);
+
+ if (!d->getParent()->getNumVBases())
+ return AddedStructorArgs{};
+
+ const FunctionProtoType *fpt = d->getType()->castAs<FunctionProtoType>();
+ mlir::Value mostDerivedArg;
+ CIRGenBuilderTy &builder = cgf.getBuilder();
+ mlir::Location loc = cgf.getLoc(d->getLocation());
+ if (delegating) {
+ mostDerivedArg = getStructorImplicitParamValue(cgf);
+ } else {
+ mostDerivedArg = builder.getSInt32(type == Ctor_Complete ? 1 : 0, loc);
+ }
+ if (fpt->isVariadic()) {
+ return AddedStructorArgs::withPrefix(
+ {{mostDerivedArg, cgm.getASTContext().IntTy}});
}
+ return AddedStructorArgs::withSuffix(
+ {{mostDerivedArg, cgm.getASTContext().IntTy}});
+}
- Address initializeArrayCookie(CIRGenFunction &cgf, Address newPtr,
- mlir::Value numElements, const CXXNewExpr *e,
- QualType elementType) override {
- cgf.cgm.errorNYI(e->getSourceRange(), "initializeArrayCookie: MSVC ABI");
- return newPtr;
+void CIRGenMicrosoftCXXABI::emitCXXConstructors(const CXXConstructorDecl *d) {
+ cgm.emitGlobal(GlobalDecl(d, Ctor_Complete));
+}
+
+void CIRGenMicrosoftCXXABI::emitCXXDestructors(const CXXDestructorDecl *d) {
+ cgm.emitGlobal(GlobalDecl(d, Dtor_Base));
+
+ if (d->getParent()->getNumVBases() > 0 && d->hasAttr<DLLExportAttr>())
+ cgm.emitGlobal(GlobalDecl(d, Dtor_Complete));
+}
+
+void CIRGenMicrosoftCXXABI::emitCXXStructor(GlobalDecl gd) {
+ if (auto *ctor = dyn_cast<CXXConstructorDecl>(gd.getDecl())) {
+ auto fn = cgm.codegenCXXStructor(gd.getWithCtorType(Ctor_Complete));
+ cgm.maybeSetTrivialComdat(*ctor, fn);
+ return;
}
- bool shouldTypeidBeNullChecked(QualType srcTy) override {
- cgm.errorNYI("shouldTypeidBeNullChecked: MSVC ABI");
- return false;
+ auto *dtor = cast<CXXDestructorDecl>(gd.getDecl());
+ if (gd.getDtorType() == Dtor_Complete &&
+ dtor->getParent()->getNumVBases() == 0)
+ gd = gd.getWithDtorType(Dtor_Base);
+
+ if (gd.getDtorType() == Dtor_Deleting ||
+ gd.getDtorType() == Dtor_VectorDeleting) {
+ cgm.errorNYI(dtor->getSourceRange(),
+ "emitCXXStructor: MSVC deleting destructor");
+ return;
}
- mlir::Value emitTypeid(CIRGenFunction &cgf, QualType srcTy, Address thisPtr,
- mlir::Type typeInfoPtrTy) override {
- cgf.cgm.errorNYI(cgf.getLoc(srcTy->getAsCXXRecordDecl()->getLocation()),
- "emitTypeid: MSVC ABI");
- return cgf.getBuilder().getNullPtr(
- typeInfoPtrTy, cgf.getLoc(srcTy->getAsCXXRecordDecl()->getLocation()));
+ auto fn = cgm.codegenCXXStructor(gd);
+ cgm.maybeSetTrivialComdat(*dtor, fn);
+}
+
+void CIRGenMicrosoftCXXABI::emitDestructorCall(
+ CIRGenFunction &cgf, const CXXDestructorDecl *dd, CXXDtorType type,
+ bool forVirtualBase, bool delegating, Address thisAddr, QualType thisTy) {
+ if (type == Dtor_Complete && dd->getParent()->getNumVBases() == 0)
+ type = Dtor_Base;
+
+ GlobalDecl gd(dd, type);
+ CIRGenCallee callee =
+ CIRGenCallee::forDirect(cgm.getAddrOfCXXStructor(gd).getOperation(), gd);
+
+ if (dd->isVirtual()) {
+ assert(type != CXXDtorType::Dtor_Deleting &&
+ "The deleting destructor should only be called via a virtual call");
+ thisAddr = adjustThisArgumentForVirtualFunctionCall(
+ cgf, GlobalDecl(dd, type), thisAddr, false);
}
- void emitBadTypeidCall(CIRGenFunction &cgf, mlir::Location loc) override {
- cgf.cgm.errorNYI(loc, "emitBadTypeidCall: MSVC ABI");
+ cgf.emitCXXDestructorCall(gd, callee, thisAddr.emitRawPointer(), thisTy,
+ /*implicitParam=*/nullptr,
+ /*implicitParamTy=*/QualType(), /*e=*/nullptr);
+}
+
+mlir::Value CIRGenMicrosoftCXXABI::emitVirtualDestructorCall(
+ CIRGenFunction &cgf, const CXXDestructorDecl *dtor, CXXDtorType dtorType,
+ Address thisAddr, DeleteOrMemberCallExpr e) {
+ auto *ce = dyn_cast<const CXXMemberCallExpr *>(e);
+ auto *de = dyn_cast<const CXXDeleteExpr *>(e);
+ assert((ce != nullptr) ^ (de != nullptr));
+ assert(ce == nullptr || ce->arg_begin() == ce->arg_end());
+
+ ASTContext &context = cgm.getASTContext();
+ bool vectorDeletingDtorsEnabled =
+ context.getTargetInfo().emitVectorDeletingDtors(context.getLangOpts());
+ GlobalDecl gd(dtor, vectorDeletingDtorsEnabled ? Dtor_VectorDeleting
+ : Dtor_Deleting);
+ const CIRGenFunctionInfo *fInfo =
+ &cgm.getTypes().arrangeCXXStructorDeclaration(gd);
+ cir::FuncType ty = cgm.getTypes().getFunctionType(*fInfo);
+ CIRGenCallee callee = CIRGenCallee::forVirtual(ce, gd, thisAddr, ty);
+
+ bool isDeleting = dtorType == Dtor_Deleting;
+ bool isArrayDelete = de && de->isArrayForm() && vectorDeletingDtorsEnabled;
+ bool isGlobalDelete = de && de->isGlobalDelete() &&
+ context.getTargetInfo().callGlobalDeleteInDeletingDtor(
+ context.getLangOpts());
+ int32_t flags =
+ (isDeleting ? 1 : 0) | (isGlobalDelete ? 4 : 0) | (isArrayDelete ? 2 : 0);
+ mlir::Value implicitParam =
+ cgf.getBuilder().getSInt32(flags, cgf.getLoc(dtor->getLocation()));
+
+ QualType thisTy;
+ if (ce)
+ thisTy = ce->getObjectType();
+ else
+ thisTy = de->getDestroyedType();
+
+ while (const ArrayType *aTy = context.getAsArrayType(thisTy))
+ thisTy = aTy->getElementType();
+
+ thisAddr = adjustThisArgumentForVirtualFunctionCall(cgf, gd, thisAddr, true);
+ cgf.emitCXXDestructorCall(gd, callee, thisAddr.emitRawPointer(), thisTy,
+ implicitParam, context.IntTy, ce);
+ return nullptr;
+}
+
+void CIRGenMicrosoftCXXABI::emitVirtualObjectDelete(
+ CIRGenFunction &cgf, const CXXDeleteExpr *de, Address ptr,
+ QualType elementType, const CXXDestructorDecl *dtor) {
+ if (!cgm.getASTContext().getTargetInfo().callGlobalDeleteInDeletingDtor(
+ cgm.getASTContext().getLangOpts())) {
+ cgf.cgm.errorNYI(de->getSourceRange(),
+ "emitVirtualObjectDelete: legacy global delete without "
+ "deleting dtor flag");
+ return;
}
+ emitVirtualDestructorCall(cgf, dtor, Dtor_Deleting, ptr, de);
+}
- void emitBadCastCall(CIRGenFunction &cgf, mlir::Location loc) override {
- cgm.errorNYI(loc, "emitBadCastCall: MSVC ABI");
+const CXXRecordDecl *
+CIRGenMicrosoftCXXABI::getThisArgumentTypeForMethod(const CXXMethodDecl *md) {
+ if (md->isVirtual()) {
+ GlobalDecl lookupGD;
+ if (const auto *dd = dyn_cast<CXXDestructorDecl>(md)) {
+ lookupGD = GlobalDecl(
+ dd, cgm.getASTContext().getTargetInfo().emitVectorDeletingDtors(
+ cgm.getASTContext().getLangOpts())
+ ? Dtor_VectorDeleting
+ : Dtor_Deleting);
+ } else {
+ lookupGD = GlobalDecl(md);
+ }
+ MethodVFTableLocation ml =
+ cgm.getMicrosoftVTableContext().getMethodVFTableLocation(lookupGD);
+ if (ml.VBase || !ml.VFPtrOffset.isZero())
+ return nullptr;
}
+ return md->getParent();
+}
- mlir::Value emitDynamicCast(CIRGenFunction &cgf, mlir::Location loc,
- QualType srcRecordTy, QualType destRecordTy,
- cir::PointerType destCIRTy, bool isRefCast,
- Address src) override {
- cgf.cgm.errorNYI(loc, "emitDynamicCast: MSVC ABI");
- return cgf.getBuilder().getNullPtr(destCIRTy, loc);
+Address CIRGenMicrosoftCXXABI::adjustThisArgumentForVirtualFunctionCall(
+ CIRGenFunction &cgf, GlobalDecl gd, Address thisAddr, bool virtualCall) {
+ if (!virtualCall) {
+ CharUnits adjustment = getVirtualFunctionPrologueThisAdjustment(gd);
+ if (adjustment.isZero())
+ return thisAddr;
+
+ CIRGenBuilderTy &builder = cgf.getBuilder();
+ mlir::Location loc = cgf.getLoc(gd.getDecl()->getLocation());
+ cir::PointerType u8PtrTy = builder.getUInt8PtrTy();
+ mlir::Value u8This = builder.createBitcast(thisAddr.getPointer(), u8PtrTy);
+ assert(adjustment.isPositive());
+ mlir::Value adjConst = builder.getSInt32(adjustment.getQuantity(), loc);
+ mlir::Value adjusted =
+ cir::PtrStrideOp::create(builder, loc, u8PtrTy, u8This, adjConst);
+ return Address(builder.createBitcast(adjusted, thisAddr.getElementType()),
+ thisAddr.getElementType(), thisAddr.getAlignment());
}
- mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc,
- QualType ty) override {
- cgm.errorNYI(loc, "getAddrOfRTTIDescriptor: MSVC ABI");
+ const auto *md = cast<CXXMethodDecl>(gd.getDecl());
+ GlobalDecl lookupGD = gd;
+ if (const auto *dd = dyn_cast<CXXDestructorDecl>(md)) {
+ if (gd.getDtorType() == Dtor_Complete)
+ return thisAddr;
+
+ lookupGD = GlobalDecl(
+ dd, cgm.getASTContext().getTargetInfo().emitVectorDeletingDtors(
+ cgm.getASTContext().getLangOpts())
+ ? Dtor_VectorDeleting
+ : Dtor_Deleting);
+ }
+ MethodVFTableLocation ml =
+ cgm.getMicrosoftVTableContext().getMethodVFTableLocation(lookupGD);
+
+ CharUnits staticOffset = ml.VFPtrOffset;
+ if (isa<CXXDestructorDecl>(md) && gd.getDtorType() == Dtor_Base)
+ staticOffset = CharUnits::Zero();
+
+ Address result = thisAddr;
+ CIRGenBuilderTy &builder = cgf.getBuilder();
+ mlir::Location loc = cgf.getLoc(gd.getDecl()->getLocation());
+ cir::PointerType u8PtrTy = builder.getUInt8PtrTy();
+
+ if (ml.VBase) {
+ const CXXRecordDecl *derived = md->getParent();
+ const CXXRecordDecl *vbase = ml.VBase;
+ mlir::Value vbaseOffset =
+ getVirtualBaseClassOffset(loc, cgf, result, derived, vbase);
+ mlir::Value rawPtr = builder.createBitcast(result.getPointer(), u8PtrTy);
+ mlir::Value vbasePtr =
+ cir::PtrStrideOp::create(builder, loc, u8PtrTy, rawPtr, vbaseOffset);
+ CharUnits vbaseAlign =
+ cgm.getVBaseAlignment(result.getAlignment(), derived, vbase);
+ result = Address(vbasePtr, builder.getUInt8Ty(), vbaseAlign);
+ }
+
+ if (!staticOffset.isZero()) {
+ assert(staticOffset.isPositive());
+ mlir::Value rawPtr = builder.createBitcast(result.getPointer(), u8PtrTy);
+ mlir::Value offsetVal = builder.getSInt32(staticOffset.getQuantity(), loc);
+ mlir::Value adjustedPtr =
+ cir::PtrStrideOp::create(builder, loc, u8PtrTy, rawPtr, offsetVal);
+ result = Address(adjustedPtr, builder.getUInt8Ty(),
+ result.getAlignment().alignmentAtOffset(staticOffset));
+ }
+
+ if (result.getElementType() != thisAddr.getElementType()) {
+ mlir::Value castPtr =
+ builder.createBitcast(result.getPointer(), thisAddr.getElementType());
+ result = Address(castPtr, thisAddr.getElementType(), result.getAlignment());
+ }
+
+ return result;
+}
+
+cir::GlobalOp CIRGenMicrosoftCXXABI::getAddrOfVTable(const CXXRecordDecl *rd,
+ CharUnits vptrOffset) {
+ VFTableIdTy id(rd, vptrOffset);
+ auto it = vftablesMap.find(id);
+ if (it != vftablesMap.end())
+ return it->second;
----------------
kazutakahirata wrote:
Could we use `try_emplace` here and bind `cir::GlobalOp &vtable = it->second;` so that we can assign to `vtable` directly and avoid repeating the `vftablesMap[id]` lookup later in this function?
```cpp
VFTableIdTy id(rd, vptrOffset);
auto [it, inserted] = vftablesMap.try_emplace(id);
if (!inserted)
return it->second;
cir::GlobalOp &vtable = it->second;
```
https://github.com/llvm/llvm-project/pull/233291
More information about the cfe-commits
mailing list