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