10b57cec5SDimitry Andric //===------- MicrosoftCXXABI.cpp - AST support for the Microsoft C++ ABI --===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This provides C++ AST support targeting the Microsoft Visual C++ 100b57cec5SDimitry Andric // ABI. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #include "CXXABI.h" 150b57cec5SDimitry Andric #include "clang/AST/ASTContext.h" 160b57cec5SDimitry Andric #include "clang/AST/Attr.h" 17480093f4SDimitry Andric #include "clang/AST/CXXInheritance.h" 180b57cec5SDimitry Andric #include "clang/AST/DeclCXX.h" 19d409305fSDimitry Andric #include "clang/AST/Mangle.h" 200b57cec5SDimitry Andric #include "clang/AST/MangleNumberingContext.h" 210b57cec5SDimitry Andric #include "clang/AST/RecordLayout.h" 220b57cec5SDimitry Andric #include "clang/AST/Type.h" 230b57cec5SDimitry Andric #include "clang/Basic/TargetInfo.h" 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric using namespace clang; 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric namespace { 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric /// Numbers things which need to correspond across multiple TUs. 300b57cec5SDimitry Andric /// Typically these are things like static locals, lambdas, or blocks. 310b57cec5SDimitry Andric class MicrosoftNumberingContext : public MangleNumberingContext { 320b57cec5SDimitry Andric llvm::DenseMap<const Type *, unsigned> ManglingNumbers; 33*5f757f3fSDimitry Andric unsigned LambdaManglingNumber = 0; 34*5f757f3fSDimitry Andric unsigned StaticLocalNumber = 0; 35*5f757f3fSDimitry Andric unsigned StaticThreadlocalNumber = 0; 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric public: 38*5f757f3fSDimitry Andric MicrosoftNumberingContext() = default; 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric unsigned getManglingNumber(const CXXMethodDecl *CallOperator) override { 410b57cec5SDimitry Andric return ++LambdaManglingNumber; 420b57cec5SDimitry Andric } 430b57cec5SDimitry Andric 440b57cec5SDimitry Andric unsigned getManglingNumber(const BlockDecl *BD) override { 450b57cec5SDimitry Andric const Type *Ty = nullptr; 460b57cec5SDimitry Andric return ++ManglingNumbers[Ty]; 470b57cec5SDimitry Andric } 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric unsigned getStaticLocalNumber(const VarDecl *VD) override { 500b57cec5SDimitry Andric if (VD->getTLSKind()) 510b57cec5SDimitry Andric return ++StaticThreadlocalNumber; 520b57cec5SDimitry Andric return ++StaticLocalNumber; 530b57cec5SDimitry Andric } 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric unsigned getManglingNumber(const VarDecl *VD, 560b57cec5SDimitry Andric unsigned MSLocalManglingNumber) override { 570b57cec5SDimitry Andric return MSLocalManglingNumber; 580b57cec5SDimitry Andric } 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric unsigned getManglingNumber(const TagDecl *TD, 610b57cec5SDimitry Andric unsigned MSLocalManglingNumber) override { 620b57cec5SDimitry Andric return MSLocalManglingNumber; 630b57cec5SDimitry Andric } 640b57cec5SDimitry Andric }; 650b57cec5SDimitry Andric 66d409305fSDimitry Andric class MSHIPNumberingContext : public MicrosoftNumberingContext { 67d409305fSDimitry Andric std::unique_ptr<MangleNumberingContext> DeviceCtx; 68d409305fSDimitry Andric 69d409305fSDimitry Andric public: 7081ad6265SDimitry Andric using MicrosoftNumberingContext::getManglingNumber; 71d409305fSDimitry Andric MSHIPNumberingContext(MangleContext *DeviceMangler) { 72d409305fSDimitry Andric DeviceCtx = createItaniumNumberingContext(DeviceMangler); 73d409305fSDimitry Andric } 74d409305fSDimitry Andric 75d409305fSDimitry Andric unsigned getDeviceManglingNumber(const CXXMethodDecl *CallOperator) override { 76d409305fSDimitry Andric return DeviceCtx->getManglingNumber(CallOperator); 77d409305fSDimitry Andric } 7881ad6265SDimitry Andric 7981ad6265SDimitry Andric unsigned getManglingNumber(const TagDecl *TD, 8081ad6265SDimitry Andric unsigned MSLocalManglingNumber) override { 8181ad6265SDimitry Andric unsigned DeviceN = DeviceCtx->getManglingNumber(TD, MSLocalManglingNumber); 8281ad6265SDimitry Andric unsigned HostN = 8381ad6265SDimitry Andric MicrosoftNumberingContext::getManglingNumber(TD, MSLocalManglingNumber); 8481ad6265SDimitry Andric if (DeviceN > 0xFFFF || HostN > 0xFFFF) { 8581ad6265SDimitry Andric DiagnosticsEngine &Diags = TD->getASTContext().getDiagnostics(); 8681ad6265SDimitry Andric unsigned DiagID = Diags.getCustomDiagID( 8781ad6265SDimitry Andric DiagnosticsEngine::Error, "Mangling number exceeds limit (65535)"); 8881ad6265SDimitry Andric Diags.Report(TD->getLocation(), DiagID); 8981ad6265SDimitry Andric } 9081ad6265SDimitry Andric return (DeviceN << 16) | HostN; 9181ad6265SDimitry Andric } 92d409305fSDimitry Andric }; 93d409305fSDimitry Andric 94349cc55cSDimitry Andric class MSSYCLNumberingContext : public MicrosoftNumberingContext { 95349cc55cSDimitry Andric std::unique_ptr<MangleNumberingContext> DeviceCtx; 96349cc55cSDimitry Andric 97349cc55cSDimitry Andric public: 98349cc55cSDimitry Andric MSSYCLNumberingContext(MangleContext *DeviceMangler) { 99349cc55cSDimitry Andric DeviceCtx = createItaniumNumberingContext(DeviceMangler); 100349cc55cSDimitry Andric } 101349cc55cSDimitry Andric 102349cc55cSDimitry Andric unsigned getDeviceManglingNumber(const CXXMethodDecl *CallOperator) override { 103349cc55cSDimitry Andric return DeviceCtx->getManglingNumber(CallOperator); 104349cc55cSDimitry Andric } 105349cc55cSDimitry Andric }; 106349cc55cSDimitry Andric 1070b57cec5SDimitry Andric class MicrosoftCXXABI : public CXXABI { 1080b57cec5SDimitry Andric ASTContext &Context; 1090b57cec5SDimitry Andric llvm::SmallDenseMap<CXXRecordDecl *, CXXConstructorDecl *> RecordToCopyCtor; 1100b57cec5SDimitry Andric 1110b57cec5SDimitry Andric llvm::SmallDenseMap<TagDecl *, DeclaratorDecl *> 1120b57cec5SDimitry Andric UnnamedTagDeclToDeclaratorDecl; 1130b57cec5SDimitry Andric llvm::SmallDenseMap<TagDecl *, TypedefNameDecl *> 1140b57cec5SDimitry Andric UnnamedTagDeclToTypedefNameDecl; 1150b57cec5SDimitry Andric 116d409305fSDimitry Andric // MangleContext for device numbering context, which is based on Itanium C++ 117d409305fSDimitry Andric // ABI. 118d409305fSDimitry Andric std::unique_ptr<MangleContext> DeviceMangler; 119d409305fSDimitry Andric 1200b57cec5SDimitry Andric public: 121d409305fSDimitry Andric MicrosoftCXXABI(ASTContext &Ctx) : Context(Ctx) { 122d409305fSDimitry Andric if (Context.getLangOpts().CUDA && Context.getAuxTargetInfo()) { 123d409305fSDimitry Andric assert(Context.getTargetInfo().getCXXABI().isMicrosoft() && 124d409305fSDimitry Andric Context.getAuxTargetInfo()->getCXXABI().isItaniumFamily() && 125d409305fSDimitry Andric "Unexpected combination of C++ ABIs."); 126d409305fSDimitry Andric DeviceMangler.reset( 127d409305fSDimitry Andric Context.createMangleContext(Context.getAuxTargetInfo())); 128d409305fSDimitry Andric } 129349cc55cSDimitry Andric else if (Context.getLangOpts().isSYCL()) { 130349cc55cSDimitry Andric DeviceMangler.reset( 131349cc55cSDimitry Andric ItaniumMangleContext::create(Context, Context.getDiagnostics())); 132349cc55cSDimitry Andric } 133d409305fSDimitry Andric } 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric MemberPointerInfo 1360b57cec5SDimitry Andric getMemberPointerInfo(const MemberPointerType *MPT) const override; 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric CallingConv getDefaultMethodCallConv(bool isVariadic) const override { 1390b57cec5SDimitry Andric if (!isVariadic && 1400b57cec5SDimitry Andric Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86) 1410b57cec5SDimitry Andric return CC_X86ThisCall; 1420b57cec5SDimitry Andric return Context.getTargetInfo().getDefaultCallingConv(); 1430b57cec5SDimitry Andric } 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric bool isNearlyEmpty(const CXXRecordDecl *RD) const override { 1460b57cec5SDimitry Andric llvm_unreachable("unapplicable to the MS ABI"); 1470b57cec5SDimitry Andric } 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric const CXXConstructorDecl * 1500b57cec5SDimitry Andric getCopyConstructorForExceptionObject(CXXRecordDecl *RD) override { 1510b57cec5SDimitry Andric return RecordToCopyCtor[RD]; 1520b57cec5SDimitry Andric } 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric void 1550b57cec5SDimitry Andric addCopyConstructorForExceptionObject(CXXRecordDecl *RD, 1560b57cec5SDimitry Andric CXXConstructorDecl *CD) override { 1570b57cec5SDimitry Andric assert(CD != nullptr); 1580b57cec5SDimitry Andric assert(RecordToCopyCtor[RD] == nullptr || RecordToCopyCtor[RD] == CD); 1590b57cec5SDimitry Andric RecordToCopyCtor[RD] = CD; 1600b57cec5SDimitry Andric } 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric void addTypedefNameForUnnamedTagDecl(TagDecl *TD, 1630b57cec5SDimitry Andric TypedefNameDecl *DD) override { 1640b57cec5SDimitry Andric TD = TD->getCanonicalDecl(); 1650b57cec5SDimitry Andric DD = DD->getCanonicalDecl(); 1660b57cec5SDimitry Andric TypedefNameDecl *&I = UnnamedTagDeclToTypedefNameDecl[TD]; 1670b57cec5SDimitry Andric if (!I) 1680b57cec5SDimitry Andric I = DD; 1690b57cec5SDimitry Andric } 1700b57cec5SDimitry Andric 1710b57cec5SDimitry Andric TypedefNameDecl *getTypedefNameForUnnamedTagDecl(const TagDecl *TD) override { 1720b57cec5SDimitry Andric return UnnamedTagDeclToTypedefNameDecl.lookup( 1730b57cec5SDimitry Andric const_cast<TagDecl *>(TD->getCanonicalDecl())); 1740b57cec5SDimitry Andric } 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric void addDeclaratorForUnnamedTagDecl(TagDecl *TD, 1770b57cec5SDimitry Andric DeclaratorDecl *DD) override { 1780b57cec5SDimitry Andric TD = TD->getCanonicalDecl(); 1790b57cec5SDimitry Andric DD = cast<DeclaratorDecl>(DD->getCanonicalDecl()); 1800b57cec5SDimitry Andric DeclaratorDecl *&I = UnnamedTagDeclToDeclaratorDecl[TD]; 1810b57cec5SDimitry Andric if (!I) 1820b57cec5SDimitry Andric I = DD; 1830b57cec5SDimitry Andric } 1840b57cec5SDimitry Andric 1850b57cec5SDimitry Andric DeclaratorDecl *getDeclaratorForUnnamedTagDecl(const TagDecl *TD) override { 1860b57cec5SDimitry Andric return UnnamedTagDeclToDeclaratorDecl.lookup( 1870b57cec5SDimitry Andric const_cast<TagDecl *>(TD->getCanonicalDecl())); 1880b57cec5SDimitry Andric } 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric std::unique_ptr<MangleNumberingContext> 1910b57cec5SDimitry Andric createMangleNumberingContext() const override { 192d409305fSDimitry Andric if (Context.getLangOpts().CUDA && Context.getAuxTargetInfo()) { 193d409305fSDimitry Andric assert(DeviceMangler && "Missing device mangler"); 194d409305fSDimitry Andric return std::make_unique<MSHIPNumberingContext>(DeviceMangler.get()); 195349cc55cSDimitry Andric } else if (Context.getLangOpts().isSYCL()) { 196349cc55cSDimitry Andric assert(DeviceMangler && "Missing device mangler"); 197349cc55cSDimitry Andric return std::make_unique<MSSYCLNumberingContext>(DeviceMangler.get()); 198d409305fSDimitry Andric } 199349cc55cSDimitry Andric 200a7dea167SDimitry Andric return std::make_unique<MicrosoftNumberingContext>(); 2010b57cec5SDimitry Andric } 2020b57cec5SDimitry Andric }; 2030b57cec5SDimitry Andric } 2040b57cec5SDimitry Andric 2050b57cec5SDimitry Andric // getNumBases() seems to only give us the number of direct bases, and not the 2060b57cec5SDimitry Andric // total. This function tells us if we inherit from anybody that uses MI, or if 2070b57cec5SDimitry Andric // we have a non-primary base class, which uses the multiple inheritance model. 2080b57cec5SDimitry Andric static bool usesMultipleInheritanceModel(const CXXRecordDecl *RD) { 2090b57cec5SDimitry Andric while (RD->getNumBases() > 0) { 2100b57cec5SDimitry Andric if (RD->getNumBases() > 1) 2110b57cec5SDimitry Andric return true; 2120b57cec5SDimitry Andric assert(RD->getNumBases() == 1); 2130b57cec5SDimitry Andric const CXXRecordDecl *Base = 2140b57cec5SDimitry Andric RD->bases_begin()->getType()->getAsCXXRecordDecl(); 2150b57cec5SDimitry Andric if (RD->isPolymorphic() && !Base->isPolymorphic()) 2160b57cec5SDimitry Andric return true; 2170b57cec5SDimitry Andric RD = Base; 2180b57cec5SDimitry Andric } 2190b57cec5SDimitry Andric return false; 2200b57cec5SDimitry Andric } 2210b57cec5SDimitry Andric 222480093f4SDimitry Andric MSInheritanceModel CXXRecordDecl::calculateInheritanceModel() const { 2230b57cec5SDimitry Andric if (!hasDefinition() || isParsingBaseSpecifiers()) 224480093f4SDimitry Andric return MSInheritanceModel::Unspecified; 2250b57cec5SDimitry Andric if (getNumVBases() > 0) 226480093f4SDimitry Andric return MSInheritanceModel::Virtual; 2270b57cec5SDimitry Andric if (usesMultipleInheritanceModel(this)) 228480093f4SDimitry Andric return MSInheritanceModel::Multiple; 229480093f4SDimitry Andric return MSInheritanceModel::Single; 2300b57cec5SDimitry Andric } 2310b57cec5SDimitry Andric 232480093f4SDimitry Andric MSInheritanceModel CXXRecordDecl::getMSInheritanceModel() const { 2330b57cec5SDimitry Andric MSInheritanceAttr *IA = getAttr<MSInheritanceAttr>(); 2340b57cec5SDimitry Andric assert(IA && "Expected MSInheritanceAttr on the CXXRecordDecl!"); 235480093f4SDimitry Andric return IA->getInheritanceModel(); 2360b57cec5SDimitry Andric } 2370b57cec5SDimitry Andric 238480093f4SDimitry Andric bool CXXRecordDecl::nullFieldOffsetIsZero() const { 239480093f4SDimitry Andric return !inheritanceModelHasOnlyOneField(/*IsMemberFunction=*/false, 240480093f4SDimitry Andric getMSInheritanceModel()) || 241480093f4SDimitry Andric (hasDefinition() && isPolymorphic()); 242480093f4SDimitry Andric } 243480093f4SDimitry Andric 244480093f4SDimitry Andric MSVtorDispMode CXXRecordDecl::getMSVtorDispMode() const { 2450b57cec5SDimitry Andric if (MSVtorDispAttr *VDA = getAttr<MSVtorDispAttr>()) 2460b57cec5SDimitry Andric return VDA->getVtorDispMode(); 247480093f4SDimitry Andric return getASTContext().getLangOpts().getVtorDispMode(); 2480b57cec5SDimitry Andric } 2490b57cec5SDimitry Andric 2500b57cec5SDimitry Andric // Returns the number of pointer and integer slots used to represent a member 2510b57cec5SDimitry Andric // pointer in the MS C++ ABI. 2520b57cec5SDimitry Andric // 2530b57cec5SDimitry Andric // Member function pointers have the following general form; however, fields 2540b57cec5SDimitry Andric // are dropped as permitted (under the MSVC interpretation) by the inheritance 2550b57cec5SDimitry Andric // model of the actual class. 2560b57cec5SDimitry Andric // 2570b57cec5SDimitry Andric // struct { 2580b57cec5SDimitry Andric // // A pointer to the member function to call. If the member function is 2590b57cec5SDimitry Andric // // virtual, this will be a thunk that forwards to the appropriate vftable 2600b57cec5SDimitry Andric // // slot. 2610b57cec5SDimitry Andric // void *FunctionPointerOrVirtualThunk; 2620b57cec5SDimitry Andric // 2630b57cec5SDimitry Andric // // An offset to add to the address of the vbtable pointer after 2640b57cec5SDimitry Andric // // (possibly) selecting the virtual base but before resolving and calling 2650b57cec5SDimitry Andric // // the function. 2660b57cec5SDimitry Andric // // Only needed if the class has any virtual bases or bases at a non-zero 2670b57cec5SDimitry Andric // // offset. 2680b57cec5SDimitry Andric // int NonVirtualBaseAdjustment; 2690b57cec5SDimitry Andric // 2700b57cec5SDimitry Andric // // The offset of the vb-table pointer within the object. Only needed for 2710b57cec5SDimitry Andric // // incomplete types. 2720b57cec5SDimitry Andric // int VBPtrOffset; 2730b57cec5SDimitry Andric // 2740b57cec5SDimitry Andric // // An offset within the vb-table that selects the virtual base containing 2750b57cec5SDimitry Andric // // the member. Loading from this offset produces a new offset that is 2760b57cec5SDimitry Andric // // added to the address of the vb-table pointer to produce the base. 2770b57cec5SDimitry Andric // int VirtualBaseAdjustmentOffset; 2780b57cec5SDimitry Andric // }; 2790b57cec5SDimitry Andric static std::pair<unsigned, unsigned> 2800b57cec5SDimitry Andric getMSMemberPointerSlots(const MemberPointerType *MPT) { 2810b57cec5SDimitry Andric const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); 282480093f4SDimitry Andric MSInheritanceModel Inheritance = RD->getMSInheritanceModel(); 2830b57cec5SDimitry Andric unsigned Ptrs = 0; 2840b57cec5SDimitry Andric unsigned Ints = 0; 2850b57cec5SDimitry Andric if (MPT->isMemberFunctionPointer()) 2860b57cec5SDimitry Andric Ptrs = 1; 2870b57cec5SDimitry Andric else 2880b57cec5SDimitry Andric Ints = 1; 289480093f4SDimitry Andric if (inheritanceModelHasNVOffsetField(MPT->isMemberFunctionPointer(), 2900b57cec5SDimitry Andric Inheritance)) 2910b57cec5SDimitry Andric Ints++; 292480093f4SDimitry Andric if (inheritanceModelHasVBPtrOffsetField(Inheritance)) 2930b57cec5SDimitry Andric Ints++; 294480093f4SDimitry Andric if (inheritanceModelHasVBTableOffsetField(Inheritance)) 2950b57cec5SDimitry Andric Ints++; 2960b57cec5SDimitry Andric return std::make_pair(Ptrs, Ints); 2970b57cec5SDimitry Andric } 2980b57cec5SDimitry Andric 2990b57cec5SDimitry Andric CXXABI::MemberPointerInfo MicrosoftCXXABI::getMemberPointerInfo( 3000b57cec5SDimitry Andric const MemberPointerType *MPT) const { 3010b57cec5SDimitry Andric // The nominal struct is laid out with pointers followed by ints and aligned 3020b57cec5SDimitry Andric // to a pointer width if any are present and an int width otherwise. 3030b57cec5SDimitry Andric const TargetInfo &Target = Context.getTargetInfo(); 304bdd1243dSDimitry Andric unsigned PtrSize = Target.getPointerWidth(LangAS::Default); 3050b57cec5SDimitry Andric unsigned IntSize = Target.getIntWidth(); 3060b57cec5SDimitry Andric 3070b57cec5SDimitry Andric unsigned Ptrs, Ints; 3080b57cec5SDimitry Andric std::tie(Ptrs, Ints) = getMSMemberPointerSlots(MPT); 3090b57cec5SDimitry Andric MemberPointerInfo MPI; 3100b57cec5SDimitry Andric MPI.HasPadding = false; 3110b57cec5SDimitry Andric MPI.Width = Ptrs * PtrSize + Ints * IntSize; 3120b57cec5SDimitry Andric 3130b57cec5SDimitry Andric // When MSVC does x86_32 record layout, it aligns aggregate member pointers to 3140b57cec5SDimitry Andric // 8 bytes. However, __alignof usually returns 4 for data memptrs and 8 for 3150b57cec5SDimitry Andric // function memptrs. 3160b57cec5SDimitry Andric if (Ptrs + Ints > 1 && Target.getTriple().isArch32Bit()) 3170b57cec5SDimitry Andric MPI.Align = 64; 3180b57cec5SDimitry Andric else if (Ptrs) 319bdd1243dSDimitry Andric MPI.Align = Target.getPointerAlign(LangAS::Default); 3200b57cec5SDimitry Andric else 3210b57cec5SDimitry Andric MPI.Align = Target.getIntAlign(); 3220b57cec5SDimitry Andric 3230b57cec5SDimitry Andric if (Target.getTriple().isArch64Bit()) { 3240b57cec5SDimitry Andric MPI.Width = llvm::alignTo(MPI.Width, MPI.Align); 3250b57cec5SDimitry Andric MPI.HasPadding = MPI.Width != (Ptrs * PtrSize + Ints * IntSize); 3260b57cec5SDimitry Andric } 3270b57cec5SDimitry Andric return MPI; 3280b57cec5SDimitry Andric } 3290b57cec5SDimitry Andric 3300b57cec5SDimitry Andric CXXABI *clang::CreateMicrosoftCXXABI(ASTContext &Ctx) { 3310b57cec5SDimitry Andric return new MicrosoftCXXABI(Ctx); 3320b57cec5SDimitry Andric } 333