MicrosoftCXXABI.cpp revision 360784
1//===------- MicrosoftCXXABI.cpp - AST support for the Microsoft C++ ABI --===// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8// 9// This provides C++ AST support targeting the Microsoft Visual C++ 10// ABI. 11// 12//===----------------------------------------------------------------------===// 13 14#include "CXXABI.h" 15#include "clang/AST/ASTContext.h" 16#include "clang/AST/Attr.h" 17#include "clang/AST/CXXInheritance.h" 18#include "clang/AST/DeclCXX.h" 19#include "clang/AST/MangleNumberingContext.h" 20#include "clang/AST/RecordLayout.h" 21#include "clang/AST/Type.h" 22#include "clang/Basic/TargetInfo.h" 23 24using namespace clang; 25 26namespace { 27 28/// Numbers things which need to correspond across multiple TUs. 29/// Typically these are things like static locals, lambdas, or blocks. 30class MicrosoftNumberingContext : public MangleNumberingContext { 31 llvm::DenseMap<const Type *, unsigned> ManglingNumbers; 32 unsigned LambdaManglingNumber; 33 unsigned StaticLocalNumber; 34 unsigned StaticThreadlocalNumber; 35 36public: 37 MicrosoftNumberingContext() 38 : MangleNumberingContext(), LambdaManglingNumber(0), 39 StaticLocalNumber(0), StaticThreadlocalNumber(0) {} 40 41 unsigned getManglingNumber(const CXXMethodDecl *CallOperator) override { 42 return ++LambdaManglingNumber; 43 } 44 45 unsigned getManglingNumber(const BlockDecl *BD) override { 46 const Type *Ty = nullptr; 47 return ++ManglingNumbers[Ty]; 48 } 49 50 unsigned getStaticLocalNumber(const VarDecl *VD) override { 51 if (VD->getTLSKind()) 52 return ++StaticThreadlocalNumber; 53 return ++StaticLocalNumber; 54 } 55 56 unsigned getManglingNumber(const VarDecl *VD, 57 unsigned MSLocalManglingNumber) override { 58 return MSLocalManglingNumber; 59 } 60 61 unsigned getManglingNumber(const TagDecl *TD, 62 unsigned MSLocalManglingNumber) override { 63 return MSLocalManglingNumber; 64 } 65}; 66 67class MicrosoftCXXABI : public CXXABI { 68 ASTContext &Context; 69 llvm::SmallDenseMap<CXXRecordDecl *, CXXConstructorDecl *> RecordToCopyCtor; 70 71 llvm::SmallDenseMap<TagDecl *, DeclaratorDecl *> 72 UnnamedTagDeclToDeclaratorDecl; 73 llvm::SmallDenseMap<TagDecl *, TypedefNameDecl *> 74 UnnamedTagDeclToTypedefNameDecl; 75 76public: 77 MicrosoftCXXABI(ASTContext &Ctx) : Context(Ctx) { } 78 79 MemberPointerInfo 80 getMemberPointerInfo(const MemberPointerType *MPT) const override; 81 82 CallingConv getDefaultMethodCallConv(bool isVariadic) const override { 83 if (!isVariadic && 84 Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86) 85 return CC_X86ThisCall; 86 return Context.getTargetInfo().getDefaultCallingConv(); 87 } 88 89 bool isNearlyEmpty(const CXXRecordDecl *RD) const override { 90 llvm_unreachable("unapplicable to the MS ABI"); 91 } 92 93 const CXXConstructorDecl * 94 getCopyConstructorForExceptionObject(CXXRecordDecl *RD) override { 95 return RecordToCopyCtor[RD]; 96 } 97 98 void 99 addCopyConstructorForExceptionObject(CXXRecordDecl *RD, 100 CXXConstructorDecl *CD) override { 101 assert(CD != nullptr); 102 assert(RecordToCopyCtor[RD] == nullptr || RecordToCopyCtor[RD] == CD); 103 RecordToCopyCtor[RD] = CD; 104 } 105 106 void addTypedefNameForUnnamedTagDecl(TagDecl *TD, 107 TypedefNameDecl *DD) override { 108 TD = TD->getCanonicalDecl(); 109 DD = DD->getCanonicalDecl(); 110 TypedefNameDecl *&I = UnnamedTagDeclToTypedefNameDecl[TD]; 111 if (!I) 112 I = DD; 113 } 114 115 TypedefNameDecl *getTypedefNameForUnnamedTagDecl(const TagDecl *TD) override { 116 return UnnamedTagDeclToTypedefNameDecl.lookup( 117 const_cast<TagDecl *>(TD->getCanonicalDecl())); 118 } 119 120 void addDeclaratorForUnnamedTagDecl(TagDecl *TD, 121 DeclaratorDecl *DD) override { 122 TD = TD->getCanonicalDecl(); 123 DD = cast<DeclaratorDecl>(DD->getCanonicalDecl()); 124 DeclaratorDecl *&I = UnnamedTagDeclToDeclaratorDecl[TD]; 125 if (!I) 126 I = DD; 127 } 128 129 DeclaratorDecl *getDeclaratorForUnnamedTagDecl(const TagDecl *TD) override { 130 return UnnamedTagDeclToDeclaratorDecl.lookup( 131 const_cast<TagDecl *>(TD->getCanonicalDecl())); 132 } 133 134 std::unique_ptr<MangleNumberingContext> 135 createMangleNumberingContext() const override { 136 return std::make_unique<MicrosoftNumberingContext>(); 137 } 138}; 139} 140 141// getNumBases() seems to only give us the number of direct bases, and not the 142// total. This function tells us if we inherit from anybody that uses MI, or if 143// we have a non-primary base class, which uses the multiple inheritance model. 144static bool usesMultipleInheritanceModel(const CXXRecordDecl *RD) { 145 while (RD->getNumBases() > 0) { 146 if (RD->getNumBases() > 1) 147 return true; 148 assert(RD->getNumBases() == 1); 149 const CXXRecordDecl *Base = 150 RD->bases_begin()->getType()->getAsCXXRecordDecl(); 151 if (RD->isPolymorphic() && !Base->isPolymorphic()) 152 return true; 153 RD = Base; 154 } 155 return false; 156} 157 158MSInheritanceModel CXXRecordDecl::calculateInheritanceModel() const { 159 if (!hasDefinition() || isParsingBaseSpecifiers()) 160 return MSInheritanceModel::Unspecified; 161 if (getNumVBases() > 0) 162 return MSInheritanceModel::Virtual; 163 if (usesMultipleInheritanceModel(this)) 164 return MSInheritanceModel::Multiple; 165 return MSInheritanceModel::Single; 166} 167 168MSInheritanceModel CXXRecordDecl::getMSInheritanceModel() const { 169 MSInheritanceAttr *IA = getAttr<MSInheritanceAttr>(); 170 assert(IA && "Expected MSInheritanceAttr on the CXXRecordDecl!"); 171 return IA->getInheritanceModel(); 172} 173 174bool CXXRecordDecl::nullFieldOffsetIsZero() const { 175 return !inheritanceModelHasOnlyOneField(/*IsMemberFunction=*/false, 176 getMSInheritanceModel()) || 177 (hasDefinition() && isPolymorphic()); 178} 179 180MSVtorDispMode CXXRecordDecl::getMSVtorDispMode() const { 181 if (MSVtorDispAttr *VDA = getAttr<MSVtorDispAttr>()) 182 return VDA->getVtorDispMode(); 183 return getASTContext().getLangOpts().getVtorDispMode(); 184} 185 186// Returns the number of pointer and integer slots used to represent a member 187// pointer in the MS C++ ABI. 188// 189// Member function pointers have the following general form; however, fields 190// are dropped as permitted (under the MSVC interpretation) by the inheritance 191// model of the actual class. 192// 193// struct { 194// // A pointer to the member function to call. If the member function is 195// // virtual, this will be a thunk that forwards to the appropriate vftable 196// // slot. 197// void *FunctionPointerOrVirtualThunk; 198// 199// // An offset to add to the address of the vbtable pointer after 200// // (possibly) selecting the virtual base but before resolving and calling 201// // the function. 202// // Only needed if the class has any virtual bases or bases at a non-zero 203// // offset. 204// int NonVirtualBaseAdjustment; 205// 206// // The offset of the vb-table pointer within the object. Only needed for 207// // incomplete types. 208// int VBPtrOffset; 209// 210// // An offset within the vb-table that selects the virtual base containing 211// // the member. Loading from this offset produces a new offset that is 212// // added to the address of the vb-table pointer to produce the base. 213// int VirtualBaseAdjustmentOffset; 214// }; 215static std::pair<unsigned, unsigned> 216getMSMemberPointerSlots(const MemberPointerType *MPT) { 217 const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); 218 MSInheritanceModel Inheritance = RD->getMSInheritanceModel(); 219 unsigned Ptrs = 0; 220 unsigned Ints = 0; 221 if (MPT->isMemberFunctionPointer()) 222 Ptrs = 1; 223 else 224 Ints = 1; 225 if (inheritanceModelHasNVOffsetField(MPT->isMemberFunctionPointer(), 226 Inheritance)) 227 Ints++; 228 if (inheritanceModelHasVBPtrOffsetField(Inheritance)) 229 Ints++; 230 if (inheritanceModelHasVBTableOffsetField(Inheritance)) 231 Ints++; 232 return std::make_pair(Ptrs, Ints); 233} 234 235CXXABI::MemberPointerInfo MicrosoftCXXABI::getMemberPointerInfo( 236 const MemberPointerType *MPT) const { 237 // The nominal struct is laid out with pointers followed by ints and aligned 238 // to a pointer width if any are present and an int width otherwise. 239 const TargetInfo &Target = Context.getTargetInfo(); 240 unsigned PtrSize = Target.getPointerWidth(0); 241 unsigned IntSize = Target.getIntWidth(); 242 243 unsigned Ptrs, Ints; 244 std::tie(Ptrs, Ints) = getMSMemberPointerSlots(MPT); 245 MemberPointerInfo MPI; 246 MPI.HasPadding = false; 247 MPI.Width = Ptrs * PtrSize + Ints * IntSize; 248 249 // When MSVC does x86_32 record layout, it aligns aggregate member pointers to 250 // 8 bytes. However, __alignof usually returns 4 for data memptrs and 8 for 251 // function memptrs. 252 if (Ptrs + Ints > 1 && Target.getTriple().isArch32Bit()) 253 MPI.Align = 64; 254 else if (Ptrs) 255 MPI.Align = Target.getPointerAlign(0); 256 else 257 MPI.Align = Target.getIntAlign(); 258 259 if (Target.getTriple().isArch64Bit()) { 260 MPI.Width = llvm::alignTo(MPI.Width, MPI.Align); 261 MPI.HasPadding = MPI.Width != (Ptrs * PtrSize + Ints * IntSize); 262 } 263 return MPI; 264} 265 266CXXABI *clang::CreateMicrosoftCXXABI(ASTContext &Ctx) { 267 return new MicrosoftCXXABI(Ctx); 268} 269 270