Coverage Report

Created: 2021-08-24 07:12

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/AST/MicrosoftCXXABI.cpp
Line
Count
Source (jump to first uncovered line)
1
//===------- MicrosoftCXXABI.cpp - AST support for the Microsoft C++ ABI --===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This provides C++ AST support targeting the Microsoft Visual C++
10
// ABI.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "CXXABI.h"
15
#include "clang/AST/ASTContext.h"
16
#include "clang/AST/Attr.h"
17
#include "clang/AST/CXXInheritance.h"
18
#include "clang/AST/DeclCXX.h"
19
#include "clang/AST/Mangle.h"
20
#include "clang/AST/MangleNumberingContext.h"
21
#include "clang/AST/RecordLayout.h"
22
#include "clang/AST/Type.h"
23
#include "clang/Basic/TargetInfo.h"
24
25
using namespace clang;
26
27
namespace {
28
29
/// Numbers things which need to correspond across multiple TUs.
30
/// Typically these are things like static locals, lambdas, or blocks.
31
class MicrosoftNumberingContext : public MangleNumberingContext {
32
  llvm::DenseMap<const Type *, unsigned> ManglingNumbers;
33
  unsigned LambdaManglingNumber;
34
  unsigned StaticLocalNumber;
35
  unsigned StaticThreadlocalNumber;
36
37
public:
38
  MicrosoftNumberingContext()
39
      : MangleNumberingContext(), LambdaManglingNumber(0),
40
2.14k
        StaticLocalNumber(0), StaticThreadlocalNumber(0) {}
41
42
1.64k
  unsigned getManglingNumber(const CXXMethodDecl *CallOperator) override {
43
1.64k
    return ++LambdaManglingNumber;
44
1.64k
  }
45
46
24
  unsigned getManglingNumber(const BlockDecl *BD) override {
47
24
    const Type *Ty = nullptr;
48
24
    return ++ManglingNumbers[Ty];
49
24
  }
50
51
111
  unsigned getStaticLocalNumber(const VarDecl *VD) override {
52
111
    if (VD->getTLSKind())
53
11
      return ++StaticThreadlocalNumber;
54
100
    return ++StaticLocalNumber;
55
111
  }
56
57
  unsigned getManglingNumber(const VarDecl *VD,
58
111
                             unsigned MSLocalManglingNumber) override {
59
111
    return MSLocalManglingNumber;
60
111
  }
61
62
  unsigned getManglingNumber(const TagDecl *TD,
63
495
                             unsigned MSLocalManglingNumber) override {
64
495
    return MSLocalManglingNumber;
65
495
  }
66
};
67
68
class MSHIPNumberingContext : public MicrosoftNumberingContext {
69
  std::unique_ptr<MangleNumberingContext> DeviceCtx;
70
71
public:
72
5
  MSHIPNumberingContext(MangleContext *DeviceMangler) {
73
5
    DeviceCtx = createItaniumNumberingContext(DeviceMangler);
74
5
  }
75
76
8
  unsigned getDeviceManglingNumber(const CXXMethodDecl *CallOperator) override {
77
8
    return DeviceCtx->getManglingNumber(CallOperator);
78
8
  }
79
};
80
81
class MicrosoftCXXABI : public CXXABI {
82
  ASTContext &Context;
83
  llvm::SmallDenseMap<CXXRecordDecl *, CXXConstructorDecl *> RecordToCopyCtor;
84
85
  llvm::SmallDenseMap<TagDecl *, DeclaratorDecl *>
86
      UnnamedTagDeclToDeclaratorDecl;
87
  llvm::SmallDenseMap<TagDecl *, TypedefNameDecl *>
88
      UnnamedTagDeclToTypedefNameDecl;
89
90
  // MangleContext for device numbering context, which is based on Itanium C++
91
  // ABI.
92
  std::unique_ptr<MangleContext> DeviceMangler;
93
94
public:
95
7.04k
  MicrosoftCXXABI(ASTContext &Ctx) : Context(Ctx) {
96
7.04k
    if (Context.getLangOpts().CUDA && 
Context.getAuxTargetInfo()6
) {
97
4
      assert(Context.getTargetInfo().getCXXABI().isMicrosoft() &&
98
4
             Context.getAuxTargetInfo()->getCXXABI().isItaniumFamily() &&
99
4
             "Unexpected combination of C++ ABIs.");
100
0
      DeviceMangler.reset(
101
4
          Context.createMangleContext(Context.getAuxTargetInfo()));
102
4
    }
103
7.04k
  }
104
105
  MemberPointerInfo
106
  getMemberPointerInfo(const MemberPointerType *MPT) const override;
107
108
46.8k
  CallingConv getDefaultMethodCallConv(bool isVariadic) const override {
109
46.8k
    if (!isVariadic &&
110
46.8k
        
Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x8646.7k
)
111
26.0k
      return CC_X86ThisCall;
112
20.8k
    return Context.getTargetInfo().getDefaultCallingConv();
113
46.8k
  }
114
115
0
  bool isNearlyEmpty(const CXXRecordDecl *RD) const override {
116
0
    llvm_unreachable("unapplicable to the MS ABI");
117
0
  }
118
119
  const CXXConstructorDecl *
120
50
  getCopyConstructorForExceptionObject(CXXRecordDecl *RD) override {
121
50
    return RecordToCopyCtor[RD];
122
50
  }
123
124
  void
125
  addCopyConstructorForExceptionObject(CXXRecordDecl *RD,
126
20
                                       CXXConstructorDecl *CD) override {
127
20
    assert(CD != nullptr);
128
0
    assert(RecordToCopyCtor[RD] == nullptr || RecordToCopyCtor[RD] == CD);
129
0
    RecordToCopyCtor[RD] = CD;
130
20
  }
131
132
  void addTypedefNameForUnnamedTagDecl(TagDecl *TD,
133
10
                                       TypedefNameDecl *DD) override {
134
10
    TD = TD->getCanonicalDecl();
135
10
    DD = DD->getCanonicalDecl();
136
10
    TypedefNameDecl *&I = UnnamedTagDeclToTypedefNameDecl[TD];
137
10
    if (!I)
138
10
      I = DD;
139
10
  }
140
141
2.15k
  TypedefNameDecl *getTypedefNameForUnnamedTagDecl(const TagDecl *TD) override {
142
2.15k
    return UnnamedTagDeclToTypedefNameDecl.lookup(
143
2.15k
        const_cast<TagDecl *>(TD->getCanonicalDecl()));
144
2.15k
  }
145
146
  void addDeclaratorForUnnamedTagDecl(TagDecl *TD,
147
93
                                      DeclaratorDecl *DD) override {
148
93
    TD = TD->getCanonicalDecl();
149
93
    DD = cast<DeclaratorDecl>(DD->getCanonicalDecl());
150
93
    DeclaratorDecl *&I = UnnamedTagDeclToDeclaratorDecl[TD];
151
93
    if (!I)
152
93
      I = DD;
153
93
  }
154
155
2.23k
  DeclaratorDecl *getDeclaratorForUnnamedTagDecl(const TagDecl *TD) override {
156
2.23k
    return UnnamedTagDeclToDeclaratorDecl.lookup(
157
2.23k
        const_cast<TagDecl *>(TD->getCanonicalDecl()));
158
2.23k
  }
159
160
  std::unique_ptr<MangleNumberingContext>
161
2.14k
  createMangleNumberingContext() const override {
162
2.14k
    if (Context.getLangOpts().CUDA && 
Context.getAuxTargetInfo()5
) {
163
5
      assert(DeviceMangler && "Missing device mangler");
164
0
      return std::make_unique<MSHIPNumberingContext>(DeviceMangler.get());
165
5
    }
166
2.13k
    return std::make_unique<MicrosoftNumberingContext>();
167
2.14k
  }
168
};
169
}
170
171
// getNumBases() seems to only give us the number of direct bases, and not the
172
// total.  This function tells us if we inherit from anybody that uses MI, or if
173
// we have a non-primary base class, which uses the multiple inheritance model.
174
537
static bool usesMultipleInheritanceModel(const CXXRecordDecl *RD) {
175
631
  while (RD->getNumBases() > 0) {
176
122
    if (RD->getNumBases() > 1)
177
20
      return true;
178
102
    assert(RD->getNumBases() == 1);
179
0
    const CXXRecordDecl *Base =
180
102
        RD->bases_begin()->getType()->getAsCXXRecordDecl();
181
102
    if (RD->isPolymorphic() && 
!Base->isPolymorphic()15
)
182
8
      return true;
183
94
    RD = Base;
184
94
  }
185
509
  return false;
186
537
}
187
188
638
MSInheritanceModel CXXRecordDecl::calculateInheritanceModel() const {
189
638
  if (!hasDefinition() || 
isParsingBaseSpecifiers()570
)
190
70
    return MSInheritanceModel::Unspecified;
191
568
  if (getNumVBases() > 0)
192
31
    return MSInheritanceModel::Virtual;
193
537
  if (usesMultipleInheritanceModel(this))
194
28
    return MSInheritanceModel::Multiple;
195
509
  return MSInheritanceModel::Single;
196
537
}
197
198
2.70k
MSInheritanceModel CXXRecordDecl::getMSInheritanceModel() const {
199
2.70k
  MSInheritanceAttr *IA = getAttr<MSInheritanceAttr>();
200
2.70k
  assert(IA && "Expected MSInheritanceAttr on the CXXRecordDecl!");
201
0
  return IA->getInheritanceModel();
202
2.70k
}
203
204
146
bool CXXRecordDecl::nullFieldOffsetIsZero() const {
205
146
  return !inheritanceModelHasOnlyOneField(/*IsMemberFunction=*/false,
206
146
                                          getMSInheritanceModel()) ||
207
146
         
(102
hasDefinition()102
&&
isPolymorphic()100
);
208
146
}
209
210
1.71k
MSVtorDispMode CXXRecordDecl::getMSVtorDispMode() const {
211
1.71k
  if (MSVtorDispAttr *VDA = getAttr<MSVtorDispAttr>())
212
26
    return VDA->getVtorDispMode();
213
1.68k
  return getASTContext().getLangOpts().getVtorDispMode();
214
1.71k
}
215
216
// Returns the number of pointer and integer slots used to represent a member
217
// pointer in the MS C++ ABI.
218
//
219
// Member function pointers have the following general form;  however, fields
220
// are dropped as permitted (under the MSVC interpretation) by the inheritance
221
// model of the actual class.
222
//
223
//   struct {
224
//     // A pointer to the member function to call.  If the member function is
225
//     // virtual, this will be a thunk that forwards to the appropriate vftable
226
//     // slot.
227
//     void *FunctionPointerOrVirtualThunk;
228
//
229
//     // An offset to add to the address of the vbtable pointer after
230
//     // (possibly) selecting the virtual base but before resolving and calling
231
//     // the function.
232
//     // Only needed if the class has any virtual bases or bases at a non-zero
233
//     // offset.
234
//     int NonVirtualBaseAdjustment;
235
//
236
//     // The offset of the vb-table pointer within the object.  Only needed for
237
//     // incomplete types.
238
//     int VBPtrOffset;
239
//
240
//     // An offset within the vb-table that selects the virtual base containing
241
//     // the member.  Loading from this offset produces a new offset that is
242
//     // added to the address of the vb-table pointer to produce the base.
243
//     int VirtualBaseAdjustmentOffset;
244
//   };
245
static std::pair<unsigned, unsigned>
246
858
getMSMemberPointerSlots(const MemberPointerType *MPT) {
247
858
  const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
248
858
  MSInheritanceModel Inheritance = RD->getMSInheritanceModel();
249
858
  unsigned Ptrs = 0;
250
858
  unsigned Ints = 0;
251
858
  if (MPT->isMemberFunctionPointer())
252
681
    Ptrs = 1;
253
177
  else
254
177
    Ints = 1;
255
858
  if (inheritanceModelHasNVOffsetField(MPT->isMemberFunctionPointer(),
256
858
                                          Inheritance))
257
140
    Ints++;
258
858
  if (inheritanceModelHasVBPtrOffsetField(Inheritance))
259
159
    Ints++;
260
858
  if (inheritanceModelHasVBTableOffsetField(Inheritance))
261
208
    Ints++;
262
858
  return std::make_pair(Ptrs, Ints);
263
858
}
264
265
CXXABI::MemberPointerInfo MicrosoftCXXABI::getMemberPointerInfo(
266
858
    const MemberPointerType *MPT) const {
267
  // The nominal struct is laid out with pointers followed by ints and aligned
268
  // to a pointer width if any are present and an int width otherwise.
269
858
  const TargetInfo &Target = Context.getTargetInfo();
270
858
  unsigned PtrSize = Target.getPointerWidth(0);
271
858
  unsigned IntSize = Target.getIntWidth();
272
273
858
  unsigned Ptrs, Ints;
274
858
  std::tie(Ptrs, Ints) = getMSMemberPointerSlots(MPT);
275
858
  MemberPointerInfo MPI;
276
858
  MPI.HasPadding = false;
277
858
  MPI.Width = Ptrs * PtrSize + Ints * IntSize;
278
279
  // When MSVC does x86_32 record layout, it aligns aggregate member pointers to
280
  // 8 bytes.  However, __alignof usually returns 4 for data memptrs and 8 for
281
  // function memptrs.
282
858
  if (Ptrs + Ints > 1 && 
Target.getTriple().isArch32Bit()230
)
283
102
    MPI.Align = 64;
284
756
  else if (Ptrs)
285
616
    MPI.Align = Target.getPointerAlign(0);
286
140
  else
287
140
    MPI.Align = Target.getIntAlign();
288
289
858
  if (Target.getTriple().isArch64Bit()) {
290
361
    MPI.Width = llvm::alignTo(MPI.Width, MPI.Align);
291
361
    MPI.HasPadding = MPI.Width != (Ptrs * PtrSize + Ints * IntSize);
292
361
  }
293
858
  return MPI;
294
858
}
295
296
7.04k
CXXABI *clang::CreateMicrosoftCXXABI(ASTContext &Ctx) {
297
7.04k
  return new MicrosoftCXXABI(Ctx);
298
7.04k
}