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 24 using namespace clang; 25 26 namespace { 27 28 /// Numbers things which need to correspond across multiple TUs. 29 /// Typically these are things like static locals, lambdas, or blocks. 30 class MicrosoftNumberingContext : public MangleNumberingContext { 31 llvm::DenseMap<const Type *, unsigned> ManglingNumbers; 32 unsigned LambdaManglingNumber; 33 unsigned StaticLocalNumber; 34 unsigned StaticThreadlocalNumber; 35 36 public: 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 67 class 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 76 public: 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. 144 static 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 158 MSInheritanceModel 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 168 MSInheritanceModel CXXRecordDecl::getMSInheritanceModel() const { 169 MSInheritanceAttr *IA = getAttr<MSInheritanceAttr>(); 170 assert(IA && "Expected MSInheritanceAttr on the CXXRecordDecl!"); 171 return IA->getInheritanceModel(); 172 } 173 174 bool CXXRecordDecl::nullFieldOffsetIsZero() const { 175 return !inheritanceModelHasOnlyOneField(/*IsMemberFunction=*/false, 176 getMSInheritanceModel()) || 177 (hasDefinition() && isPolymorphic()); 178 } 179 180 MSVtorDispMode 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 // }; 215 static std::pair<unsigned, unsigned> 216 getMSMemberPointerSlots(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 235 CXXABI::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 266 CXXABI *clang::CreateMicrosoftCXXABI(ASTContext &Ctx) { 267 return new MicrosoftCXXABI(Ctx); 268 } 269 270