MicrosoftCXXABI.cpp 9.0 KB

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