xref: /minix3/external/bsd/llvm/dist/clang/lib/AST/MicrosoftCXXABI.cpp (revision f4a2713ac843a11c696ec80c0a5e3e5d80b4d338)
1*f4a2713aSLionel Sambuc //===------- MicrosoftCXXABI.cpp - AST support for the Microsoft C++ ABI --===//
2*f4a2713aSLionel Sambuc //
3*f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4*f4a2713aSLionel Sambuc //
5*f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6*f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7*f4a2713aSLionel Sambuc //
8*f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9*f4a2713aSLionel Sambuc //
10*f4a2713aSLionel Sambuc // This provides C++ AST support targeting the Microsoft Visual C++
11*f4a2713aSLionel Sambuc // ABI.
12*f4a2713aSLionel Sambuc //
13*f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
14*f4a2713aSLionel Sambuc 
15*f4a2713aSLionel Sambuc #include "CXXABI.h"
16*f4a2713aSLionel Sambuc #include "clang/AST/Attr.h"
17*f4a2713aSLionel Sambuc #include "clang/AST/ASTContext.h"
18*f4a2713aSLionel Sambuc #include "clang/AST/DeclCXX.h"
19*f4a2713aSLionel Sambuc #include "clang/AST/MangleNumberingContext.h"
20*f4a2713aSLionel Sambuc #include "clang/AST/RecordLayout.h"
21*f4a2713aSLionel Sambuc #include "clang/AST/Type.h"
22*f4a2713aSLionel Sambuc #include "clang/Basic/TargetInfo.h"
23*f4a2713aSLionel Sambuc 
24*f4a2713aSLionel Sambuc using namespace clang;
25*f4a2713aSLionel Sambuc 
26*f4a2713aSLionel Sambuc namespace {
27*f4a2713aSLionel Sambuc 
28*f4a2713aSLionel Sambuc /// \brief Numbers things which need to correspond across multiple TUs.
29*f4a2713aSLionel Sambuc /// Typically these are things like static locals, lambdas, or blocks.
30*f4a2713aSLionel Sambuc class MicrosoftNumberingContext : public MangleNumberingContext {
31*f4a2713aSLionel Sambuc   unsigned NumStaticLocals;
32*f4a2713aSLionel Sambuc 
33*f4a2713aSLionel Sambuc public:
34*f4a2713aSLionel Sambuc   MicrosoftNumberingContext() : NumStaticLocals(0) { }
35*f4a2713aSLionel Sambuc 
36*f4a2713aSLionel Sambuc   /// Static locals are numbered by source order.
37*f4a2713aSLionel Sambuc   virtual unsigned getManglingNumber(const VarDecl *VD) {
38*f4a2713aSLionel Sambuc     assert(VD->isStaticLocal());
39*f4a2713aSLionel Sambuc     return ++NumStaticLocals;
40*f4a2713aSLionel Sambuc   }
41*f4a2713aSLionel Sambuc };
42*f4a2713aSLionel Sambuc 
43*f4a2713aSLionel Sambuc class MicrosoftCXXABI : public CXXABI {
44*f4a2713aSLionel Sambuc   ASTContext &Context;
45*f4a2713aSLionel Sambuc public:
46*f4a2713aSLionel Sambuc   MicrosoftCXXABI(ASTContext &Ctx) : Context(Ctx) { }
47*f4a2713aSLionel Sambuc 
48*f4a2713aSLionel Sambuc   std::pair<uint64_t, unsigned>
49*f4a2713aSLionel Sambuc   getMemberPointerWidthAndAlign(const MemberPointerType *MPT) const;
50*f4a2713aSLionel Sambuc 
51*f4a2713aSLionel Sambuc   CallingConv getDefaultMethodCallConv(bool isVariadic) const {
52*f4a2713aSLionel Sambuc     if (!isVariadic &&
53*f4a2713aSLionel Sambuc         Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86)
54*f4a2713aSLionel Sambuc       return CC_X86ThisCall;
55*f4a2713aSLionel Sambuc     return CC_C;
56*f4a2713aSLionel Sambuc   }
57*f4a2713aSLionel Sambuc 
58*f4a2713aSLionel Sambuc   bool isNearlyEmpty(const CXXRecordDecl *RD) const {
59*f4a2713aSLionel Sambuc     // FIXME: Audit the corners
60*f4a2713aSLionel Sambuc     if (!RD->isDynamicClass())
61*f4a2713aSLionel Sambuc       return false;
62*f4a2713aSLionel Sambuc 
63*f4a2713aSLionel Sambuc     const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
64*f4a2713aSLionel Sambuc 
65*f4a2713aSLionel Sambuc     // In the Microsoft ABI, classes can have one or two vtable pointers.
66*f4a2713aSLionel Sambuc     CharUnits PointerSize =
67*f4a2713aSLionel Sambuc       Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
68*f4a2713aSLionel Sambuc     return Layout.getNonVirtualSize() == PointerSize ||
69*f4a2713aSLionel Sambuc       Layout.getNonVirtualSize() == PointerSize * 2;
70*f4a2713aSLionel Sambuc   }
71*f4a2713aSLionel Sambuc 
72*f4a2713aSLionel Sambuc   MangleNumberingContext *createMangleNumberingContext() const {
73*f4a2713aSLionel Sambuc     return new MicrosoftNumberingContext();
74*f4a2713aSLionel Sambuc   }
75*f4a2713aSLionel Sambuc };
76*f4a2713aSLionel Sambuc }
77*f4a2713aSLionel Sambuc 
78*f4a2713aSLionel Sambuc // getNumBases() seems to only give us the number of direct bases, and not the
79*f4a2713aSLionel Sambuc // total.  This function tells us if we inherit from anybody that uses MI, or if
80*f4a2713aSLionel Sambuc // we have a non-primary base class, which uses the multiple inheritance model.
81*f4a2713aSLionel Sambuc static bool usesMultipleInheritanceModel(const CXXRecordDecl *RD) {
82*f4a2713aSLionel Sambuc   while (RD->getNumBases() > 0) {
83*f4a2713aSLionel Sambuc     if (RD->getNumBases() > 1)
84*f4a2713aSLionel Sambuc       return true;
85*f4a2713aSLionel Sambuc     assert(RD->getNumBases() == 1);
86*f4a2713aSLionel Sambuc     const CXXRecordDecl *Base =
87*f4a2713aSLionel Sambuc         RD->bases_begin()->getType()->getAsCXXRecordDecl();
88*f4a2713aSLionel Sambuc     if (RD->isPolymorphic() && !Base->isPolymorphic())
89*f4a2713aSLionel Sambuc       return true;
90*f4a2713aSLionel Sambuc     RD = Base;
91*f4a2713aSLionel Sambuc   }
92*f4a2713aSLionel Sambuc   return false;
93*f4a2713aSLionel Sambuc }
94*f4a2713aSLionel Sambuc 
95*f4a2713aSLionel Sambuc static MSInheritanceModel MSInheritanceAttrToModel(attr::Kind Kind) {
96*f4a2713aSLionel Sambuc   switch (Kind) {
97*f4a2713aSLionel Sambuc   default: llvm_unreachable("expected MS inheritance attribute");
98*f4a2713aSLionel Sambuc   case attr::SingleInheritance:      return MSIM_Single;
99*f4a2713aSLionel Sambuc   case attr::MultipleInheritance:    return MSIM_Multiple;
100*f4a2713aSLionel Sambuc   case attr::VirtualInheritance:     return MSIM_Virtual;
101*f4a2713aSLionel Sambuc   case attr::UnspecifiedInheritance: return MSIM_Unspecified;
102*f4a2713aSLionel Sambuc   }
103*f4a2713aSLionel Sambuc }
104*f4a2713aSLionel Sambuc 
105*f4a2713aSLionel Sambuc MSInheritanceModel CXXRecordDecl::getMSInheritanceModel() const {
106*f4a2713aSLionel Sambuc   if (Attr *IA = this->getAttr<MSInheritanceAttr>())
107*f4a2713aSLionel Sambuc     return MSInheritanceAttrToModel(IA->getKind());
108*f4a2713aSLionel Sambuc   // If there was no explicit attribute, the record must be defined already, and
109*f4a2713aSLionel Sambuc   // we can figure out the inheritance model from its other properties.
110*f4a2713aSLionel Sambuc   if (this->getNumVBases() > 0)
111*f4a2713aSLionel Sambuc     return MSIM_Virtual;
112*f4a2713aSLionel Sambuc   if (usesMultipleInheritanceModel(this))
113*f4a2713aSLionel Sambuc     return this->isPolymorphic() ? MSIM_MultiplePolymorphic : MSIM_Multiple;
114*f4a2713aSLionel Sambuc   return this->isPolymorphic() ? MSIM_SinglePolymorphic : MSIM_Single;
115*f4a2713aSLionel Sambuc }
116*f4a2713aSLionel Sambuc 
117*f4a2713aSLionel Sambuc // Returns the number of pointer and integer slots used to represent a member
118*f4a2713aSLionel Sambuc // pointer in the MS C++ ABI.
119*f4a2713aSLionel Sambuc //
120*f4a2713aSLionel Sambuc // Member function pointers have the following general form;  however, fields
121*f4a2713aSLionel Sambuc // are dropped as permitted (under the MSVC interpretation) by the inheritance
122*f4a2713aSLionel Sambuc // model of the actual class.
123*f4a2713aSLionel Sambuc //
124*f4a2713aSLionel Sambuc //   struct {
125*f4a2713aSLionel Sambuc //     // A pointer to the member function to call.  If the member function is
126*f4a2713aSLionel Sambuc //     // virtual, this will be a thunk that forwards to the appropriate vftable
127*f4a2713aSLionel Sambuc //     // slot.
128*f4a2713aSLionel Sambuc //     void *FunctionPointerOrVirtualThunk;
129*f4a2713aSLionel Sambuc //
130*f4a2713aSLionel Sambuc //     // An offset to add to the address of the vbtable pointer after (possibly)
131*f4a2713aSLionel Sambuc //     // selecting the virtual base but before resolving and calling the function.
132*f4a2713aSLionel Sambuc //     // Only needed if the class has any virtual bases or bases at a non-zero
133*f4a2713aSLionel Sambuc //     // offset.
134*f4a2713aSLionel Sambuc //     int NonVirtualBaseAdjustment;
135*f4a2713aSLionel Sambuc //
136*f4a2713aSLionel Sambuc //     // An offset within the vb-table that selects the virtual base containing
137*f4a2713aSLionel Sambuc //     // the member.  Loading from this offset produces a new offset that is
138*f4a2713aSLionel Sambuc //     // added to the address of the vb-table pointer to produce the base.
139*f4a2713aSLionel Sambuc //     int VirtualBaseAdjustmentOffset;
140*f4a2713aSLionel Sambuc //
141*f4a2713aSLionel Sambuc //     // The offset of the vb-table pointer within the object.  Only needed for
142*f4a2713aSLionel Sambuc //     // incomplete types.
143*f4a2713aSLionel Sambuc //     int VBPtrOffset;
144*f4a2713aSLionel Sambuc //   };
145*f4a2713aSLionel Sambuc static std::pair<unsigned, unsigned>
146*f4a2713aSLionel Sambuc getMSMemberPointerSlots(const MemberPointerType *MPT) {
147*f4a2713aSLionel Sambuc   const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
148*f4a2713aSLionel Sambuc   MSInheritanceModel Inheritance = RD->getMSInheritanceModel();
149*f4a2713aSLionel Sambuc   unsigned Ptrs;
150*f4a2713aSLionel Sambuc   unsigned Ints = 0;
151*f4a2713aSLionel Sambuc   if (MPT->isMemberFunctionPointer()) {
152*f4a2713aSLionel Sambuc     // Member function pointers are a struct of a function pointer followed by a
153*f4a2713aSLionel Sambuc     // variable number of ints depending on the inheritance model used.  The
154*f4a2713aSLionel Sambuc     // function pointer is a real function if it is non-virtual and a vftable
155*f4a2713aSLionel Sambuc     // slot thunk if it is virtual.  The ints select the object base passed for
156*f4a2713aSLionel Sambuc     // the 'this' pointer.
157*f4a2713aSLionel Sambuc     Ptrs = 1;  // First slot is always a function pointer.
158*f4a2713aSLionel Sambuc     switch (Inheritance) {
159*f4a2713aSLionel Sambuc     case MSIM_Unspecified: ++Ints;  // VBTableOffset
160*f4a2713aSLionel Sambuc     case MSIM_Virtual:     ++Ints;  // VirtualBaseAdjustmentOffset
161*f4a2713aSLionel Sambuc     case MSIM_MultiplePolymorphic:
162*f4a2713aSLionel Sambuc     case MSIM_Multiple:    ++Ints;  // NonVirtualBaseAdjustment
163*f4a2713aSLionel Sambuc     case MSIM_SinglePolymorphic:
164*f4a2713aSLionel Sambuc     case MSIM_Single:      break;   // Nothing
165*f4a2713aSLionel Sambuc     }
166*f4a2713aSLionel Sambuc   } else {
167*f4a2713aSLionel Sambuc     // Data pointers are an aggregate of ints.  The first int is an offset
168*f4a2713aSLionel Sambuc     // followed by vbtable-related offsets.
169*f4a2713aSLionel Sambuc     Ptrs = 0;
170*f4a2713aSLionel Sambuc     switch (Inheritance) {
171*f4a2713aSLionel Sambuc     case MSIM_Unspecified: ++Ints;  // VBTableOffset
172*f4a2713aSLionel Sambuc     case MSIM_Virtual:     ++Ints;  // VirtualBaseAdjustmentOffset
173*f4a2713aSLionel Sambuc     case MSIM_MultiplePolymorphic:
174*f4a2713aSLionel Sambuc     case MSIM_Multiple:             // Nothing
175*f4a2713aSLionel Sambuc     case MSIM_SinglePolymorphic:
176*f4a2713aSLionel Sambuc     case MSIM_Single:      ++Ints;  // Field offset
177*f4a2713aSLionel Sambuc     }
178*f4a2713aSLionel Sambuc   }
179*f4a2713aSLionel Sambuc   return std::make_pair(Ptrs, Ints);
180*f4a2713aSLionel Sambuc }
181*f4a2713aSLionel Sambuc 
182*f4a2713aSLionel Sambuc std::pair<uint64_t, unsigned> MicrosoftCXXABI::getMemberPointerWidthAndAlign(
183*f4a2713aSLionel Sambuc     const MemberPointerType *MPT) const {
184*f4a2713aSLionel Sambuc   const TargetInfo &Target = Context.getTargetInfo();
185*f4a2713aSLionel Sambuc   assert(Target.getTriple().getArch() == llvm::Triple::x86 ||
186*f4a2713aSLionel Sambuc          Target.getTriple().getArch() == llvm::Triple::x86_64);
187*f4a2713aSLionel Sambuc   unsigned Ptrs, Ints;
188*f4a2713aSLionel Sambuc   llvm::tie(Ptrs, Ints) = getMSMemberPointerSlots(MPT);
189*f4a2713aSLionel Sambuc   // The nominal struct is laid out with pointers followed by ints and aligned
190*f4a2713aSLionel Sambuc   // to a pointer width if any are present and an int width otherwise.
191*f4a2713aSLionel Sambuc   unsigned PtrSize = Target.getPointerWidth(0);
192*f4a2713aSLionel Sambuc   unsigned IntSize = Target.getIntWidth();
193*f4a2713aSLionel Sambuc   uint64_t Width = Ptrs * PtrSize + Ints * IntSize;
194*f4a2713aSLionel Sambuc   unsigned Align = Ptrs > 0 ? Target.getPointerAlign(0) : Target.getIntAlign();
195*f4a2713aSLionel Sambuc   Width = llvm::RoundUpToAlignment(Width, Align);
196*f4a2713aSLionel Sambuc   return std::make_pair(Width, Align);
197*f4a2713aSLionel Sambuc }
198*f4a2713aSLionel Sambuc 
199*f4a2713aSLionel Sambuc CXXABI *clang::CreateMicrosoftCXXABI(ASTContext &Ctx) {
200*f4a2713aSLionel Sambuc   return new MicrosoftCXXABI(Ctx);
201*f4a2713aSLionel Sambuc }
202*f4a2713aSLionel Sambuc 
203