aboutsummaryrefslogtreecommitdiff
path: root/lib/AST/Mangle.cpp
blob: c3f3b11caccfc9830f9f8b16ffc31c0eaeee5453 (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
134
135
136
137
138
139
140
//===--- Mangle.cpp - Mangle C++ Names --------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Implements generic name mangling support for blocks and Objective-C.
//
//===----------------------------------------------------------------------===//
#include "clang/AST/Mangle.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/ExprCXX.h"
#include "clang/Basic/ABI.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/ErrorHandling.h"

#define MANGLE_CHECKER 0

#if MANGLE_CHECKER
#include <cxxabi.h>
#endif

using namespace clang;

// FIXME: For blocks we currently mimic GCC's mangling scheme, which leaves
// much to be desired. Come up with a better mangling scheme.

namespace {

static void mangleFunctionBlock(MangleContext &Context,
                                llvm::StringRef Outer,
                                const BlockDecl *BD,
                                llvm::raw_ostream &Out) {
  Out << "__" << Outer << "_block_invoke_" << Context.getBlockId(BD, true);
}

static void checkMangleDC(const DeclContext *DC, const BlockDecl *BD) {
#ifndef NDEBUG
  const DeclContext *ExpectedDC = BD->getDeclContext();
  while (isa<BlockDecl>(ExpectedDC) || isa<EnumDecl>(ExpectedDC))
    ExpectedDC = ExpectedDC->getParent();
  // In-class initializers for non-static data members are lexically defined
  // within the class, but are mangled as if they were specified as constructor
  // member initializers.
  if (isa<CXXRecordDecl>(ExpectedDC) && DC != ExpectedDC)
    DC = DC->getParent();
  assert(DC == ExpectedDC && "Given decl context did not match expected!");
#endif
}

}

void MangleContext::mangleGlobalBlock(const BlockDecl *BD,
                                      llvm::raw_ostream &Out) {
  Out << "__block_global_" << getBlockId(BD, false);
}

void MangleContext::mangleCtorBlock(const CXXConstructorDecl *CD,
                                    CXXCtorType CT, const BlockDecl *BD,
                                    llvm::raw_ostream &ResStream) {
  checkMangleDC(CD, BD);
  llvm::SmallString<64> Buffer;
  llvm::raw_svector_ostream Out(Buffer);
  mangleCXXCtor(CD, CT, Out);
  Out.flush();
  mangleFunctionBlock(*this, Buffer, BD, ResStream);
}

void MangleContext::mangleDtorBlock(const CXXDestructorDecl *DD,
                                    CXXDtorType DT, const BlockDecl *BD,
                                    llvm::raw_ostream &ResStream) {
  checkMangleDC(DD, BD);
  llvm::SmallString<64> Buffer;
  llvm::raw_svector_ostream Out(Buffer);
  mangleCXXDtor(DD, DT, Out);
  Out.flush();
  mangleFunctionBlock(*this, Buffer, BD, ResStream);
}

void MangleContext::mangleBlock(const DeclContext *DC, const BlockDecl *BD,
                                llvm::raw_ostream &Out) {
  assert(!isa<CXXConstructorDecl>(DC) && !isa<CXXDestructorDecl>(DC));
  checkMangleDC(DC, BD);

  llvm::SmallString<64> Buffer;
  llvm::raw_svector_ostream Stream(Buffer);
  if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) {
    mangleObjCMethodName(Method, Stream);
  } else {
    const NamedDecl *ND = cast<NamedDecl>(DC);
    if (IdentifierInfo *II = ND->getIdentifier())
      Stream << II->getName();
    else {
      // FIXME: We were doing a mangleUnqualifiedName() before, but that's
      // a private member of a class that will soon itself be private to the
      // Itanium C++ ABI object. What should we do now? Right now, I'm just
      // calling the mangleName() method on the MangleContext; is there a
      // better way?
      mangleName(ND, Stream);
    }
  }
  Stream.flush();
  mangleFunctionBlock(*this, Buffer, BD, Out);
}

void MangleContext::mangleObjCMethodName(const ObjCMethodDecl *MD,
                                         llvm::raw_ostream &Out) {
  llvm::SmallString<64> Name;
  llvm::raw_svector_ostream OS(Name);
  
  const ObjCContainerDecl *CD =
  dyn_cast<ObjCContainerDecl>(MD->getDeclContext());
  assert (CD && "Missing container decl in GetNameForMethod");
  OS << (MD->isInstanceMethod() ? '-' : '+') << '[' << CD->getName();
  if (const ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(CD))
    OS << '(' << CID << ')';
  OS << ' ' << MD->getSelector().getAsString() << ']';
  
  Out << OS.str().size() << OS.str();
}

void MangleContext::mangleBlock(const BlockDecl *BD,
                                llvm::raw_ostream &Out) {
  const DeclContext *DC = BD->getDeclContext();
  while (isa<BlockDecl>(DC) || isa<EnumDecl>(DC))
    DC = DC->getParent();
  if (DC->isFunctionOrMethod())
    mangleBlock(DC, BD, Out);
  else
    mangleGlobalBlock(BD, Out);
}