Coverage Report

Created: 2020-02-25 14:32

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/AST/Interp/Descriptor.cpp
Line
Count
Source (jump to first uncovered line)
1
//===--- Descriptor.cpp - Types for the constexpr VM ------------*- C++ -*-===//
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
#include "Descriptor.h"
10
#include "Pointer.h"
11
#include "PrimType.h"
12
#include "Record.h"
13
14
using namespace clang;
15
using namespace clang::interp;
16
17
template <typename T>
18
0
static void ctorTy(Block *, char *Ptr, bool, bool, bool, Descriptor *) {
19
0
  new (Ptr) T();
20
0
}
21
22
0
template <typename T> static void dtorTy(Block *, char *Ptr, Descriptor *) {
23
0
  reinterpret_cast<T *>(Ptr)->~T();
24
0
}
25
26
template <typename T>
27
0
static void moveTy(Block *, char *Src, char *Dst, Descriptor *) {
28
0
  auto *SrcPtr = reinterpret_cast<T *>(Src);
29
0
  auto *DstPtr = reinterpret_cast<T *>(Dst);
30
0
  new (DstPtr) T(std::move(*SrcPtr));
31
0
}
32
33
template <typename T>
34
0
static void ctorArrayTy(Block *, char *Ptr, bool, bool, bool, Descriptor *D) {
35
0
  for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) {
36
0
    new (&reinterpret_cast<T *>(Ptr)[I]) T();
37
0
  }
38
0
}
39
40
template <typename T>
41
0
static void dtorArrayTy(Block *, char *Ptr, Descriptor *D) {
42
0
  for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) {
43
0
    reinterpret_cast<T *>(Ptr)[I].~T();
44
0
  }
45
0
}
46
47
template <typename T>
48
0
static void moveArrayTy(Block *, char *Src, char *Dst, Descriptor *D) {
49
0
  for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) {
50
0
    auto *SrcPtr = &reinterpret_cast<T *>(Src)[I];
51
0
    auto *DstPtr = &reinterpret_cast<T *>(Dst)[I];
52
0
    new (DstPtr) T(std::move(*SrcPtr));
53
0
  }
54
0
}
55
56
static void ctorArrayDesc(Block *B, char *Ptr, bool IsConst, bool IsMutable,
57
0
                          bool IsActive, Descriptor *D) {
58
0
  const unsigned NumElems = D->getNumElems();
59
0
  const unsigned ElemSize =
60
0
      D->ElemDesc->getAllocSize() + sizeof(InlineDescriptor);
61
0
62
0
  unsigned ElemOffset = 0;
63
0
  for (unsigned I = 0; I < NumElems; ++I, ElemOffset += ElemSize) {
64
0
    auto *ElemPtr = Ptr + ElemOffset;
65
0
    auto *Desc = reinterpret_cast<InlineDescriptor *>(ElemPtr);
66
0
    auto *ElemLoc = reinterpret_cast<char *>(Desc + 1);
67
0
    auto *SD = D->ElemDesc;
68
0
69
0
    Desc->Offset = ElemOffset + sizeof(InlineDescriptor);
70
0
    Desc->Desc = SD;
71
0
    Desc->IsInitialized = true;
72
0
    Desc->IsBase = false;
73
0
    Desc->IsActive = IsActive;
74
0
    Desc->IsConst = IsConst || D->IsConst;
75
0
    Desc->IsMutable = IsMutable || D->IsMutable;
76
0
    if (auto Fn = D->ElemDesc->CtorFn)
77
0
      Fn(B, ElemLoc, Desc->IsConst, Desc->IsMutable, IsActive, D->ElemDesc);
78
0
  }
79
0
}
80
81
0
static void dtorArrayDesc(Block *B, char *Ptr, Descriptor *D) {
82
0
  const unsigned NumElems = D->getNumElems();
83
0
  const unsigned ElemSize =
84
0
      D->ElemDesc->getAllocSize() + sizeof(InlineDescriptor);
85
0
86
0
  unsigned ElemOffset = 0;
87
0
  for (unsigned I = 0; I < NumElems; ++I, ElemOffset += ElemSize) {
88
0
    auto *ElemPtr = Ptr + ElemOffset;
89
0
    auto *Desc = reinterpret_cast<InlineDescriptor *>(ElemPtr);
90
0
    auto *ElemLoc = reinterpret_cast<char *>(Desc + 1);
91
0
    if (auto Fn = D->ElemDesc->DtorFn)
92
0
      Fn(B, ElemLoc, D->ElemDesc);
93
0
  }
94
0
}
95
96
0
static void moveArrayDesc(Block *B, char *Src, char *Dst, Descriptor *D) {
97
0
  const unsigned NumElems = D->getNumElems();
98
0
  const unsigned ElemSize =
99
0
      D->ElemDesc->getAllocSize() + sizeof(InlineDescriptor);
100
0
101
0
  unsigned ElemOffset = 0;
102
0
  for (unsigned I = 0; I < NumElems; ++I, ElemOffset += ElemSize) {
103
0
    auto *SrcPtr = Src + ElemOffset;
104
0
    auto *DstPtr = Dst + ElemOffset;
105
0
106
0
    auto *SrcDesc = reinterpret_cast<InlineDescriptor *>(SrcPtr);
107
0
    auto *SrcElemLoc = reinterpret_cast<char *>(SrcDesc + 1);
108
0
    auto *DstDesc = reinterpret_cast<InlineDescriptor *>(DstPtr);
109
0
    auto *DstElemLoc = reinterpret_cast<char *>(DstDesc + 1);
110
0
111
0
    *DstDesc = *SrcDesc;
112
0
    if (auto Fn = D->ElemDesc->MoveFn)
113
0
      Fn(B, SrcElemLoc, DstElemLoc, D->ElemDesc);
114
0
  }
115
0
}
116
117
static void ctorRecord(Block *B, char *Ptr, bool IsConst, bool IsMutable,
118
0
                       bool IsActive, Descriptor *D) {
119
0
  const bool IsUnion = D->ElemRecord->isUnion();
120
0
  auto CtorSub = [=](unsigned SubOff, Descriptor *F, bool IsBase) {
121
0
    auto *Desc = reinterpret_cast<InlineDescriptor *>(Ptr + SubOff) - 1;
122
0
    Desc->Offset = SubOff;
123
0
    Desc->Desc = F;
124
0
    Desc->IsInitialized = (B->isStatic() || F->IsArray) && !IsBase;
125
0
    Desc->IsBase = IsBase;
126
0
    Desc->IsActive = IsActive && !IsUnion;
127
0
    Desc->IsConst = IsConst || F->IsConst;
128
0
    Desc->IsMutable = IsMutable || F->IsMutable;
129
0
    if (auto Fn = F->CtorFn)
130
0
      Fn(B, Ptr + SubOff, Desc->IsConst, Desc->IsMutable, Desc->IsActive, F);
131
0
  };
132
0
  for (const auto &B : D->ElemRecord->bases())
133
0
    CtorSub(B.Offset, B.Desc, /*isBase=*/true);
134
0
  for (const auto &F : D->ElemRecord->fields())
135
0
    CtorSub(F.Offset, F.Desc, /*isBase=*/false);
136
0
  for (const auto &V : D->ElemRecord->virtual_bases())
137
0
    CtorSub(V.Offset, V.Desc, /*isBase=*/true);
138
0
}
139
140
0
static void dtorRecord(Block *B, char *Ptr, Descriptor *D) {
141
0
  auto DtorSub = [=](unsigned SubOff, Descriptor *F) {
142
0
    if (auto Fn = F->DtorFn)
143
0
      Fn(B, Ptr + SubOff, F);
144
0
  };
145
0
  for (const auto &F : D->ElemRecord->bases())
146
0
    DtorSub(F.Offset, F.Desc);
147
0
  for (const auto &F : D->ElemRecord->fields())
148
0
    DtorSub(F.Offset, F.Desc);
149
0
  for (const auto &F : D->ElemRecord->virtual_bases())
150
0
    DtorSub(F.Offset, F.Desc);
151
0
}
152
153
0
static void moveRecord(Block *B, char *Src, char *Dst, Descriptor *D) {
154
0
  for (const auto &F : D->ElemRecord->fields()) {
155
0
    auto FieldOff = F.Offset;
156
0
    auto FieldDesc = F.Desc;
157
0
158
0
    *(reinterpret_cast<Descriptor **>(Dst + FieldOff) - 1) = FieldDesc;
159
0
    if (auto Fn = FieldDesc->MoveFn)
160
0
      Fn(B, Src + FieldOff, Dst + FieldOff, FieldDesc);
161
0
  }
162
0
}
163
164
2
static BlockCtorFn getCtorPrim(PrimType Type) {
165
2
  COMPOSITE_TYPE_SWITCH(Type, return ctorTy<T>, return nullptr);
166
0
}
167
168
2
static BlockDtorFn getDtorPrim(PrimType Type) {
169
2
  COMPOSITE_TYPE_SWITCH(Type, return dtorTy<T>, return nullptr);
170
0
}
171
172
2
static BlockMoveFn getMovePrim(PrimType Type) {
173
2
  COMPOSITE_TYPE_SWITCH(Type, return moveTy<T>, return nullptr);
174
0
}
175
176
0
static BlockCtorFn getCtorArrayPrim(PrimType Type) {
177
0
  COMPOSITE_TYPE_SWITCH(Type, return ctorArrayTy<T>, return nullptr);
178
0
}
179
180
0
static BlockDtorFn getDtorArrayPrim(PrimType Type) {
181
0
  COMPOSITE_TYPE_SWITCH(Type, return dtorArrayTy<T>, return nullptr);
182
0
}
183
184
0
static BlockMoveFn getMoveArrayPrim(PrimType Type) {
185
0
  COMPOSITE_TYPE_SWITCH(Type, return moveArrayTy<T>, return nullptr);
186
0
}
187
188
Descriptor::Descriptor(const DeclTy &D, PrimType Type, bool IsConst,
189
                       bool IsTemporary, bool IsMutable)
190
    : Source(D), ElemSize(primSize(Type)), Size(ElemSize), AllocSize(Size),
191
      IsConst(IsConst), IsMutable(IsMutable), IsTemporary(IsTemporary),
192
      CtorFn(getCtorPrim(Type)), DtorFn(getDtorPrim(Type)),
193
2
      MoveFn(getMovePrim(Type)) {
194
2
  assert(Source && "Missing source");
195
2
}
196
197
Descriptor::Descriptor(const DeclTy &D, PrimType Type, size_t NumElems,
198
                       bool IsConst, bool IsTemporary, bool IsMutable)
199
    : Source(D), ElemSize(primSize(Type)), Size(ElemSize * NumElems),
200
      AllocSize(align(Size) + sizeof(InitMap *)), IsConst(IsConst),
201
      IsMutable(IsMutable), IsTemporary(IsTemporary), IsArray(true),
202
      CtorFn(getCtorArrayPrim(Type)), DtorFn(getDtorArrayPrim(Type)),
203
0
      MoveFn(getMoveArrayPrim(Type)) {
204
0
  assert(Source && "Missing source");
205
0
}
206
207
Descriptor::Descriptor(const DeclTy &D, PrimType Type, bool IsTemporary,
208
                       UnknownSize)
209
    : Source(D), ElemSize(primSize(Type)), Size(UnknownSizeMark),
210
      AllocSize(alignof(void *)), IsConst(true), IsMutable(false),
211
      IsTemporary(IsTemporary), IsArray(true), CtorFn(getCtorArrayPrim(Type)),
212
0
      DtorFn(getDtorArrayPrim(Type)), MoveFn(getMoveArrayPrim(Type)) {
213
0
  assert(Source && "Missing source");
214
0
}
215
216
Descriptor::Descriptor(const DeclTy &D, Descriptor *Elem, unsigned NumElems,
217
                       bool IsConst, bool IsTemporary, bool IsMutable)
218
    : Source(D), ElemSize(Elem->getAllocSize() + sizeof(InlineDescriptor)),
219
      Size(ElemSize * NumElems),
220
      AllocSize(std::max<size_t>(alignof(void *), Size)), ElemDesc(Elem),
221
      IsConst(IsConst), IsMutable(IsMutable), IsTemporary(IsTemporary),
222
      IsArray(true), CtorFn(ctorArrayDesc), DtorFn(dtorArrayDesc),
223
0
      MoveFn(moveArrayDesc) {
224
0
  assert(Source && "Missing source");
225
0
}
226
227
Descriptor::Descriptor(const DeclTy &D, Descriptor *Elem, bool IsTemporary,
228
                       UnknownSize)
229
    : Source(D), ElemSize(Elem->getAllocSize() + sizeof(InlineDescriptor)),
230
      Size(UnknownSizeMark), AllocSize(alignof(void *)), ElemDesc(Elem),
231
      IsConst(true), IsMutable(false), IsTemporary(IsTemporary), IsArray(true),
232
0
      CtorFn(ctorArrayDesc), DtorFn(dtorArrayDesc), MoveFn(moveArrayDesc) {
233
0
  assert(Source && "Missing source");
234
0
}
235
236
Descriptor::Descriptor(const DeclTy &D, Record *R, bool IsConst,
237
                       bool IsTemporary, bool IsMutable)
238
    : Source(D), ElemSize(std::max<size_t>(alignof(void *), R->getFullSize())),
239
      Size(ElemSize), AllocSize(Size), ElemRecord(R), IsConst(IsConst),
240
      IsMutable(IsMutable), IsTemporary(IsTemporary), CtorFn(ctorRecord),
241
0
      DtorFn(dtorRecord), MoveFn(moveRecord) {
242
0
  assert(Source && "Missing source");
243
0
}
244
245
0
QualType Descriptor::getType() const {
246
0
  if (auto *E = asExpr())
247
0
    return E->getType();
248
0
  if (auto *D = asValueDecl())
249
0
    return D->getType();
250
0
  llvm_unreachable("Invalid descriptor type");
251
0
}
252
253
0
SourceLocation Descriptor::getLocation() const {
254
0
  if (auto *D = Source.dyn_cast<const Decl *>())
255
0
    return D->getLocation();
256
0
  if (auto *E = Source.dyn_cast<const Expr *>())
257
0
    return E->getExprLoc();
258
0
  llvm_unreachable("Invalid descriptor type");
259
0
}
260
261
0
InitMap::InitMap(unsigned N) : UninitFields(N) {
262
0
  for (unsigned I = 0; I < N / PER_FIELD; ++I) {
263
0
    data()[I] = 0;
264
0
  }
265
0
}
266
267
0
InitMap::T *InitMap::data() {
268
0
  auto *Start = reinterpret_cast<char *>(this) + align(sizeof(InitMap));
269
0
  return reinterpret_cast<T *>(Start);
270
0
}
271
272
0
bool InitMap::initialize(unsigned I) {
273
0
  unsigned Bucket = I / PER_FIELD;
274
0
  unsigned Mask = 1ull << static_cast<uint64_t>(I % PER_FIELD);
275
0
  if (!(data()[Bucket] & Mask)) {
276
0
    data()[Bucket] |= Mask;
277
0
    UninitFields -= 1;
278
0
  }
279
0
  return UninitFields == 0;
280
0
}
281
282
0
bool InitMap::isInitialized(unsigned I) {
283
0
  unsigned Bucket = I / PER_FIELD;
284
0
  unsigned Mask = 1ull << static_cast<uint64_t>(I % PER_FIELD);
285
0
  return data()[Bucket] & Mask;
286
0
}
287
288
0
InitMap *InitMap::allocate(unsigned N) {
289
0
  const size_t NumFields = ((N + PER_FIELD - 1) / PER_FIELD);
290
0
  const size_t Size = align(sizeof(InitMap)) + NumFields * PER_FIELD;
291
0
  return new (malloc(Size)) InitMap(N);
292
0
}