Home | History | Annotate | Download | only in AST
      1 //===------- MicrosoftCXXABI.cpp - AST support for the Microsoft C++ ABI --===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This provides C++ AST support targeting the Microsoft Visual C++
     11 // ABI.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "CXXABI.h"
     16 #include "clang/AST/ASTContext.h"
     17 #include "clang/AST/Attr.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 /// \brief 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 public:
     32   unsigned getManglingNumber(const VarDecl *VD,
     33                              unsigned MSLocalManglingNumber) override {
     34     return MSLocalManglingNumber;
     35   }
     36 
     37   unsigned getManglingNumber(const TagDecl *TD,
     38                              unsigned MSLocalManglingNumber) override {
     39     return MSLocalManglingNumber;
     40   }
     41 };
     42 
     43 class MicrosoftCXXABI : public CXXABI {
     44   ASTContext &Context;
     45 public:
     46   MicrosoftCXXABI(ASTContext &Ctx) : Context(Ctx) { }
     47 
     48   std::pair<uint64_t, unsigned>
     49   getMemberPointerWidthAndAlign(const MemberPointerType *MPT) const override;
     50 
     51   CallingConv getDefaultMethodCallConv(bool isVariadic) const override {
     52     if (!isVariadic &&
     53         Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86)
     54       return CC_X86ThisCall;
     55     return CC_C;
     56   }
     57 
     58   bool isNearlyEmpty(const CXXRecordDecl *RD) const override {
     59     // FIXME: Audit the corners
     60     if (!RD->isDynamicClass())
     61       return false;
     62 
     63     const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
     64 
     65     // In the Microsoft ABI, classes can have one or two vtable pointers.
     66     CharUnits PointerSize =
     67       Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
     68     return Layout.getNonVirtualSize() == PointerSize ||
     69       Layout.getNonVirtualSize() == PointerSize * 2;
     70   }
     71 
     72   MangleNumberingContext *createMangleNumberingContext() const override {
     73     return new MicrosoftNumberingContext();
     74   }
     75 };
     76 }
     77 
     78 // getNumBases() seems to only give us the number of direct bases, and not the
     79 // total.  This function tells us if we inherit from anybody that uses MI, or if
     80 // we have a non-primary base class, which uses the multiple inheritance model.
     81 static bool usesMultipleInheritanceModel(const CXXRecordDecl *RD) {
     82   while (RD->getNumBases() > 0) {
     83     if (RD->getNumBases() > 1)
     84       return true;
     85     assert(RD->getNumBases() == 1);
     86     const CXXRecordDecl *Base =
     87         RD->bases_begin()->getType()->getAsCXXRecordDecl();
     88     if (RD->isPolymorphic() && !Base->isPolymorphic())
     89       return true;
     90     RD = Base;
     91   }
     92   return false;
     93 }
     94 
     95 MSInheritanceAttr::Spelling CXXRecordDecl::calculateInheritanceModel() const {
     96   if (!hasDefinition() || isParsingBaseSpecifiers())
     97     return MSInheritanceAttr::Keyword_unspecified_inheritance;
     98   if (getNumVBases() > 0)
     99     return MSInheritanceAttr::Keyword_virtual_inheritance;
    100   if (usesMultipleInheritanceModel(this))
    101     return MSInheritanceAttr::Keyword_multiple_inheritance;
    102   return MSInheritanceAttr::Keyword_single_inheritance;
    103 }
    104 
    105 MSInheritanceAttr::Spelling
    106 CXXRecordDecl::getMSInheritanceModel() const {
    107   MSInheritanceAttr *IA = getAttr<MSInheritanceAttr>();
    108   assert(IA && "Expected MSInheritanceAttr on the CXXRecordDecl!");
    109   return IA->getSemanticSpelling();
    110 }
    111 
    112 MSVtorDispAttr::Mode CXXRecordDecl::getMSVtorDispMode() const {
    113   if (MSVtorDispAttr *VDA = getAttr<MSVtorDispAttr>())
    114     return VDA->getVtorDispMode();
    115   return MSVtorDispAttr::Mode(getASTContext().getLangOpts().VtorDispMode);
    116 }
    117 
    118 // Returns the number of pointer and integer slots used to represent a member
    119 // pointer in the MS C++ ABI.
    120 //
    121 // Member function pointers have the following general form;  however, fields
    122 // are dropped as permitted (under the MSVC interpretation) by the inheritance
    123 // model of the actual class.
    124 //
    125 //   struct {
    126 //     // A pointer to the member function to call.  If the member function is
    127 //     // virtual, this will be a thunk that forwards to the appropriate vftable
    128 //     // slot.
    129 //     void *FunctionPointerOrVirtualThunk;
    130 //
    131 //     // An offset to add to the address of the vbtable pointer after (possibly)
    132 //     // selecting the virtual base but before resolving and calling the function.
    133 //     // Only needed if the class has any virtual bases or bases at a non-zero
    134 //     // offset.
    135 //     int NonVirtualBaseAdjustment;
    136 //
    137 //     // The offset of the vb-table pointer within the object.  Only needed for
    138 //     // incomplete types.
    139 //     int VBPtrOffset;
    140 //
    141 //     // An offset within the vb-table that selects the virtual base containing
    142 //     // the member.  Loading from this offset produces a new offset that is
    143 //     // added to the address of the vb-table pointer to produce the base.
    144 //     int VirtualBaseAdjustmentOffset;
    145 //   };
    146 static std::pair<unsigned, unsigned>
    147 getMSMemberPointerSlots(const MemberPointerType *MPT) {
    148   const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
    149   MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel();
    150   unsigned Ptrs = 0;
    151   unsigned Ints = 0;
    152   if (MPT->isMemberFunctionPointer())
    153     Ptrs = 1;
    154   else
    155     Ints = 1;
    156   if (MSInheritanceAttr::hasNVOffsetField(MPT->isMemberFunctionPointer(),
    157                                           Inheritance))
    158     Ints++;
    159   if (MSInheritanceAttr::hasVBPtrOffsetField(Inheritance))
    160     Ints++;
    161   if (MSInheritanceAttr::hasVBTableOffsetField(Inheritance))
    162     Ints++;
    163   return std::make_pair(Ptrs, Ints);
    164 }
    165 
    166 std::pair<uint64_t, unsigned> MicrosoftCXXABI::getMemberPointerWidthAndAlign(
    167     const MemberPointerType *MPT) const {
    168   const TargetInfo &Target = Context.getTargetInfo();
    169   assert(Target.getTriple().getArch() == llvm::Triple::x86 ||
    170          Target.getTriple().getArch() == llvm::Triple::x86_64);
    171   unsigned Ptrs, Ints;
    172   std::tie(Ptrs, Ints) = getMSMemberPointerSlots(MPT);
    173   // The nominal struct is laid out with pointers followed by ints and aligned
    174   // to a pointer width if any are present and an int width otherwise.
    175   unsigned PtrSize = Target.getPointerWidth(0);
    176   unsigned IntSize = Target.getIntWidth();
    177   uint64_t Width = Ptrs * PtrSize + Ints * IntSize;
    178   unsigned Align;
    179 
    180   // When MSVC does x86_32 record layout, it aligns aggregate member pointers to
    181   // 8 bytes.  However, __alignof usually returns 4 for data memptrs and 8 for
    182   // function memptrs.
    183   if (Ptrs + Ints > 1 && Target.getTriple().getArch() == llvm::Triple::x86)
    184     Align = 8 * 8;
    185   else if (Ptrs)
    186     Align = Target.getPointerAlign(0);
    187   else
    188     Align = Target.getIntAlign();
    189 
    190   if (Target.getTriple().getArch() == llvm::Triple::x86_64)
    191     Width = llvm::RoundUpToAlignment(Width, Align);
    192   return std::make_pair(Width, Align);
    193 }
    194 
    195 CXXABI *clang::CreateMicrosoftCXXABI(ASTContext &Ctx) {
    196   return new MicrosoftCXXABI(Ctx);
    197 }
    198 
    199