llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clangir Author: R-Goc <details> <summary>Changes</summary> * Implement foundational CIRGenMicrosoftCXXABI class and driver wiring. * Implement string literal mangling (??_C@<!-- -->_). * Implement constructor this-return (hasThisReturn). * Add initial lit test in clang/test/CIR/CodeGen/cxx-msvc-abi.cpp. Assisted-by: Gemini:gemini-3.8-flash-high --- Patch is 71.04 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/233291.diff 11 Files Affected: - (modified) clang/lib/CIR/CodeGen/CIRGenCall.cpp (+4-10) - (modified) clang/lib/CIR/CodeGen/CIRGenClass.cpp (-1) - (modified) clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp (+5-2) - (modified) clang/lib/CIR/CodeGen/CIRGenFunction.cpp (+2-2) - (modified) clang/lib/CIR/CodeGen/CIRGenMicrosoftCXXABI.cpp (+965-170) - (modified) clang/lib/CIR/CodeGen/CIRGenModule.cpp (+29-16) - (modified) clang/lib/CIR/CodeGen/CIRGenModule.h (+7) - (modified) clang/lib/CIR/CodeGen/CIRGenVTables.h (+8) - (modified) clang/lib/CIR/CodeGen/CIRGenerator.cpp (+10-2) - (modified) clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerMicrosoftCXXABI.cpp (+9-3) - (modified) clang/test/CIR/CodeGen/cxx-msvc-abi.cpp (+122-2) ``````````diff diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp index c562e4308c1ab0..79a628e2f5b051 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp @@ -900,9 +900,6 @@ CIRGenTypes::arrangeCXXStructorDeclaration(GlobalDecl gd) { ? astContext.VoidPtrTy : astContext.VoidTy; - assert(!theCXXABI.hasThisReturn(gd) && - "Please send PR with a test and remove this"); - assert(!cir::MissingFeatures::opCallCIRGenFuncInfoExtParamInfo()); assert(!cir::MissingFeatures::opCallFnInfoOpts()); @@ -1038,13 +1035,10 @@ const CIRGenFunctionInfo &CIRGenTypes::arrangeCXXConstructorCall( : RequiredArgs::All; GlobalDecl gd(d, ctorKind); - if (theCXXABI.hasThisReturn(gd)) - cgm.errorNYI(d->getSourceRange(), - "arrangeCXXConstructorCall: hasThisReturn"); - if (theCXXABI.hasMostDerivedReturn(gd)) - cgm.errorNYI(d->getSourceRange(), - "arrangeCXXConstructorCall: hasMostDerivedReturn"); - CanQualType resultType = astContext.VoidTy; + CanQualType resultType = theCXXABI.hasThisReturn(gd) ? argTypes.front() + : theCXXABI.hasMostDerivedReturn(gd) + ? astContext.VoidPtrTy + : astContext.VoidTy; assert(!cir::MissingFeatures::opCallFnInfoOpts()); assert(!cir::MissingFeatures::opCallCIRGenFuncInfoExtParamInfo()); diff --git a/clang/lib/CIR/CodeGen/CIRGenClass.cpp b/clang/lib/CIR/CodeGen/CIRGenClass.cpp index 9e6ff99792500a..2ea99be02dc3f1 100644 --- a/clang/lib/CIR/CodeGen/CIRGenClass.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenClass.cpp @@ -1053,7 +1053,6 @@ void CIRGenFunction::enterDtorCleanups(const CXXDestructorDecl *dd, "only the Microsoft ABI passes an implicit deleting dtor param"); cgm.errorNYI(dd->getSourceRange(), "deleting destructor with conditional delete: MSVC ABI"); - } else { assert(!dd->getOperatorDelete()->isDestroyingOperatorDelete() && "destroying operator delete is handled by emitDestructorBody"); diff --git a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp index decddca749d835..e80a2e6498fc33 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp @@ -342,8 +342,11 @@ static void emitNullBaseClassInitialization(CIRGenFunction &cgf, stores.emplace_back(CharUnits::Zero(), nvSize); // Each store is split by the existence of a vbptr. - // TODO(cir): This only needs handling for the MS CXXABI. - assert(!cir::MissingFeatures::msabi()); + if (cgf.cgm.getTarget().getCXXABI().isMicrosoft() && base->getNumVBases()) { + cgf.cgm.errorNYI(base->getSourceRange(), + "emitNullBaseClassInitialization: MSVC vbptr splitting"); + return; + } // If the type contains a pointer to data member we can't memset it to zero. // Instead, create a null constant and copy it to the destination. diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp index 1fa57c4087da2c..89030b720b3b43 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp @@ -1082,9 +1082,9 @@ clang::QualType CIRGenFunction::buildFunctionArgList(clang::GlobalDecl gd, const auto *md = dyn_cast<CXXMethodDecl>(fd); if (md && md->isImplicitObjectMemberFunction()) { if (cgm.getCXXABI().hasThisReturn(gd)) - cgm.errorNYI(fd->getSourceRange(), "this return"); + retTy = md->getThisType(); else if (cgm.getCXXABI().hasMostDerivedReturn(gd)) - cgm.errorNYI(fd->getSourceRange(), "most derived return"); + retTy = getContext().VoidPtrTy; cgm.getCXXABI().buildThisParam(*this, args); } diff --git a/clang/lib/CIR/CodeGen/CIRGenMicrosoftCXXABI.cpp b/clang/lib/CIR/CodeGen/CIRGenMicrosoftCXXABI.cpp index 276e3e93cdda0f..8e5dc211b6953d 100644 --- a/clang/lib/CIR/CodeGen/CIRGenMicrosoftCXXABI.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenMicrosoftCXXABI.cpp @@ -1,4 +1,4 @@ -//===--- CIRGenMicrosoftCXXABI.cpp - Emit CIR Code for MS C++ ABI --------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,7 +6,10 @@ // //===----------------------------------------------------------------------===// // -// This provides C++ code generation targeting the Microsoft C++ ABI. +// This provides C++ code generation targeting the Microsoft C++ ABI. The class +// in this file generates structures that follow the Microsoft C++ ABI, which is +// documented at: +// https://learn.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170 // //===----------------------------------------------------------------------===// @@ -14,95 +17,219 @@ #include "CIRGenFunction.h" #include "CIRGenModule.h" +#include "clang/AST/Attr.h" +#include "clang/AST/CXXInheritance.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/Mangle.h" +#include "clang/AST/RecordLayout.h" +#include "clang/AST/VTableBuilder.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/CIR/MissingFeatures.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" using namespace clang; using namespace clang::CIRGen; namespace { +static bool isDeletingDtor(GlobalDecl gd) { + return isa<CXXDestructorDecl>(gd.getDecl()) && + (gd.getDtorType() == Dtor_Deleting || + gd.getDtorType() == Dtor_VectorDeleting); +} + +static QualType decomposeTypeForEH(ASTContext &context, QualType t, + bool &isConst, bool &isVolatile, + bool &isUnaligned) { + t = context.getExceptionObjectType(t); + isConst = false; + isVolatile = false; + isUnaligned = false; + QualType pointeeType = t->getPointeeType(); + if (!pointeeType.isNull()) { + isConst = pointeeType.isConstQualified(); + isVolatile = pointeeType.isVolatileQualified(); + isUnaligned = pointeeType.getQualifiers().hasUnaligned(); + } + if (const auto *mpty = t->getAs<MemberPointerType>()) + t = context.getMemberPointerType(pointeeType.getUnqualifiedType(), + mpty->getQualifier(), + mpty->getMostRecentCXXRecordDecl()); + if (t->isPointerType()) + t = context.getPointerType(pointeeType.getUnqualifiedType()); + return t; +} + class CIRGenMicrosoftCXXABI : public CIRGenCXXABI { + using VFTableIdTy = std::pair<const CXXRecordDecl *, CharUnits>; + llvm::DenseMap<VFTableIdTy, cir::GlobalOp> vftablesMap; + + MicrosoftMangleContext &getMangleContext() { + return *cast<MicrosoftMangleContext>(mangleContext.get()); + } + + CharUnits getVirtualFunctionPrologueThisAdjustment(GlobalDecl gd); + + mlir::Value getVBaseOffsetFromVBPtr(CIRGenFunction &cgf, mlir::Location loc, + Address thisAddr, int64_t vbPtrOffset, + unsigned vbTableIndex, + mlir::Value *vbPtrOut = nullptr); + public: CIRGenMicrosoftCXXABI(CIRGenModule &cgm) : CIRGenCXXABI(cgm) {} + bool hasThisReturn(clang::GlobalDecl gd) const override { + return isa<CXXConstructorDecl>(gd.getDecl()); + } + + bool hasMostDerivedReturn(clang::GlobalDecl gd) const override { + return false; + } + + llvm::StringRef getPureVirtualCallName() override { return "_purecall"; } + llvm::StringRef getDeletedVirtualCallName() override { return "_purecall"; } + + bool canSpeculativelyEmitVTable(const CXXRecordDecl *rd) const override { + return false; + } + + bool doStructorsInitializeVPtrs(const CXXRecordDecl *vtableClass) override { + return !vtableClass->hasAttr<MSNoVTableAttr>(); + } + + bool exportThunk() override { return false; } + + bool useThunkForDtorVariant(const CXXDestructorDecl *dtor, + CXXDtorType dt) const override { + return dt != Dtor_Base; + } + + bool isZeroInitializable(const MemberPointerType *mpt) override { + if (mpt->isMemberFunctionPointer()) + return true; + + const CXXRecordDecl *rd = mpt->getMostRecentCXXRecordDecl(); + MSInheritanceModel inheritance = rd->getMSInheritanceModel(); + return (!inheritanceModelHasVBTableOffsetField(inheritance) && + rd->nullFieldOffsetIsZero()); + } + + bool requiresArrayCookie(const CXXNewExpr *e) override { + return e->getAllocatedType().isDestructedType(); + } + + CharUnits getArrayCookieSizeImpl(QualType elementType) override { + ASTContext &ctx = cgm.getASTContext(); + return std::max(ctx.getTypeSizeInChars(ctx.getSizeType()), + ctx.getTypeAlignInChars(elementType)); + } + + Address initializeArrayCookie(CIRGenFunction &cgf, Address newPtr, + mlir::Value numElements, const CXXNewExpr *e, + QualType elementType) override; + + cir::GlobalLinkageKind + getCXXDestructorLinkage(GVALinkage linkage, const CXXDestructorDecl *dtor, + CXXDtorType dt) const override { + if (linkage == GVA_Internal) + return cir::GlobalLinkageKind::InternalLinkage; + + switch (dt) { + case Dtor_Base: + return cgm.getCIRLinkageForDeclarator(dtor, linkage); + case Dtor_Complete: + if (dtor->hasAttr<DLLExportAttr>()) + return cir::GlobalLinkageKind::WeakODRLinkage; + return linkage == GVA_DiscardableODR + ? cir::GlobalLinkageKind::LinkOnceODRLinkage + : cir::GlobalLinkageKind::WeakODRLinkage; + case Dtor_Deleting: + case Dtor_VectorDeleting: + return cir::GlobalLinkageKind::LinkOnceODRLinkage; + case Dtor_Comdat: + llvm_unreachable("emitting dtor comdat as function?"); + case Dtor_Unified: + llvm_unreachable("unexpected unified dtor type"); + } + llvm_unreachable("invalid dtor type"); + } + + void setThunkLinkage(cir::FuncOp thunk, bool forVTable, GlobalDecl gd, + bool returnAdjustment) override { + GVALinkage linkage = cgm.getASTContext().GetGVALinkageForFunction( + cast<FunctionDecl>(gd.getDecl())); + + if (linkage == GVA_Internal) + thunk.setLinkage(cir::GlobalLinkageKind::InternalLinkage); + else if (returnAdjustment) + thunk.setLinkage(cir::GlobalLinkageKind::WeakODRLinkage); + else + thunk.setLinkage(cir::GlobalLinkageKind::LinkOnceODRLinkage); + } + + CatchTypeInfo getCatchAllTypeInfo() override { + if (cgm.getASTContext().getLangOpts().EHAsynch) + return CatchTypeInfo{nullptr, 0}; + else + return CatchTypeInfo{nullptr, 0x40}; + } + + void adjustCallArgsForDestructorThunk(CIRGenFunction &cgf, GlobalDecl gd, + CallArgList &callArgs) override { + assert((gd.getDtorType() == Dtor_VectorDeleting || + gd.getDtorType() == Dtor_Deleting) && + "Only vector deleting destructor thunks are available in this ABI"); + callArgs.add(RValue::get(getStructorImplicitParamValue(cgf)), + cgm.getASTContext().IntTy); + } + AddedStructorArgCounts buildStructorSignature(GlobalDecl gd, - SmallVectorImpl<CanQualType> &argTys) override { - cgm.errorNYI(gd.getDecl()->getSourceRange(), - "buildStructorSignature: MSVC ABI"); - return AddedStructorArgCounts{}; - } + llvm::SmallVectorImpl<CanQualType> &argTys) override; void addImplicitStructorParams(CIRGenFunction &cgf, QualType &resTy, - FunctionArgList ¶ms) override { - cgf.cgm.errorNYI(cgf.curGD.getDecl()->getSourceRange(), - "addImplicitStructorParams: MSVC ABI"); - } + FunctionArgList ¶ms) override; void emitInstanceFunctionProlog(SourceLocation loc, - CIRGenFunction &cgf) override { - cgf.cgm.errorNYI(loc, "emitInstanceFunctionProlog: MSVC ABI"); - } + CIRGenFunction &cgf) override; AddedStructorArgs getImplicitConstructorArgs(CIRGenFunction &cgf, const CXXConstructorDecl *d, CXXCtorType type, bool forVirtualBase, - bool delegating) override { - cgf.cgm.errorNYI(d->getSourceRange(), - "getImplicitConstructorArgs: MSVC ABI"); - return AddedStructorArgs{}; - } + bool delegating) override; mlir::Value getCXXDestructorImplicitParam(CIRGenFunction &cgf, const CXXDestructorDecl *dd, CXXDtorType type, bool forVirtualBase, bool delegating) override { - cgf.cgm.errorNYI(dd->getSourceRange(), - "getCXXDestructorImplicitParam: MSVC ABI"); return nullptr; } - void emitCXXConstructors(const CXXConstructorDecl *d) override { - cgm.errorNYI(d->getSourceRange(), "emitCXXConstructors: MSVC ABI"); - } - - void emitCXXDestructors(const CXXDestructorDecl *d) override { - cgm.errorNYI(d->getSourceRange(), "emitCXXDestructors: MSVC ABI"); - } - - void emitCXXStructor(GlobalDecl gd) override { - cgm.errorNYI(gd.getDecl()->getSourceRange(), "emitCXXStructor: MSVC ABI"); - } + void emitCXXConstructors(const CXXConstructorDecl *d) override; + void emitCXXDestructors(const CXXDestructorDecl *d) override; + void emitCXXStructor(GlobalDecl gd) override; void emitDestructorCall(CIRGenFunction &cgf, const CXXDestructorDecl *dd, CXXDtorType type, bool forVirtualBase, bool delegating, Address thisAddr, - QualType thisTy) override { - cgf.cgm.errorNYI(dd->getSourceRange(), "emitDestructorCall: MSVC ABI"); - } + QualType thisTy) override; mlir::Value emitVirtualDestructorCall(CIRGenFunction &cgf, const CXXDestructorDecl *dtor, CXXDtorType dtorType, Address thisAddr, - DeleteOrMemberCallExpr e) override { - cgf.cgm.errorNYI(dtor->getSourceRange(), - "emitVirtualDestructorCall: MSVC ABI"); - return nullptr; - } + DeleteOrMemberCallExpr e) override; void emitVirtualObjectDelete(CIRGenFunction &cgf, const CXXDeleteExpr *de, Address ptr, QualType elementType, - const CXXDestructorDecl *dtor) override { - cgf.cgm.errorNYI(de->getSourceRange(), "emitVirtualObjectDelete: MSVC ABI"); - } + const CXXDestructorDecl *dtor) override; size_t getSrcArgforCopyCtor(const CXXConstructorDecl *cd, FunctionArgList &args) const override { - cgm.errorNYI(cd->getSourceRange(), "getSrcArgforCopyCtor: MSVC ABI"); assert(args.size() >= 2 && "expected the arglist to have at least two args!"); // The 'most_derived' parameter goes second if the ctor is variadic and @@ -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::V... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/233291 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
