Coverage Report

Created: 2023-05-31 04:38

/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
      : LambdaManglingNumber(0), StaticLocalNumber(0),
40
2.20k
        StaticThreadlocalNumber(0) {}
41
42
1.67k
  unsigned getManglingNumber(const CXXMethodDecl *CallOperator) override {
43
1.67k
    return ++LambdaManglingNumber;
44
1.67k
  }
45
46
25
  unsigned getManglingNumber(const BlockDecl *BD) override {
47
25
    const Type *Ty = nullptr;
48
25
    return ++ManglingNumbers[Ty];
49
25
  }
50
51
113
  unsigned getStaticLocalNumber(const VarDecl *VD) override {
52
113
    if (VD->getTLSKind())
53
11
      return ++StaticThreadlocalNumber;
54
102
    return ++StaticLocalNumber;
55
113
  }
56
57
  unsigned getManglingNumber(const VarDecl *VD,
58
113
                             unsigned MSLocalManglingNumber) override {
59
113
    return MSLocalManglingNumber;
60
113
  }
61
62
  unsigned getManglingNumber(const TagDecl *TD,
63
542
                             unsigned MSLocalManglingNumber) override {
64
542
    return MSLocalManglingNumber;
65
542
  }
66
};
67
68
class MSHIPNumberingContext : public MicrosoftNumberingContext {
69
  std::unique_ptr<MangleNumberingContext> DeviceCtx;
70
71
public:
72
  using MicrosoftNumberingContext::getManglingNumber;
73
7
  MSHIPNumberingContext(MangleContext *DeviceMangler) {
74
7
    DeviceCtx = createItaniumNumberingContext(DeviceMangler);
75
7
  }
76
77
8
  unsigned getDeviceManglingNumber(const CXXMethodDecl *CallOperator) override {
78
8
    return DeviceCtx->getManglingNumber(CallOperator);
79
8
  }
80
81
  unsigned getManglingNumber(const TagDecl *TD,
82
2
                             unsigned MSLocalManglingNumber) override {
83
2
    unsigned DeviceN = DeviceCtx->getManglingNumber(TD, MSLocalManglingNumber);
84
2
    unsigned HostN =
85
2
        MicrosoftNumberingContext::getManglingNumber(TD, MSLocalManglingNumber);
86
2
    if (DeviceN > 0xFFFF || HostN > 0xFFFF) {
87
0
      DiagnosticsEngine &Diags = TD->getASTContext().getDiagnostics();
88
0
      unsigned DiagID = Diags.getCustomDiagID(
89
0
          DiagnosticsEngine::Error, "Mangling number exceeds limit (65535)");
90
0
      Diags.Report(TD->getLocation(), DiagID);
91
0
    }
92
2
    return (DeviceN << 16) | HostN;
93
2
  }
94
};
95
96
class MSSYCLNumberingContext : public MicrosoftNumberingContext {
97
  std::unique_ptr<MangleNumberingContext> DeviceCtx;
98
99
public:
100
9
  MSSYCLNumberingContext(MangleContext *DeviceMangler) {
101
9
    DeviceCtx = createItaniumNumberingContext(DeviceMangler);
102
9
  }
103
104
22
  unsigned getDeviceManglingNumber(const CXXMethodDecl *CallOperator) override {
105
22
    return DeviceCtx->getManglingNumber(CallOperator);
106
22
  }
107
};
108
109
class MicrosoftCXXABI : public CXXABI {
110
  ASTContext &Context;
111
  llvm::SmallDenseMap<CXXRecordDecl *, CXXConstructorDecl *> RecordToCopyCtor;
112
113
  llvm::SmallDenseMap<TagDecl *, DeclaratorDecl *>
114
      UnnamedTagDeclToDeclaratorDecl;
115
  llvm::SmallDenseMap<TagDecl *, TypedefNameDecl *>
116
      UnnamedTagDeclToTypedefNameDecl;
117
118
  // MangleContext for device numbering context, which is based on Itanium C++
119
  // ABI.
120
  std::unique_ptr<MangleContext> DeviceMangler;
121
122
public:
123
7.58k
  MicrosoftCXXABI(ASTContext &Ctx) : Context(Ctx) {
124
7.58k
    if (Context.getLangOpts().CUDA && 
Context.getAuxTargetInfo()11
) {
125
9
      assert(Context.getTargetInfo().getCXXABI().isMicrosoft() &&
126
9
             Context.getAuxTargetInfo()->getCXXABI().isItaniumFamily() &&
127
9
             "Unexpected combination of C++ ABIs.");
128
9
      DeviceMangler.reset(
129
9
          Context.createMangleContext(Context.getAuxTargetInfo()));
130
9
    }
131
7.57k
    else if (Context.getLangOpts().isSYCL()) {
132
2
      DeviceMangler.reset(
133
2
          ItaniumMangleContext::create(Context, Context.getDiagnostics()));
134
2
    }
135
7.58k
  }
136
137
  MemberPointerInfo
138
  getMemberPointerInfo(const MemberPointerType *MPT) const override;
139
140
48.2k
  CallingConv getDefaultMethodCallConv(bool isVariadic) const override {
141
48.2k
    if (!isVariadic &&
142
48.2k
        
Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x8648.1k
)
143
26.2k
      return CC_X86ThisCall;
144
22.0k
    return Context.getTargetInfo().getDefaultCallingConv();
145
48.2k
  }
146
147
0
  bool isNearlyEmpty(const CXXRecordDecl *RD) const override {
148
0
    llvm_unreachable("unapplicable to the MS ABI");
149
0
  }
150
151
  const CXXConstructorDecl *
152
31
  getCopyConstructorForExceptionObject(CXXRecordDecl *RD) override {
153
31
    return RecordToCopyCtor[RD];
154
31
  }
155
156
  void
157
  addCopyConstructorForExceptionObject(CXXRecordDecl *RD,
158
15
                                       CXXConstructorDecl *CD) override {
159
15
    assert(CD != nullptr);
160
15
    assert(RecordToCopyCtor[RD] == nullptr || RecordToCopyCtor[RD] == CD);
161
15
    RecordToCopyCtor[RD] = CD;
162
15
  }
163
164
  void addTypedefNameForUnnamedTagDecl(TagDecl *TD,
165
10
                                       TypedefNameDecl *DD) override {
166
10
    TD = TD->getCanonicalDecl();
167
10
    DD = DD->getCanonicalDecl();
168
10
    TypedefNameDecl *&I = UnnamedTagDeclToTypedefNameDecl[TD];
169
10
    if (!I)
170
10
      I = DD;
171
10
  }
172
173
2.26k
  TypedefNameDecl *getTypedefNameForUnnamedTagDecl(const TagDecl *TD) override {
174
2.26k
    return UnnamedTagDeclToTypedefNameDecl.lookup(
175
2.26k
        const_cast<TagDecl *>(TD->getCanonicalDecl()));
176
2.26k
  }
177
178
  void addDeclaratorForUnnamedTagDecl(TagDecl *TD,
179
95
                                      DeclaratorDecl *DD) override {
180
95
    TD = TD->getCanonicalDecl();
181
95
    DD = cast<DeclaratorDecl>(DD->getCanonicalDecl());
182
95
    DeclaratorDecl *&I = UnnamedTagDeclToDeclaratorDecl[TD];
183
95
    if (!I)
184
95
      I = DD;
185
95
  }
186
187
2.35k
  DeclaratorDecl *getDeclaratorForUnnamedTagDecl(const TagDecl *TD) override {
188
2.35k
    return UnnamedTagDeclToDeclaratorDecl.lookup(
189
2.35k
        const_cast<TagDecl *>(TD->getCanonicalDecl()));
190
2.35k
  }
191
192
  std::unique_ptr<MangleNumberingContext>
193
2.20k
  createMangleNumberingContext() const override {
194
2.20k
    if (Context.getLangOpts().CUDA && 
Context.getAuxTargetInfo()7
) {
195
7
      assert(DeviceMangler && "Missing device mangler");
196
7
      return std::make_unique<MSHIPNumberingContext>(DeviceMangler.get());
197
2.20k
    } else if (Context.getLangOpts().isSYCL()) {
198
9
      assert(DeviceMangler && "Missing device mangler");
199
9
      return std::make_unique<MSSYCLNumberingContext>(DeviceMangler.get());
200
9
    }
201
202
2.19k
    return std::make_unique<MicrosoftNumberingContext>();
203
2.20k
  }
204
};
205
}
206
207
// getNumBases() seems to only give us the number of direct bases, and not the
208
// total.  This function tells us if we inherit from anybody that uses MI, or if
209
// we have a non-primary base class, which uses the multiple inheritance model.
210
550
static bool usesMultipleInheritanceModel(const CXXRecordDecl *RD) {
211
644
  while (RD->getNumBases() > 0) {
212
124
    if (RD->getNumBases() > 1)
213
22
      return true;
214
102
    assert(RD->getNumBases() == 1);
215
102
    const CXXRecordDecl *Base =
216
102
        RD->bases_begin()->getType()->getAsCXXRecordDecl();
217
102
    if (RD->isPolymorphic() && 
!Base->isPolymorphic()15
)
218
8
      return true;
219
94
    RD = Base;
220
94
  }
221
520
  return false;
222
550
}
223
224
656
MSInheritanceModel CXXRecordDecl::calculateInheritanceModel() const {
225
656
  if (!hasDefinition() || 
isParsingBaseSpecifiers()586
)
226
72
    return MSInheritanceModel::Unspecified;
227
584
  if (getNumVBases() > 0)
228
34
    return MSInheritanceModel::Virtual;
229
550
  if (usesMultipleInheritanceModel(this))
230
30
    return MSInheritanceModel::Multiple;
231
520
  return MSInheritanceModel::Single;
232
550
}
233
234
3.02k
MSInheritanceModel CXXRecordDecl::getMSInheritanceModel() const {
235
3.02k
  MSInheritanceAttr *IA = getAttr<MSInheritanceAttr>();
236
3.02k
  assert(IA && "Expected MSInheritanceAttr on the CXXRecordDecl!");
237
3.02k
  return IA->getInheritanceModel();
238
3.02k
}
239
240
146
bool CXXRecordDecl::nullFieldOffsetIsZero() const {
241
146
  return !inheritanceModelHasOnlyOneField(/*IsMemberFunction=*/false,
242
146
                                          getMSInheritanceModel()) ||
243
146
         
(100
hasDefinition()100
&&
isPolymorphic()98
);
244
146
}
245
246
1.72k
MSVtorDispMode CXXRecordDecl::getMSVtorDispMode() const {
247
1.72k
  if (MSVtorDispAttr *VDA = getAttr<MSVtorDispAttr>())
248
26
    return VDA->getVtorDispMode();
249
1.69k
  return getASTContext().getLangOpts().getVtorDispMode();
250
1.72k
}
251
252
// Returns the number of pointer and integer slots used to represent a member
253
// pointer in the MS C++ ABI.
254
//
255
// Member function pointers have the following general form;  however, fields
256
// are dropped as permitted (under the MSVC interpretation) by the inheritance
257
// model of the actual class.
258
//
259
//   struct {
260
//     // A pointer to the member function to call.  If the member function is
261
//     // virtual, this will be a thunk that forwards to the appropriate vftable
262
//     // slot.
263
//     void *FunctionPointerOrVirtualThunk;
264
//
265
//     // An offset to add to the address of the vbtable pointer after
266
//     // (possibly) selecting the virtual base but before resolving and calling
267
//     // the function.
268
//     // Only needed if the class has any virtual bases or bases at a non-zero
269
//     // offset.
270
//     int NonVirtualBaseAdjustment;
271
//
272
//     // The offset of the vb-table pointer within the object.  Only needed for
273
//     // incomplete types.
274
//     int VBPtrOffset;
275
//
276
//     // An offset within the vb-table that selects the virtual base containing
277
//     // the member.  Loading from this offset produces a new offset that is
278
//     // added to the address of the vb-table pointer to produce the base.
279
//     int VirtualBaseAdjustmentOffset;
280
//   };
281
static std::pair<unsigned, unsigned>
282
865
getMSMemberPointerSlots(const MemberPointerType *MPT) {
283
865
  const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
284
865
  MSInheritanceModel Inheritance = RD->getMSInheritanceModel();
285
865
  unsigned Ptrs = 0;
286
865
  unsigned Ints = 0;
287
865
  if (MPT->isMemberFunctionPointer())
288
686
    Ptrs = 1;
289
179
  else
290
179
    Ints = 1;
291
865
  if (inheritanceModelHasNVOffsetField(MPT->isMemberFunctionPointer(),
292
865
                                          Inheritance))
293
142
    Ints++;
294
865
  if (inheritanceModelHasVBPtrOffsetField(Inheritance))
295
161
    Ints++;
296
865
  if (inheritanceModelHasVBTableOffsetField(Inheritance))
297
211
    Ints++;
298
865
  return std::make_pair(Ptrs, Ints);
299
865
}
300
301
CXXABI::MemberPointerInfo MicrosoftCXXABI::getMemberPointerInfo(
302
865
    const MemberPointerType *MPT) const {
303
  // The nominal struct is laid out with pointers followed by ints and aligned
304
  // to a pointer width if any are present and an int width otherwise.
305
865
  const TargetInfo &Target = Context.getTargetInfo();
306
865
  unsigned PtrSize = Target.getPointerWidth(LangAS::Default);
307
865
  unsigned IntSize = Target.getIntWidth();
308
309
865
  unsigned Ptrs, Ints;
310
865
  std::tie(Ptrs, Ints) = getMSMemberPointerSlots(MPT);
311
865
  MemberPointerInfo MPI;
312
865
  MPI.HasPadding = false;
313
865
  MPI.Width = Ptrs * PtrSize + Ints * IntSize;
314
315
  // When MSVC does x86_32 record layout, it aligns aggregate member pointers to
316
  // 8 bytes.  However, __alignof usually returns 4 for data memptrs and 8 for
317
  // function memptrs.
318
865
  if (Ptrs + Ints > 1 && 
Target.getTriple().isArch32Bit()234
)
319
102
    MPI.Align = 64;
320
763
  else if (Ptrs)
321
621
    MPI.Align = Target.getPointerAlign(LangAS::Default);
322
142
  else
323
142
    MPI.Align = Target.getIntAlign();
324
325
865
  if (Target.getTriple().isArch64Bit()) {
326
367
    MPI.Width = llvm::alignTo(MPI.Width, MPI.Align);
327
367
    MPI.HasPadding = MPI.Width != (Ptrs * PtrSize + Ints * IntSize);
328
367
  }
329
865
  return MPI;
330
865
}
331
332
7.58k
CXXABI *clang::CreateMicrosoftCXXABI(ASTContext &Ctx) {
333
7.58k
  return new MicrosoftCXXABI(Ctx);
334
7.58k
}