blob: 2f41cec718022e3fe3303e155bce8bd5d5807978 [file] [log] [blame]
Charles Davis071cc7d2010-08-16 03:33:14 +00001//===------- 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//
Chris Lattnerfc8f0e12011-04-15 05:22:18 +000010// This provides C++ AST support targeting the Microsoft Visual C++
Charles Davis071cc7d2010-08-16 03:33:14 +000011// ABI.
12//
13//===----------------------------------------------------------------------===//
14
15#include "CXXABI.h"
Reid Kleckner84e9ab42013-03-28 20:02:56 +000016#include "clang/AST/Attr.h"
Charles Davis071cc7d2010-08-16 03:33:14 +000017#include "clang/AST/ASTContext.h"
Charles Davis071cc7d2010-08-16 03:33:14 +000018#include "clang/AST/DeclCXX.h"
Anders Carlssondae0cb52010-11-25 01:51:53 +000019#include "clang/AST/RecordLayout.h"
20#include "clang/AST/Type.h"
21#include "clang/Basic/TargetInfo.h"
Charles Davis071cc7d2010-08-16 03:33:14 +000022
23using namespace clang;
24
25namespace {
26class MicrosoftCXXABI : public CXXABI {
27 ASTContext &Context;
28public:
29 MicrosoftCXXABI(ASTContext &Ctx) : Context(Ctx) { }
30
Reid Kleckner84e9ab42013-03-28 20:02:56 +000031 std::pair<uint64_t, unsigned>
32 getMemberPointerWidthAndAlign(const MemberPointerType *MPT) const;
Charles Davis424ae982010-10-29 03:25:11 +000033
Timur Iskhodzhanov8f88a1d2012-07-12 09:50:54 +000034 CallingConv getDefaultMethodCallConv(bool isVariadic) const {
35 if (!isVariadic && Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86)
Charles Davis424ae982010-10-29 03:25:11 +000036 return CC_X86ThisCall;
37 else
38 return CC_C;
39 }
Anders Carlssondae0cb52010-11-25 01:51:53 +000040
41 bool isNearlyEmpty(const CXXRecordDecl *RD) const {
42 // FIXME: Audit the corners
43 if (!RD->isDynamicClass())
44 return false;
45
46 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
47
48 // In the Microsoft ABI, classes can have one or two vtable pointers.
Ken Dyck5c3633f2011-02-01 01:52:10 +000049 CharUnits PointerSize =
Douglas Gregorbcfd1f52011-09-02 00:18:52 +000050 Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
Ken Dyck5c3633f2011-02-01 01:52:10 +000051 return Layout.getNonVirtualSize() == PointerSize ||
52 Layout.getNonVirtualSize() == PointerSize * 2;
Anders Carlssondae0cb52010-11-25 01:51:53 +000053 }
Charles Davis071cc7d2010-08-16 03:33:14 +000054};
55}
56
Reid Kleckner84e9ab42013-03-28 20:02:56 +000057// getNumBases() seems to only give us the number of direct bases, and not the
58// total. This function tells us if we inherit from anybody that uses MI, or if
59// we have a non-primary base class, which uses the multiple inheritance model.
60static bool usesMultipleInheritanceModel(const CXXRecordDecl *RD) {
61 while (RD->getNumBases() > 0) {
62 if (RD->getNumBases() > 1)
63 return true;
64 assert(RD->getNumBases() == 1);
65 const CXXRecordDecl *Base = RD->bases_begin()->getType()->getAsCXXRecordDecl();
66 if (RD->isPolymorphic() && !Base->isPolymorphic())
67 return true;
68 RD = Base;
69 }
70 return false;
71}
72
73std::pair<uint64_t, unsigned>
74MicrosoftCXXABI::getMemberPointerWidthAndAlign(const MemberPointerType *MPT) const {
75 const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
76 const TargetInfo &Target = Context.getTargetInfo();
77
78 assert(Target.getTriple().getArch() == llvm::Triple::x86 ||
79 Target.getTriple().getArch() == llvm::Triple::x86_64);
80
81 Attr *IA = RD->getAttr<MSInheritanceAttr>();
82 attr::Kind Inheritance;
83 if (IA) {
84 Inheritance = IA->getKind();
85 } else if (RD->getNumVBases() > 0) {
86 Inheritance = attr::VirtualInheritance;
87 } else if (MPT->getPointeeType()->isFunctionType() &&
88 usesMultipleInheritanceModel(RD)) {
89 Inheritance = attr::MultipleInheritance;
90 } else {
91 Inheritance = attr::SingleInheritance;
92 }
93
94 unsigned PtrSize = Target.getPointerWidth(0);
95 unsigned IntSize = Target.getIntWidth();
96 uint64_t Width;
97 unsigned Align;
98 if (MPT->getPointeeType()->isFunctionType()) {
99 // Member function pointers are a struct of a function pointer followed by a
100 // variable number of ints depending on the inheritance model used. The
101 // function pointer is a real function if it is non-virtual and a vftable
102 // slot thunk if it is virtual. The ints select the object base passed for
103 // the 'this' pointer.
104 Align = Target.getPointerAlign(0);
105 switch (Inheritance) {
106 case attr::SingleInheritance: Width = PtrSize; break;
107 case attr::MultipleInheritance: Width = PtrSize + 1 * IntSize; break;
108 case attr::VirtualInheritance: Width = PtrSize + 2 * IntSize; break;
109 case attr::UnspecifiedInheritance: Width = PtrSize + 3 * IntSize; break;
110 default: llvm_unreachable("unknown inheritance model");
111 }
112 } else {
113 // Data pointers are an aggregate of ints. The first int is an offset
114 // followed by vbtable-related offsets.
115 Align = Target.getIntAlign();
116 switch (Inheritance) {
117 case attr::SingleInheritance: // Same as multiple inheritance.
118 case attr::MultipleInheritance: Width = 1 * IntSize; break;
119 case attr::VirtualInheritance: Width = 2 * IntSize; break;
120 case attr::UnspecifiedInheritance: Width = 3 * IntSize; break;
121 default: llvm_unreachable("unknown inheritance model");
122 }
123 }
124 Width = llvm::RoundUpToAlignment(Width, Align);
125
126 // FIXME: Verify that our alignment matches MSVC.
127 return std::make_pair(Width, Align);
Charles Davis071cc7d2010-08-16 03:33:14 +0000128}
129
130CXXABI *clang::CreateMicrosoftCXXABI(ASTContext &Ctx) {
131 return new MicrosoftCXXABI(Ctx);
132}
133