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