1f4a2713aSLionel Sambuc //===------- ItaniumCXXABI.cpp - AST support for the Itanium C++ ABI ------===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // This provides C++ AST support targeting the Itanium C++ ABI, which is
11f4a2713aSLionel Sambuc // documented at:
12f4a2713aSLionel Sambuc // http://www.codesourcery.com/public/cxx-abi/abi.html
13f4a2713aSLionel Sambuc // http://www.codesourcery.com/public/cxx-abi/abi-eh.html
14f4a2713aSLionel Sambuc //
15f4a2713aSLionel Sambuc // It also supports the closely-related ARM C++ ABI, documented at:
16f4a2713aSLionel Sambuc // http://infocenter.arm.com/help/topic/com.arm.doc.ihi0041c/IHI0041C_cppabi.pdf
17f4a2713aSLionel Sambuc //
18f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
19f4a2713aSLionel Sambuc
20f4a2713aSLionel Sambuc #include "CXXABI.h"
21f4a2713aSLionel Sambuc #include "clang/AST/ASTContext.h"
22f4a2713aSLionel Sambuc #include "clang/AST/DeclCXX.h"
23f4a2713aSLionel Sambuc #include "clang/AST/MangleNumberingContext.h"
24f4a2713aSLionel Sambuc #include "clang/AST/RecordLayout.h"
25f4a2713aSLionel Sambuc #include "clang/AST/Type.h"
26f4a2713aSLionel Sambuc #include "clang/Basic/TargetInfo.h"
27f4a2713aSLionel Sambuc
28f4a2713aSLionel Sambuc using namespace clang;
29f4a2713aSLionel Sambuc
30f4a2713aSLionel Sambuc namespace {
31f4a2713aSLionel Sambuc
32*0a6a1f1dSLionel Sambuc /// According to Itanium C++ ABI 5.1.2:
33*0a6a1f1dSLionel Sambuc /// the name of an anonymous union is considered to be
34*0a6a1f1dSLionel Sambuc /// the name of the first named data member found by a pre-order,
35*0a6a1f1dSLionel Sambuc /// depth-first, declaration-order walk of the data members of
36*0a6a1f1dSLionel Sambuc /// the anonymous union.
37*0a6a1f1dSLionel Sambuc /// If there is no such data member (i.e., if all of the data members
38*0a6a1f1dSLionel Sambuc /// in the union are unnamed), then there is no way for a program to
39*0a6a1f1dSLionel Sambuc /// refer to the anonymous union, and there is therefore no need to mangle its name.
40*0a6a1f1dSLionel Sambuc ///
41*0a6a1f1dSLionel Sambuc /// Returns the name of anonymous union VarDecl or nullptr if it is not found.
findAnonymousUnionVarDeclName(const VarDecl & VD)42*0a6a1f1dSLionel Sambuc static const IdentifierInfo *findAnonymousUnionVarDeclName(const VarDecl& VD) {
43*0a6a1f1dSLionel Sambuc const RecordType *RT = VD.getType()->getAs<RecordType>();
44*0a6a1f1dSLionel Sambuc assert(RT && "type of VarDecl is expected to be RecordType.");
45*0a6a1f1dSLionel Sambuc assert(RT->getDecl()->isUnion() && "RecordType is expected to be a union.");
46*0a6a1f1dSLionel Sambuc if (const FieldDecl *FD = RT->getDecl()->findFirstNamedDataMember()) {
47*0a6a1f1dSLionel Sambuc return FD->getIdentifier();
48*0a6a1f1dSLionel Sambuc }
49*0a6a1f1dSLionel Sambuc
50*0a6a1f1dSLionel Sambuc return nullptr;
51*0a6a1f1dSLionel Sambuc }
52*0a6a1f1dSLionel Sambuc
53f4a2713aSLionel Sambuc /// \brief Keeps track of the mangled names of lambda expressions and block
54f4a2713aSLionel Sambuc /// literals within a particular context.
55f4a2713aSLionel Sambuc class ItaniumNumberingContext : public MangleNumberingContext {
56*0a6a1f1dSLionel Sambuc llvm::DenseMap<const Type *, unsigned> ManglingNumbers;
57*0a6a1f1dSLionel Sambuc llvm::DenseMap<const IdentifierInfo *, unsigned> VarManglingNumbers;
58*0a6a1f1dSLionel Sambuc llvm::DenseMap<const IdentifierInfo *, unsigned> TagManglingNumbers;
59f4a2713aSLionel Sambuc
60f4a2713aSLionel Sambuc public:
getManglingNumber(const CXXMethodDecl * CallOperator)61*0a6a1f1dSLionel Sambuc unsigned getManglingNumber(const CXXMethodDecl *CallOperator) override {
62*0a6a1f1dSLionel Sambuc const FunctionProtoType *Proto =
63*0a6a1f1dSLionel Sambuc CallOperator->getType()->getAs<FunctionProtoType>();
64*0a6a1f1dSLionel Sambuc ASTContext &Context = CallOperator->getASTContext();
65*0a6a1f1dSLionel Sambuc
66*0a6a1f1dSLionel Sambuc QualType Key =
67*0a6a1f1dSLionel Sambuc Context.getFunctionType(Context.VoidTy, Proto->getParamTypes(),
68*0a6a1f1dSLionel Sambuc FunctionProtoType::ExtProtoInfo());
69*0a6a1f1dSLionel Sambuc Key = Context.getCanonicalType(Key);
70*0a6a1f1dSLionel Sambuc return ++ManglingNumbers[Key->castAs<FunctionProtoType>()];
71*0a6a1f1dSLionel Sambuc }
72*0a6a1f1dSLionel Sambuc
getManglingNumber(const BlockDecl * BD)73*0a6a1f1dSLionel Sambuc unsigned getManglingNumber(const BlockDecl *BD) override {
74*0a6a1f1dSLionel Sambuc const Type *Ty = nullptr;
75*0a6a1f1dSLionel Sambuc return ++ManglingNumbers[Ty];
76*0a6a1f1dSLionel Sambuc }
77*0a6a1f1dSLionel Sambuc
getStaticLocalNumber(const VarDecl * VD)78*0a6a1f1dSLionel Sambuc unsigned getStaticLocalNumber(const VarDecl *VD) override {
79*0a6a1f1dSLionel Sambuc return 0;
80*0a6a1f1dSLionel Sambuc }
81*0a6a1f1dSLionel Sambuc
82f4a2713aSLionel Sambuc /// Variable decls are numbered by identifier.
getManglingNumber(const VarDecl * VD,unsigned)83*0a6a1f1dSLionel Sambuc unsigned getManglingNumber(const VarDecl *VD, unsigned) override {
84*0a6a1f1dSLionel Sambuc const IdentifierInfo *Identifier = VD->getIdentifier();
85*0a6a1f1dSLionel Sambuc if (!Identifier) {
86*0a6a1f1dSLionel Sambuc // VarDecl without an identifier represents an anonymous union declaration.
87*0a6a1f1dSLionel Sambuc Identifier = findAnonymousUnionVarDeclName(*VD);
88*0a6a1f1dSLionel Sambuc }
89*0a6a1f1dSLionel Sambuc return ++VarManglingNumbers[Identifier];
90*0a6a1f1dSLionel Sambuc }
91*0a6a1f1dSLionel Sambuc
getManglingNumber(const TagDecl * TD,unsigned)92*0a6a1f1dSLionel Sambuc unsigned getManglingNumber(const TagDecl *TD, unsigned) override {
93*0a6a1f1dSLionel Sambuc return ++TagManglingNumbers[TD->getIdentifier()];
94f4a2713aSLionel Sambuc }
95f4a2713aSLionel Sambuc };
96f4a2713aSLionel Sambuc
97f4a2713aSLionel Sambuc class ItaniumCXXABI : public CXXABI {
98f4a2713aSLionel Sambuc protected:
99f4a2713aSLionel Sambuc ASTContext &Context;
100f4a2713aSLionel Sambuc public:
ItaniumCXXABI(ASTContext & Ctx)101f4a2713aSLionel Sambuc ItaniumCXXABI(ASTContext &Ctx) : Context(Ctx) { }
102f4a2713aSLionel Sambuc
103f4a2713aSLionel Sambuc std::pair<uint64_t, unsigned>
getMemberPointerWidthAndAlign(const MemberPointerType * MPT) const104*0a6a1f1dSLionel Sambuc getMemberPointerWidthAndAlign(const MemberPointerType *MPT) const override {
105f4a2713aSLionel Sambuc const TargetInfo &Target = Context.getTargetInfo();
106f4a2713aSLionel Sambuc TargetInfo::IntType PtrDiff = Target.getPtrDiffType(0);
107f4a2713aSLionel Sambuc uint64_t Width = Target.getTypeWidth(PtrDiff);
108f4a2713aSLionel Sambuc unsigned Align = Target.getTypeAlign(PtrDiff);
109f4a2713aSLionel Sambuc if (MPT->getPointeeType()->isFunctionType())
110f4a2713aSLionel Sambuc Width = 2 * Width;
111f4a2713aSLionel Sambuc return std::make_pair(Width, Align);
112f4a2713aSLionel Sambuc }
113f4a2713aSLionel Sambuc
getDefaultMethodCallConv(bool isVariadic) const114*0a6a1f1dSLionel Sambuc CallingConv getDefaultMethodCallConv(bool isVariadic) const override {
115*0a6a1f1dSLionel Sambuc const llvm::Triple &T = Context.getTargetInfo().getTriple();
116*0a6a1f1dSLionel Sambuc if (!isVariadic && T.isWindowsGNUEnvironment() &&
117*0a6a1f1dSLionel Sambuc T.getArch() == llvm::Triple::x86)
118*0a6a1f1dSLionel Sambuc return CC_X86ThisCall;
119f4a2713aSLionel Sambuc return CC_C;
120f4a2713aSLionel Sambuc }
121f4a2713aSLionel Sambuc
122f4a2713aSLionel Sambuc // We cheat and just check that the class has a vtable pointer, and that it's
123f4a2713aSLionel Sambuc // only big enough to have a vtable pointer and nothing more (or less).
isNearlyEmpty(const CXXRecordDecl * RD) const124*0a6a1f1dSLionel Sambuc bool isNearlyEmpty(const CXXRecordDecl *RD) const override {
125f4a2713aSLionel Sambuc
126f4a2713aSLionel Sambuc // Check that the class has a vtable pointer.
127f4a2713aSLionel Sambuc if (!RD->isDynamicClass())
128f4a2713aSLionel Sambuc return false;
129f4a2713aSLionel Sambuc
130f4a2713aSLionel Sambuc const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
131f4a2713aSLionel Sambuc CharUnits PointerSize =
132f4a2713aSLionel Sambuc Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
133f4a2713aSLionel Sambuc return Layout.getNonVirtualSize() == PointerSize;
134f4a2713aSLionel Sambuc }
135f4a2713aSLionel Sambuc
createMangleNumberingContext() const136*0a6a1f1dSLionel Sambuc MangleNumberingContext *createMangleNumberingContext() const override {
137f4a2713aSLionel Sambuc return new ItaniumNumberingContext();
138f4a2713aSLionel Sambuc }
139f4a2713aSLionel Sambuc };
140f4a2713aSLionel Sambuc }
141f4a2713aSLionel Sambuc
CreateItaniumCXXABI(ASTContext & Ctx)142f4a2713aSLionel Sambuc CXXABI *clang::CreateItaniumCXXABI(ASTContext &Ctx) {
143f4a2713aSLionel Sambuc return new ItaniumCXXABI(Ctx);
144f4a2713aSLionel Sambuc }
145