Coverage Report

Created: 2020-02-15 09:57

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