MicrosoftCXXABI.cpp revision 84e9ab44af3a16f66d62590505db2036ef0aa03b
1071cc7deffad608165b1ddd5263e8bf181861520Charles Davis//===------- MicrosoftCXXABI.cpp - AST support for the Microsoft C++ ABI --===// 2071cc7deffad608165b1ddd5263e8bf181861520Charles Davis// 3071cc7deffad608165b1ddd5263e8bf181861520Charles Davis// The LLVM Compiler Infrastructure 4071cc7deffad608165b1ddd5263e8bf181861520Charles Davis// 5071cc7deffad608165b1ddd5263e8bf181861520Charles Davis// This file is distributed under the University of Illinois Open Source 6071cc7deffad608165b1ddd5263e8bf181861520Charles Davis// License. See LICENSE.TXT for details. 7071cc7deffad608165b1ddd5263e8bf181861520Charles Davis// 8071cc7deffad608165b1ddd5263e8bf181861520Charles Davis//===----------------------------------------------------------------------===// 9071cc7deffad608165b1ddd5263e8bf181861520Charles Davis// 10fc8f0e14ad142ed811e90fbd9a30e419e301c717Chris Lattner// This provides C++ AST support targeting the Microsoft Visual C++ 11071cc7deffad608165b1ddd5263e8bf181861520Charles Davis// ABI. 12071cc7deffad608165b1ddd5263e8bf181861520Charles Davis// 13071cc7deffad608165b1ddd5263e8bf181861520Charles Davis//===----------------------------------------------------------------------===// 14071cc7deffad608165b1ddd5263e8bf181861520Charles Davis 15071cc7deffad608165b1ddd5263e8bf181861520Charles Davis#include "CXXABI.h" 1684e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner#include "clang/AST/Attr.h" 17071cc7deffad608165b1ddd5263e8bf181861520Charles Davis#include "clang/AST/ASTContext.h" 18071cc7deffad608165b1ddd5263e8bf181861520Charles Davis#include "clang/AST/DeclCXX.h" 19dae0cb52e4e3d46bbfc9a4510909522197a92e54Anders Carlsson#include "clang/AST/RecordLayout.h" 20dae0cb52e4e3d46bbfc9a4510909522197a92e54Anders Carlsson#include "clang/AST/Type.h" 21dae0cb52e4e3d46bbfc9a4510909522197a92e54Anders Carlsson#include "clang/Basic/TargetInfo.h" 22071cc7deffad608165b1ddd5263e8bf181861520Charles Davis 23071cc7deffad608165b1ddd5263e8bf181861520Charles Davisusing namespace clang; 24071cc7deffad608165b1ddd5263e8bf181861520Charles Davis 25071cc7deffad608165b1ddd5263e8bf181861520Charles Davisnamespace { 26071cc7deffad608165b1ddd5263e8bf181861520Charles Davisclass MicrosoftCXXABI : public CXXABI { 27071cc7deffad608165b1ddd5263e8bf181861520Charles Davis ASTContext &Context; 28071cc7deffad608165b1ddd5263e8bf181861520Charles Davispublic: 29071cc7deffad608165b1ddd5263e8bf181861520Charles Davis MicrosoftCXXABI(ASTContext &Ctx) : Context(Ctx) { } 30071cc7deffad608165b1ddd5263e8bf181861520Charles Davis 3184e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner std::pair<uint64_t, unsigned> 3284e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner getMemberPointerWidthAndAlign(const MemberPointerType *MPT) const; 33424ae9882e8a6eecc9dfe7c2d8623e72b2563873Charles Davis 348f88a1dcc57cfe8580eb1558a783ad8499bfe8e0Timur Iskhodzhanov CallingConv getDefaultMethodCallConv(bool isVariadic) const { 358f88a1dcc57cfe8580eb1558a783ad8499bfe8e0Timur Iskhodzhanov if (!isVariadic && Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86) 36424ae9882e8a6eecc9dfe7c2d8623e72b2563873Charles Davis return CC_X86ThisCall; 37424ae9882e8a6eecc9dfe7c2d8623e72b2563873Charles Davis else 38424ae9882e8a6eecc9dfe7c2d8623e72b2563873Charles Davis return CC_C; 39424ae9882e8a6eecc9dfe7c2d8623e72b2563873Charles Davis } 40dae0cb52e4e3d46bbfc9a4510909522197a92e54Anders Carlsson 41dae0cb52e4e3d46bbfc9a4510909522197a92e54Anders Carlsson bool isNearlyEmpty(const CXXRecordDecl *RD) const { 42dae0cb52e4e3d46bbfc9a4510909522197a92e54Anders Carlsson // FIXME: Audit the corners 43dae0cb52e4e3d46bbfc9a4510909522197a92e54Anders Carlsson if (!RD->isDynamicClass()) 44dae0cb52e4e3d46bbfc9a4510909522197a92e54Anders Carlsson return false; 45dae0cb52e4e3d46bbfc9a4510909522197a92e54Anders Carlsson 46dae0cb52e4e3d46bbfc9a4510909522197a92e54Anders Carlsson const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); 47dae0cb52e4e3d46bbfc9a4510909522197a92e54Anders Carlsson 48dae0cb52e4e3d46bbfc9a4510909522197a92e54Anders Carlsson // In the Microsoft ABI, classes can have one or two vtable pointers. 495c3633fa57f27b0909ab5767715c4e66b8920165Ken Dyck CharUnits PointerSize = 50bcfd1f55bfbb3e5944cd5e03d07b343e280838c4Douglas Gregor Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0)); 515c3633fa57f27b0909ab5767715c4e66b8920165Ken Dyck return Layout.getNonVirtualSize() == PointerSize || 525c3633fa57f27b0909ab5767715c4e66b8920165Ken Dyck Layout.getNonVirtualSize() == PointerSize * 2; 53dae0cb52e4e3d46bbfc9a4510909522197a92e54Anders Carlsson } 54071cc7deffad608165b1ddd5263e8bf181861520Charles Davis}; 55071cc7deffad608165b1ddd5263e8bf181861520Charles Davis} 56071cc7deffad608165b1ddd5263e8bf181861520Charles Davis 5784e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner// getNumBases() seems to only give us the number of direct bases, and not the 5884e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner// total. This function tells us if we inherit from anybody that uses MI, or if 5984e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner// we have a non-primary base class, which uses the multiple inheritance model. 6084e9ab44af3a16f66d62590505db2036ef0aa03bReid Klecknerstatic bool usesMultipleInheritanceModel(const CXXRecordDecl *RD) { 6184e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner while (RD->getNumBases() > 0) { 6284e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner if (RD->getNumBases() > 1) 6384e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner return true; 6484e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner assert(RD->getNumBases() == 1); 6584e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner const CXXRecordDecl *Base = RD->bases_begin()->getType()->getAsCXXRecordDecl(); 6684e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner if (RD->isPolymorphic() && !Base->isPolymorphic()) 6784e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner return true; 6884e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner RD = Base; 6984e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner } 7084e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner return false; 7184e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner} 7284e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner 7384e9ab44af3a16f66d62590505db2036ef0aa03bReid Klecknerstd::pair<uint64_t, unsigned> 7484e9ab44af3a16f66d62590505db2036ef0aa03bReid KlecknerMicrosoftCXXABI::getMemberPointerWidthAndAlign(const MemberPointerType *MPT) const { 7584e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl(); 7684e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner const TargetInfo &Target = Context.getTargetInfo(); 7784e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner 7884e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner assert(Target.getTriple().getArch() == llvm::Triple::x86 || 7984e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner Target.getTriple().getArch() == llvm::Triple::x86_64); 8084e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner 8184e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner Attr *IA = RD->getAttr<MSInheritanceAttr>(); 8284e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner attr::Kind Inheritance; 8384e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner if (IA) { 8484e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner Inheritance = IA->getKind(); 8584e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner } else if (RD->getNumVBases() > 0) { 8684e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner Inheritance = attr::VirtualInheritance; 8784e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner } else if (MPT->getPointeeType()->isFunctionType() && 8884e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner usesMultipleInheritanceModel(RD)) { 8984e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner Inheritance = attr::MultipleInheritance; 9084e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner } else { 9184e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner Inheritance = attr::SingleInheritance; 9284e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner } 9384e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner 9484e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner unsigned PtrSize = Target.getPointerWidth(0); 9584e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner unsigned IntSize = Target.getIntWidth(); 9684e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner uint64_t Width; 9784e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner unsigned Align; 9884e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner if (MPT->getPointeeType()->isFunctionType()) { 9984e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner // Member function pointers are a struct of a function pointer followed by a 10084e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner // variable number of ints depending on the inheritance model used. The 10184e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner // function pointer is a real function if it is non-virtual and a vftable 10284e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner // slot thunk if it is virtual. The ints select the object base passed for 10384e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner // the 'this' pointer. 10484e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner Align = Target.getPointerAlign(0); 10584e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner switch (Inheritance) { 10684e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner case attr::SingleInheritance: Width = PtrSize; break; 10784e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner case attr::MultipleInheritance: Width = PtrSize + 1 * IntSize; break; 10884e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner case attr::VirtualInheritance: Width = PtrSize + 2 * IntSize; break; 10984e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner case attr::UnspecifiedInheritance: Width = PtrSize + 3 * IntSize; break; 11084e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner default: llvm_unreachable("unknown inheritance model"); 11184e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner } 11284e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner } else { 11384e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner // Data pointers are an aggregate of ints. The first int is an offset 11484e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner // followed by vbtable-related offsets. 11584e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner Align = Target.getIntAlign(); 11684e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner switch (Inheritance) { 11784e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner case attr::SingleInheritance: // Same as multiple inheritance. 11884e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner case attr::MultipleInheritance: Width = 1 * IntSize; break; 11984e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner case attr::VirtualInheritance: Width = 2 * IntSize; break; 12084e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner case attr::UnspecifiedInheritance: Width = 3 * IntSize; break; 12184e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner default: llvm_unreachable("unknown inheritance model"); 12284e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner } 12384e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner } 12484e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner Width = llvm::RoundUpToAlignment(Width, Align); 12584e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner 12684e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner // FIXME: Verify that our alignment matches MSVC. 12784e9ab44af3a16f66d62590505db2036ef0aa03bReid Kleckner return std::make_pair(Width, Align); 128071cc7deffad608165b1ddd5263e8bf181861520Charles Davis} 129071cc7deffad608165b1ddd5263e8bf181861520Charles Davis 130071cc7deffad608165b1ddd5263e8bf181861520Charles DavisCXXABI *clang::CreateMicrosoftCXXABI(ASTContext &Ctx) { 131071cc7deffad608165b1ddd5263e8bf181861520Charles Davis return new MicrosoftCXXABI(Ctx); 132071cc7deffad608165b1ddd5263e8bf181861520Charles Davis} 133071cc7deffad608165b1ddd5263e8bf181861520Charles Davis 134