xref: /minix3/external/bsd/llvm/dist/clang/lib/AST/ItaniumCXXABI.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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