Coverage Report

Created: 2020-09-19 12:23

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/AST/Interp/InterpFrame.cpp
Line
Count
Source (jump to first uncovered line)
1
//===--- InterpFrame.cpp - Call Frame implementation for the 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 "InterpFrame.h"
10
#include "Function.h"
11
#include "Interp.h"
12
#include "InterpStack.h"
13
#include "PrimType.h"
14
#include "Program.h"
15
#include "clang/AST/DeclCXX.h"
16
17
using namespace clang;
18
using namespace clang::interp;
19
20
InterpFrame::InterpFrame(InterpState &S, Function *Func, InterpFrame *Caller,
21
                         CodePtr RetPC, Pointer &&This)
22
    : Caller(Caller), S(S), Func(Func), This(std::move(This)), RetPC(RetPC),
23
      ArgSize(Func ? Func->getArgSize() : 0),
24
8
      Args(static_cast<char *>(S.Stk.top())), FrameOffset(S.Stk.size()) {
25
8
  if (Func) {
26
1
    if (unsigned FrameSize = Func->getFrameSize()) {
27
0
      Locals = std::make_unique<char[]>(FrameSize);
28
0
      for (auto &Scope : Func->scopes()) {
29
0
        for (auto &Local : Scope.locals()) {
30
0
          Block *B = new (localBlock(Local.Offset)) Block(Local.Desc);
31
0
          B->invokeCtor();
32
0
        }
33
0
      }
34
0
    }
35
1
  }
36
8
}
37
38
8
InterpFrame::~InterpFrame() {
39
8
  if (Func && 
Func->isConstructor()1
&&
This.isBaseClass()0
)
40
0
    This.initialize();
41
8
  for (auto &Param : Params)
42
0
    S.deallocate(reinterpret_cast<Block *>(Param.second.get()));
43
8
}
44
45
0
void InterpFrame::destroy(unsigned Idx) {
46
0
  for (auto &Local : Func->getScope(Idx).locals()) {
47
0
    S.deallocate(reinterpret_cast<Block *>(localBlock(Local.Offset)));
48
0
  }
49
0
}
50
51
0
void InterpFrame::popArgs() {
52
0
  for (PrimType Ty : Func->args_reverse())
53
0
    TYPE_SWITCH(Ty, S.Stk.discard<T>());
54
0
}
55
56
template <typename T>
57
0
static void print(llvm::raw_ostream &OS, const T &V, ASTContext &, QualType) {
58
0
  OS << V;
59
0
}
Unexecuted instantiation: InterpFrame.cpp:void print<clang::interp::Integral<8u, true> >(llvm::raw_ostream&, clang::interp::Integral<8u, true> const&, clang::ASTContext&, clang::QualType)
Unexecuted instantiation: InterpFrame.cpp:void print<clang::interp::Integral<8u, false> >(llvm::raw_ostream&, clang::interp::Integral<8u, false> const&, clang::ASTContext&, clang::QualType)
Unexecuted instantiation: InterpFrame.cpp:void print<clang::interp::Integral<16u, true> >(llvm::raw_ostream&, clang::interp::Integral<16u, true> const&, clang::ASTContext&, clang::QualType)
Unexecuted instantiation: InterpFrame.cpp:void print<clang::interp::Integral<16u, false> >(llvm::raw_ostream&, clang::interp::Integral<16u, false> const&, clang::ASTContext&, clang::QualType)
Unexecuted instantiation: InterpFrame.cpp:void print<clang::interp::Integral<32u, true> >(llvm::raw_ostream&, clang::interp::Integral<32u, true> const&, clang::ASTContext&, clang::QualType)
Unexecuted instantiation: InterpFrame.cpp:void print<clang::interp::Integral<32u, false> >(llvm::raw_ostream&, clang::interp::Integral<32u, false> const&, clang::ASTContext&, clang::QualType)
Unexecuted instantiation: InterpFrame.cpp:void print<clang::interp::Integral<64u, true> >(llvm::raw_ostream&, clang::interp::Integral<64u, true> const&, clang::ASTContext&, clang::QualType)
Unexecuted instantiation: InterpFrame.cpp:void print<clang::interp::Integral<64u, false> >(llvm::raw_ostream&, clang::interp::Integral<64u, false> const&, clang::ASTContext&, clang::QualType)
Unexecuted instantiation: InterpFrame.cpp:void print<clang::interp::Boolean>(llvm::raw_ostream&, clang::interp::Boolean const&, clang::ASTContext&, clang::QualType)
60
61
template <>
62
void print(llvm::raw_ostream &OS, const Pointer &P, ASTContext &Ctx,
63
0
           QualType Ty) {
64
0
  if (P.isZero()) {
65
0
    OS << "nullptr";
66
0
    return;
67
0
  }
68
0
69
0
  auto printDesc = [&OS, &Ctx](Descriptor *Desc) {
70
0
    if (auto *D = Desc->asDecl()) {
71
      // Subfields or named values.
72
0
      if (auto *VD = dyn_cast<ValueDecl>(D)) {
73
0
        OS << *VD;
74
0
        return;
75
0
      }
76
      // Base classes.
77
0
      if (isa<RecordDecl>(D)) {
78
0
        return;
79
0
      }
80
0
    }
81
    // Temporary expression.
82
0
    if (auto *E = Desc->asExpr()) {
83
0
      E->printPretty(OS, nullptr, Ctx.getPrintingPolicy());
84
0
      return;
85
0
    }
86
0
    llvm_unreachable("Invalid descriptor type");
87
0
  };
88
0
89
0
  if (!Ty->isReferenceType())
90
0
    OS << "&";
91
0
  llvm::SmallVector<Pointer, 2> Levels;
92
0
  for (Pointer F = P; !F.isRoot(); ) {
93
0
    Levels.push_back(F);
94
0
    F = F.isArrayElement() ? F.getArray().expand() : F.getBase();
95
0
  }
96
0
97
0
  printDesc(P.getDeclDesc());
98
0
  for (auto It = Levels.rbegin(); It != Levels.rend(); ++It) {
99
0
    if (It->inArray()) {
100
0
      OS << "[" << It->expand().getIndex() << "]";
101
0
      continue;
102
0
    }
103
0
    if (auto Index = It->getIndex()) {
104
0
      OS << " + " << Index;
105
0
      continue;
106
0
    }
107
0
    OS << ".";
108
0
    printDesc(It->getFieldDesc());
109
0
  }
110
0
}
111
112
0
void InterpFrame::describe(llvm::raw_ostream &OS) {
113
0
  const FunctionDecl *F = getCallee();
114
0
  auto *M = dyn_cast<CXXMethodDecl>(F);
115
0
  if (M && M->isInstance() && !isa<CXXConstructorDecl>(F)) {
116
0
    print(OS, This, S.getCtx(), S.getCtx().getRecordType(M->getParent()));
117
0
    OS << "->";
118
0
  }
119
0
  OS << *F << "(";
120
0
  unsigned Off = Func->hasRVO() ? primSize(PT_Ptr) : 0;
121
0
  for (unsigned I = 0, N = F->getNumParams(); I < N; ++I) {
122
0
    QualType Ty = F->getParamDecl(I)->getType();
123
0
124
0
    PrimType PrimTy;
125
0
    if (llvm::Optional<PrimType> T = S.Ctx.classify(Ty)) {
126
0
      PrimTy = *T;
127
0
    } else {
128
0
      PrimTy = PT_Ptr;
129
0
    }
130
0
131
0
    TYPE_SWITCH(PrimTy, print(OS, stackRef<T>(Off), S.getCtx(), Ty));
132
0
    Off += align(primSize(PrimTy));
133
0
    if (I + 1 != N)
134
0
      OS << ", ";
135
0
  }
136
0
  OS << ")";
137
0
}
138
139
0
Frame *InterpFrame::getCaller() const {
140
0
  if (Caller->Caller)
141
0
    return Caller;
142
0
  return S.getSplitFrame();
143
0
}
144
145
0
SourceLocation InterpFrame::getCallLocation() const {
146
0
  if (!Caller->Func)
147
0
    return S.getLocation(nullptr, {});
148
0
  return S.getLocation(Caller->Func, RetPC - sizeof(uintptr_t));
149
0
}
150
151
0
const FunctionDecl *InterpFrame::getCallee() const {
152
0
  return Func->getDecl();
153
0
}
154
155
0
Pointer InterpFrame::getLocalPointer(unsigned Offset) {
156
0
  assert(Offset < Func->getFrameSize() && "Invalid local offset.");
157
0
  return Pointer(
158
0
      reinterpret_cast<Block *>(Locals.get() + Offset - sizeof(Block)));
159
0
}
160
161
0
Pointer InterpFrame::getParamPointer(unsigned Off) {
162
  // Return the block if it was created previously.
163
0
  auto Pt = Params.find(Off);
164
0
  if (Pt != Params.end()) {
165
0
    return Pointer(reinterpret_cast<Block *>(Pt->second.get()));
166
0
  }
167
0
168
  // Allocate memory to store the parameter and the block metadata.
169
0
  const auto &Desc = Func->getParamDescriptor(Off);
170
0
  size_t BlockSize = sizeof(Block) + Desc.second->getAllocSize();
171
0
  auto Memory = std::make_unique<char[]>(BlockSize);
172
0
  auto *B = new (Memory.get()) Block(Desc.second);
173
0
174
  // Copy the initial value.
175
0
  TYPE_SWITCH(Desc.first, new (B->data()) T(stackRef<T>(Off)));
176
0
177
  // Record the param.
178
0
  Params.insert({Off, std::move(Memory)});
179
0
  return Pointer(B);
180
0
}
181
182
0
SourceInfo InterpFrame::getSource(CodePtr PC) const {
183
0
  return S.getSource(Func, PC);
184
0
}
185
186
0
const Expr *InterpFrame::getExpr(CodePtr PC) const {
187
0
  return S.getExpr(Func, PC);
188
0
}
189
190
0
SourceLocation InterpFrame::getLocation(CodePtr PC) const {
191
0
  return S.getLocation(Func, PC);
192
0
}
193