Coverage Report

Created: 2021-08-24 07:12

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/AST/Interp/Program.cpp
Line
Count
Source (jump to first uncovered line)
1
//===--- Program.cpp - Bytecode 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 "Program.h"
10
#include "ByteCodeStmtGen.h"
11
#include "Context.h"
12
#include "Function.h"
13
#include "Opcode.h"
14
#include "PrimType.h"
15
#include "clang/AST/Decl.h"
16
#include "clang/AST/DeclCXX.h"
17
18
using namespace clang;
19
using namespace clang::interp;
20
21
0
unsigned Program::getOrCreateNativePointer(const void *Ptr) {
22
0
  auto It = NativePointerIndices.find(Ptr);
23
0
  if (It != NativePointerIndices.end())
24
0
    return It->second;
25
26
0
  unsigned Idx = NativePointers.size();
27
0
  NativePointers.push_back(Ptr);
28
0
  NativePointerIndices[Ptr] = Idx;
29
0
  return Idx;
30
0
}
31
32
0
const void *Program::getNativePointer(unsigned Idx) {
33
0
  return NativePointers[Idx];
34
0
}
35
36
0
unsigned Program::createGlobalString(const StringLiteral *S) {
37
0
  const size_t CharWidth = S->getCharByteWidth();
38
0
  const size_t BitWidth = CharWidth * Ctx.getCharBit();
39
40
0
  PrimType CharType;
41
0
  switch (CharWidth) {
42
0
  case 1:
43
0
    CharType = PT_Sint8;
44
0
    break;
45
0
  case 2:
46
0
    CharType = PT_Uint16;
47
0
    break;
48
0
  case 4:
49
0
    CharType = PT_Uint32;
50
0
    break;
51
0
  default:
52
0
    llvm_unreachable("unsupported character width");
53
0
  }
54
55
  // Create a descriptor for the string.
56
0
  Descriptor *Desc = allocateDescriptor(S, CharType, S->getLength() + 1,
57
0
                                        /*isConst=*/true,
58
0
                                        /*isTemporary=*/false,
59
0
                                        /*isMutable=*/false);
60
61
  // Allocate storage for the string.
62
  // The byte length does not include the null terminator.
63
0
  unsigned I = Globals.size();
64
0
  unsigned Sz = Desc->getAllocSize();
65
0
  auto *G = new (Allocator, Sz) Global(Desc, /*isStatic=*/true,
66
0
                                       /*isExtern=*/false);
67
0
  Globals.push_back(G);
68
69
  // Construct the string in storage.
70
0
  const Pointer Ptr(G->block());
71
0
  for (unsigned I = 0, N = S->getLength(); I <= N; ++I) {
72
0
    Pointer Field = Ptr.atIndex(I).narrow();
73
0
    const uint32_t CodePoint = I == N ? 0 : S->getCodeUnit(I);
74
0
    switch (CharType) {
75
0
      case PT_Sint8: {
76
0
        using T = PrimConv<PT_Sint8>::T;
77
0
        Field.deref<T>() = T::from(CodePoint, BitWidth);
78
0
        break;
79
0
      }
80
0
      case PT_Uint16: {
81
0
        using T = PrimConv<PT_Uint16>::T;
82
0
        Field.deref<T>() = T::from(CodePoint, BitWidth);
83
0
        break;
84
0
      }
85
0
      case PT_Uint32: {
86
0
        using T = PrimConv<PT_Uint32>::T;
87
0
        Field.deref<T>() = T::from(CodePoint, BitWidth);
88
0
        break;
89
0
      }
90
0
      default:
91
0
        llvm_unreachable("unsupported character type");
92
0
    }
93
0
  }
94
0
  return I;
95
0
}
96
97
0
Pointer Program::getPtrGlobal(unsigned Idx) {
98
0
  assert(Idx < Globals.size());
99
0
  return Pointer(Globals[Idx]->block());
100
0
}
101
102
0
llvm::Optional<unsigned> Program::getGlobal(const ValueDecl *VD) {
103
0
  auto It = GlobalIndices.find(VD);
104
0
  if (It != GlobalIndices.end())
105
0
    return It->second;
106
107
  // Find any previous declarations which were aleady evaluated.
108
0
  llvm::Optional<unsigned> Index;
109
0
  for (const Decl *P = VD; P; P = P->getPreviousDecl()) {
110
0
    auto It = GlobalIndices.find(P);
111
0
    if (It != GlobalIndices.end()) {
112
0
      Index = It->second;
113
0
      break;
114
0
    }
115
0
  }
116
117
  // Map the decl to the existing index.
118
0
  if (Index) {
119
0
    GlobalIndices[VD] = *Index;
120
0
    return {};
121
0
  }
122
123
0
  return Index;
124
0
}
125
126
0
llvm::Optional<unsigned> Program::getOrCreateGlobal(const ValueDecl *VD) {
127
0
  if (auto Idx = getGlobal(VD))
128
0
    return Idx;
129
130
0
  if (auto Idx = createGlobal(VD)) {
131
0
    GlobalIndices[VD] = *Idx;
132
0
    return Idx;
133
0
  }
134
0
  return {};
135
0
}
136
137
0
llvm::Optional<unsigned> Program::getOrCreateDummy(const ParmVarDecl *PD) {
138
0
  auto &ASTCtx = Ctx.getASTContext();
139
140
  // Create a pointer to an incomplete array of the specified elements.
141
0
  QualType ElemTy = PD->getType()->castAs<PointerType>()->getPointeeType();
142
0
  QualType Ty = ASTCtx.getIncompleteArrayType(ElemTy, ArrayType::Normal, 0);
143
144
  // Dedup blocks since they are immutable and pointers cannot be compared.
145
0
  auto It = DummyParams.find(PD);
146
0
  if (It != DummyParams.end())
147
0
    return It->second;
148
149
0
  if (auto Idx = createGlobal(PD, Ty, /*isStatic=*/true, /*isExtern=*/true)) {
150
0
    DummyParams[PD] = *Idx;
151
0
    return Idx;
152
0
  }
153
0
  return {};
154
0
}
155
156
0
llvm::Optional<unsigned> Program::createGlobal(const ValueDecl *VD) {
157
0
  bool IsStatic, IsExtern;
158
0
  if (auto *Var = dyn_cast<VarDecl>(VD)) {
159
0
    IsStatic = !Var->hasLocalStorage();
160
0
    IsExtern = !Var->getAnyInitializer();
161
0
  } else {
162
0
    IsStatic = false;
163
0
    IsExtern = true;
164
0
  }
165
0
  if (auto Idx = createGlobal(VD, VD->getType(), IsStatic, IsExtern)) {
166
0
    for (const Decl *P = VD; P; P = P->getPreviousDecl())
167
0
      GlobalIndices[P] = *Idx;
168
0
    return *Idx;
169
0
  }
170
0
  return {};
171
0
}
172
173
0
llvm::Optional<unsigned> Program::createGlobal(const Expr *E) {
174
0
  return createGlobal(E, E->getType(), /*isStatic=*/true, /*isExtern=*/false);
175
0
}
176
177
llvm::Optional<unsigned> Program::createGlobal(const DeclTy &D, QualType Ty,
178
0
                                               bool IsStatic, bool IsExtern) {
179
  // Create a descriptor for the global.
180
0
  Descriptor *Desc;
181
0
  const bool IsConst = Ty.isConstQualified();
182
0
  const bool IsTemporary = D.dyn_cast<const Expr *>();
183
0
  if (auto T = Ctx.classify(Ty)) {
184
0
    Desc = createDescriptor(D, *T, IsConst, IsTemporary);
185
0
  } else {
186
0
    Desc = createDescriptor(D, Ty.getTypePtr(), IsConst, IsTemporary);
187
0
  }
188
0
  if (!Desc)
189
0
    return {};
190
191
  // Allocate a block for storage.
192
0
  unsigned I = Globals.size();
193
194
0
  auto *G = new (Allocator, Desc->getAllocSize())
195
0
      Global(getCurrentDecl(), Desc, IsStatic, IsExtern);
196
0
  G->block()->invokeCtor();
197
198
0
  Globals.push_back(G);
199
200
0
  return I;
201
0
}
202
203
1
Function *Program::getFunction(const FunctionDecl *F) {
204
1
  F = F->getDefinition();
205
1
  auto It = Funcs.find(F);
206
1
  return It == Funcs.end() ? nullptr : 
It->second.get()0
;
207
1
}
208
209
0
llvm::Expected<Function *> Program::getOrCreateFunction(const FunctionDecl *F) {
210
0
  if (Function *Func = getFunction(F)) {
211
0
    return Func;
212
0
  }
213
214
  // Try to compile the function if it wasn't compiled yet.
215
0
  if (const FunctionDecl *FD = F->getDefinition())
216
0
    return ByteCodeStmtGen<ByteCodeEmitter>(Ctx, *this).compileFunc(FD);
217
218
  // A relocation which traps if not resolved.
219
0
  return nullptr;
220
0
}
221
222
0
Record *Program::getOrCreateRecord(const RecordDecl *RD) {
223
  // Use the actual definition as a key.
224
0
  RD = RD->getDefinition();
225
0
  if (!RD)
226
0
    return nullptr;
227
228
  // Deduplicate records.
229
0
  auto It = Records.find(RD);
230
0
  if (It != Records.end()) {
231
0
    return It->second;
232
0
  }
233
234
  // Number of bytes required by fields and base classes.
235
0
  unsigned Size = 0;
236
  // Number of bytes required by virtual base.
237
0
  unsigned VirtSize = 0;
238
239
  // Helper to get a base descriptor.
240
0
  auto GetBaseDesc = [this](const RecordDecl *BD, Record *BR) -> Descriptor * {
241
0
    if (!BR)
242
0
      return nullptr;
243
0
    return allocateDescriptor(BD, BR, /*isConst=*/false,
244
0
                              /*isTemporary=*/false,
245
0
                              /*isMutable=*/false);
246
0
  };
247
248
  // Reserve space for base classes.
249
0
  Record::BaseList Bases;
250
0
  Record::VirtualBaseList VirtBases;
251
0
  if (auto *CD = dyn_cast<CXXRecordDecl>(RD)) {
252
0
    for (const CXXBaseSpecifier &Spec : CD->bases()) {
253
0
      if (Spec.isVirtual())
254
0
        continue;
255
256
0
      const RecordDecl *BD = Spec.getType()->castAs<RecordType>()->getDecl();
257
0
      Record *BR = getOrCreateRecord(BD);
258
0
      if (Descriptor *Desc = GetBaseDesc(BD, BR)) {
259
0
        Size += align(sizeof(InlineDescriptor));
260
0
        Bases.push_back({BD, Size, Desc, BR});
261
0
        Size += align(BR->getSize());
262
0
        continue;
263
0
      }
264
0
      return nullptr;
265
0
    }
266
267
0
    for (const CXXBaseSpecifier &Spec : CD->vbases()) {
268
0
      const RecordDecl *BD = Spec.getType()->castAs<RecordType>()->getDecl();
269
0
      Record *BR = getOrCreateRecord(BD);
270
271
0
      if (Descriptor *Desc = GetBaseDesc(BD, BR)) {
272
0
        VirtSize += align(sizeof(InlineDescriptor));
273
0
        VirtBases.push_back({BD, VirtSize, Desc, BR});
274
0
        VirtSize += align(BR->getSize());
275
0
        continue;
276
0
      }
277
0
      return nullptr;
278
0
    }
279
0
  }
280
281
  // Reserve space for fields.
282
0
  Record::FieldList Fields;
283
0
  for (const FieldDecl *FD : RD->fields()) {
284
    // Reserve space for the field's descriptor and the offset.
285
0
    Size += align(sizeof(InlineDescriptor));
286
287
    // Classify the field and add its metadata.
288
0
    QualType FT = FD->getType();
289
0
    const bool IsConst = FT.isConstQualified();
290
0
    const bool IsMutable = FD->isMutable();
291
0
    Descriptor *Desc;
292
0
    if (llvm::Optional<PrimType> T = Ctx.classify(FT)) {
293
0
      Desc = createDescriptor(FD, *T, IsConst, /*isTemporary=*/false,
294
0
                              IsMutable);
295
0
    } else {
296
0
      Desc = createDescriptor(FD, FT.getTypePtr(), IsConst,
297
0
                              /*isTemporary=*/false, IsMutable);
298
0
    }
299
0
    if (!Desc)
300
0
      return nullptr;
301
0
    Fields.push_back({FD, Size, Desc});
302
0
    Size += align(Desc->getAllocSize());
303
0
  }
304
305
0
  Record *R = new (Allocator) Record(RD, std::move(Bases), std::move(Fields),
306
0
                                     std::move(VirtBases), VirtSize, Size);
307
0
  Records.insert({RD, R});
308
0
  return R;
309
0
}
310
311
Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty,
312
                                      bool IsConst, bool IsTemporary,
313
0
                                      bool IsMutable) {
314
  // Classes and structures.
315
0
  if (auto *RT = Ty->getAs<RecordType>()) {
316
0
    if (auto *Record = getOrCreateRecord(RT->getDecl()))
317
0
      return allocateDescriptor(D, Record, IsConst, IsTemporary, IsMutable);
318
0
  }
319
320
  // Arrays.
321
0
  if (auto ArrayType = Ty->getAsArrayTypeUnsafe()) {
322
0
    QualType ElemTy = ArrayType->getElementType();
323
    // Array of well-known bounds.
324
0
    if (auto CAT = dyn_cast<ConstantArrayType>(ArrayType)) {
325
0
      size_t NumElems = CAT->getSize().getZExtValue();
326
0
      if (llvm::Optional<PrimType> T = Ctx.classify(ElemTy)) {
327
        // Arrays of primitives.
328
0
        unsigned ElemSize = primSize(*T);
329
0
        if (std::numeric_limits<unsigned>::max() / ElemSize <= NumElems) {
330
0
          return {};
331
0
        }
332
0
        return allocateDescriptor(D, *T, NumElems, IsConst, IsTemporary,
333
0
                                  IsMutable);
334
0
      } else {
335
        // Arrays of composites. In this case, the array is a list of pointers,
336
        // followed by the actual elements.
337
0
        Descriptor *Desc =
338
0
            createDescriptor(D, ElemTy.getTypePtr(), IsConst, IsTemporary);
339
0
        if (!Desc)
340
0
          return nullptr;
341
0
        InterpSize ElemSize = Desc->getAllocSize() + sizeof(InlineDescriptor);
342
0
        if (std::numeric_limits<unsigned>::max() / ElemSize <= NumElems)
343
0
          return {};
344
0
        return allocateDescriptor(D, Desc, NumElems, IsConst, IsTemporary,
345
0
                                  IsMutable);
346
0
      }
347
0
    }
348
349
    // Array of unknown bounds - cannot be accessed and pointer arithmetic
350
    // is forbidden on pointers to such objects.
351
0
    if (isa<IncompleteArrayType>(ArrayType)) {
352
0
      if (llvm::Optional<PrimType> T = Ctx.classify(ElemTy)) {
353
0
        return allocateDescriptor(D, *T, IsTemporary,
354
0
                                  Descriptor::UnknownSize{});
355
0
      } else {
356
0
        Descriptor *Desc =
357
0
            createDescriptor(D, ElemTy.getTypePtr(), IsConst, IsTemporary);
358
0
        if (!Desc)
359
0
          return nullptr;
360
0
        return allocateDescriptor(D, Desc, IsTemporary,
361
0
                                  Descriptor::UnknownSize{});
362
0
      }
363
0
    }
364
0
  }
365
366
  // Atomic types.
367
0
  if (auto *AT = Ty->getAs<AtomicType>()) {
368
0
    const Type *InnerTy = AT->getValueType().getTypePtr();
369
0
    return createDescriptor(D, InnerTy, IsConst, IsTemporary, IsMutable);
370
0
  }
371
372
  // Complex types - represented as arrays of elements.
373
0
  if (auto *CT = Ty->getAs<ComplexType>()) {
374
0
    PrimType ElemTy = *Ctx.classify(CT->getElementType());
375
0
    return allocateDescriptor(D, ElemTy, 2, IsConst, IsTemporary, IsMutable);
376
0
  }
377
378
0
  return nullptr;
379
0
}