EvalEmitter.cpp revision 353942
1165982Srwatson//===--- EvalEmitter.cpp - Instruction emitter for the VM -------*- C++ -*-===//
2165982Srwatson//
3165982Srwatson// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4165982Srwatson// See https://llvm.org/LICENSE.txt for license information.
5165982Srwatson// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6165982Srwatson//
7165982Srwatson//===----------------------------------------------------------------------===//
8165982Srwatson
9165982Srwatson#include "EvalEmitter.h"
10165982Srwatson#include "Context.h"
11165982Srwatson#include "Interp.h"
12165982Srwatson#include "Opcode.h"
13165982Srwatson#include "Program.h"
14165982Srwatson#include "clang/AST/DeclCXX.h"
15165982Srwatson
16165982Srwatsonusing namespace clang;
17165982Srwatsonusing namespace clang::interp;
18165982Srwatson
19165982Srwatsonusing APSInt = llvm::APSInt;
20165982Srwatsontemplate <typename T> using Expected = llvm::Expected<T>;
21165982Srwatson
22165982SrwatsonEvalEmitter::EvalEmitter(Context &Ctx, Program &P, State &Parent,
23165982Srwatson                         InterpStack &Stk, APValue &Result)
24165982Srwatson    : Ctx(Ctx), P(P), S(Parent, P, Stk, Ctx, this), Result(Result) {
25165982Srwatson  // Create a dummy frame for the interpreter which does not have locals.
26165982Srwatson  S.Current = new InterpFrame(S, nullptr, nullptr, CodePtr(), Pointer());
27165982Srwatson}
28165982Srwatson
29165984Srwatsonllvm::Expected<bool> EvalEmitter::interpretExpr(const Expr *E) {
30165982Srwatson  if (this->visitExpr(E))
31165982Srwatson    return true;
32165982Srwatson  if (BailLocation)
33165982Srwatson    return llvm::make_error<ByteCodeGenError>(*BailLocation);
34165982Srwatson  return false;
35165982Srwatson}
36165982Srwatson
37165982Srwatsonllvm::Expected<bool> EvalEmitter::interpretDecl(const VarDecl *VD) {
38165984Srwatson  if (this->visitDecl(VD))
39165982Srwatson    return true;
40165982Srwatson  if (BailLocation)
41165982Srwatson    return llvm::make_error<ByteCodeGenError>(*BailLocation);
42165982Srwatson  return false;
43165982Srwatson}
44165982Srwatson
45165982Srwatsonvoid EvalEmitter::emitLabel(LabelTy Label) {
46165982Srwatson  CurrentLabel = Label;
47165982Srwatson}
48165982Srwatson
49165982SrwatsonEvalEmitter::LabelTy EvalEmitter::getLabel() { return NextLabel++; }
50165982Srwatson
51165982SrwatsonScope::Local EvalEmitter::createLocal(Descriptor *D) {
52165982Srwatson  // Allocate memory for a local.
53165982Srwatson  auto Memory = std::make_unique<char[]>(sizeof(Block) + D->getAllocSize());
54165982Srwatson  auto *B = new (Memory.get()) Block(D, /*isStatic=*/false);
55165982Srwatson  B->invokeCtor();
56165982Srwatson
57294485Sngie  // Register the local.
58165982Srwatson  unsigned Off = Locals.size();
59294485Sngie  Locals.insert({Off, std::move(Memory)});
60165982Srwatson  return {Off, D};
61165982Srwatson}
62165982Srwatson
63165982Srwatsonbool EvalEmitter::bail(const SourceLocation &Loc) {
64165982Srwatson  if (!BailLocation)
65165982Srwatson    BailLocation = Loc;
66165982Srwatson  return false;
67165982Srwatson}
68165982Srwatson
69165982Srwatsonbool EvalEmitter::jumpTrue(const LabelTy &Label) {
70165982Srwatson  if (isActive()) {
71294485Sngie    if (S.Stk.pop<bool>())
72165982Srwatson      ActiveLabel = Label;
73294485Sngie  }
74165982Srwatson  return true;
75165982Srwatson}
76165982Srwatson
77165982Srwatsonbool EvalEmitter::jumpFalse(const LabelTy &Label) {
78165982Srwatson  if (isActive()) {
79165982Srwatson    if (!S.Stk.pop<bool>())
80165982Srwatson      ActiveLabel = Label;
81165982Srwatson  }
82165982Srwatson  return true;
83165982Srwatson}
84165982Srwatson
85165982Srwatsonbool EvalEmitter::jump(const LabelTy &Label) {
86165982Srwatson  if (isActive())
87165982Srwatson    CurrentLabel = ActiveLabel = Label;
88165982Srwatson  return true;
89165982Srwatson}
90294485Sngie
91165982Srwatsonbool EvalEmitter::fallthrough(const LabelTy &Label) {
92294485Sngie  if (isActive())
93165982Srwatson    ActiveLabel = Label;
94165982Srwatson  CurrentLabel = Label;
95165982Srwatson  return true;
96294485Sngie}
97165982Srwatson
98165982Srwatsontemplate <PrimType OpType> bool EvalEmitter::emitRet(const SourceInfo &Info) {
99165982Srwatson  if (!isActive())
100165982Srwatson    return true;
101294485Sngie  using T = typename PrimConv<OpType>::T;
102165982Srwatson  return ReturnValue<T>(S.Stk.pop<T>(), Result);
103294485Sngie}
104165982Srwatson
105165982Srwatsonbool EvalEmitter::emitRetVoid(const SourceInfo &Info) { return true; }
106165982Srwatson
107294485Sngiebool EvalEmitter::emitRetValue(const SourceInfo &Info) {
108165982Srwatson  // Method to recursively traverse composites.
109165982Srwatson  std::function<bool(QualType, const Pointer &, APValue &)> Composite;
110165982Srwatson  Composite = [this, &Composite](QualType Ty, const Pointer &Ptr, APValue &R) {
111165982Srwatson    if (auto *AT = Ty->getAs<AtomicType>())
112165982Srwatson      Ty = AT->getValueType();
113165982Srwatson
114165982Srwatson    if (auto *RT = Ty->getAs<RecordType>()) {
115165982Srwatson      auto *Record = Ptr.getRecord();
116165982Srwatson      assert(Record && "Missing record descriptor");
117165984Srwatson
118165982Srwatson      bool Ok = true;
119165984Srwatson      if (RT->getDecl()->isUnion()) {
120165984Srwatson        const FieldDecl *ActiveField = nullptr;
121165982Srwatson        APValue Value;
122165982Srwatson        for (auto &F : Record->fields()) {
123165982Srwatson          const Pointer &FP = Ptr.atField(F.Offset);
124165982Srwatson          QualType FieldTy = F.Decl->getType();
125165982Srwatson          if (FP.isActive()) {
126165982Srwatson            if (llvm::Optional<PrimType> T = Ctx.classify(FieldTy)) {
127165982Srwatson              TYPE_SWITCH(*T, Ok &= ReturnValue<T>(FP.deref<T>(), Value));
128165982Srwatson            } else {
129165982Srwatson              Ok &= Composite(FieldTy, FP, Value);
130165982Srwatson            }
131165982Srwatson            break;
132165982Srwatson          }
133294485Sngie        }
134165982Srwatson        R = APValue(ActiveField, Value);
135294485Sngie      } else {
136165982Srwatson        unsigned NF = Record->getNumFields();
137165982Srwatson        unsigned NB = Record->getNumBases();
138294485Sngie        unsigned NV = Ptr.isBaseClass() ? 0 : Record->getNumVirtualBases();
139165982Srwatson
140165982Srwatson        R = APValue(APValue::UninitStruct(), NB, NF);
141165982Srwatson
142165982Srwatson        for (unsigned I = 0; I < NF; ++I) {
143165982Srwatson          const Record::Field *FD = Record->getField(I);
144165982Srwatson          QualType FieldTy = FD->Decl->getType();
145165982Srwatson          const Pointer &FP = Ptr.atField(FD->Offset);
146294485Sngie          APValue &Value = R.getStructField(I);
147165982Srwatson
148294485Sngie          if (llvm::Optional<PrimType> T = Ctx.classify(FieldTy)) {
149165984Srwatson            TYPE_SWITCH(*T, Ok &= ReturnValue<T>(FP.deref<T>(), Value));
150165984Srwatson          } else {
151294485Sngie            Ok &= Composite(FieldTy, FP, Value);
152165982Srwatson          }
153165982Srwatson        }
154165982Srwatson
155165982Srwatson        for (unsigned I = 0; I < NB; ++I) {
156165982Srwatson          const Record::Base *BD = Record->getBase(I);
157165982Srwatson          QualType BaseTy = Ctx.getASTContext().getRecordType(BD->Decl);
158294485Sngie          const Pointer &BP = Ptr.atField(BD->Offset);
159294485Sngie          Ok &= Composite(BaseTy, BP, R.getStructBase(I));
160165982Srwatson        }
161165982Srwatson
162294485Sngie        for (unsigned I = 0; I < NV; ++I) {
163294485Sngie          const Record::Base *VD = Record->getVirtualBase(I);
164294485Sngie          QualType VirtBaseTy = Ctx.getASTContext().getRecordType(VD->Decl);
165165982Srwatson          const Pointer &VP = Ptr.atField(VD->Offset);
166165984Srwatson          Ok &= Composite(VirtBaseTy, VP, R.getStructBase(NB + I));
167165984Srwatson        }
168165984Srwatson      }
169165984Srwatson      return Ok;
170165984Srwatson    }
171165984Srwatson    if (auto *AT = Ty->getAsArrayTypeUnsafe()) {
172165984Srwatson      const size_t NumElems = Ptr.getNumElems();
173165984Srwatson      QualType ElemTy = AT->getElementType();
174294485Sngie      R = APValue(APValue::UninitArray{}, NumElems, NumElems);
175165984Srwatson
176294485Sngie      bool Ok = true;
177165984Srwatson      for (unsigned I = 0; I < NumElems; ++I) {
178294485Sngie        APValue &Slot = R.getArrayInitializedElt(I);
179165984Srwatson        const Pointer &EP = Ptr.atIndex(I);
180165982Srwatson        if (llvm::Optional<PrimType> T = Ctx.classify(ElemTy)) {
181165982Srwatson          TYPE_SWITCH(*T, Ok &= ReturnValue<T>(EP.deref<T>(), Slot));
182165982Srwatson        } else {
183165982Srwatson          Ok &= Composite(ElemTy, EP.narrow(), Slot);
184165982Srwatson        }
185165982Srwatson      }
186165982Srwatson      return Ok;
187165982Srwatson    }
188165982Srwatson    llvm_unreachable("invalid value to return");
189165982Srwatson  };
190294485Sngie
191165982Srwatson  // Return the composite type.
192165982Srwatson  const auto &Ptr = S.Stk.pop<Pointer>();
193165982Srwatson  return Composite(Ptr.getType(), Ptr, Result);
194165982Srwatson}
195165982Srwatson
196165982Srwatsonbool EvalEmitter::emitGetPtrLocal(uint32_t I, const SourceInfo &Info) {
197165982Srwatson  if (!isActive())
198294485Sngie    return true;
199165982Srwatson
200165982Srwatson  auto It = Locals.find(I);
201165982Srwatson  assert(It != Locals.end() && "Missing local variable");
202165982Srwatson  S.Stk.push<Pointer>(reinterpret_cast<Block *>(It->second.get()));
203165982Srwatson  return true;
204165982Srwatson}
205165982Srwatson
206294485Sngietemplate <PrimType OpType>
207165982Srwatsonbool EvalEmitter::emitGetLocal(uint32_t I, const SourceInfo &Info) {
208165982Srwatson  if (!isActive())
209165982Srwatson    return true;
210165982Srwatson
211165982Srwatson  using T = typename PrimConv<OpType>::T;
212281974Sngie
213165982Srwatson  auto It = Locals.find(I);
214165982Srwatson  assert(It != Locals.end() && "Missing local variable");
215281974Sngie  auto *B = reinterpret_cast<Block *>(It->second.get());
216294485Sngie  S.Stk.push<T>(*reinterpret_cast<T *>(B + 1));
217281974Sngie  return true;
218165982Srwatson}
219165982Srwatson
220294485Sngietemplate <PrimType OpType>
221165982Srwatsonbool EvalEmitter::emitSetLocal(uint32_t I, const SourceInfo &Info) {
222165982Srwatson  if (!isActive())
223165982Srwatson    return true;
224294485Sngie
225165982Srwatson  using T = typename PrimConv<OpType>::T;
226165982Srwatson
227165982Srwatson  auto It = Locals.find(I);
228294485Sngie  assert(It != Locals.end() && "Missing local variable");
229165982Srwatson  auto *B = reinterpret_cast<Block *>(It->second.get());
230165982Srwatson  *reinterpret_cast<T *>(B + 1) = S.Stk.pop<T>();
231165982Srwatson  return true;
232165982Srwatson}
233165982Srwatson
234165982Srwatsonbool EvalEmitter::emitDestroy(uint32_t I, const SourceInfo &Info) {
235165982Srwatson  if (!isActive())
236165982Srwatson    return true;
237165982Srwatson
238165982Srwatson  for (auto &Local : Descriptors[I]) {
239165982Srwatson    auto It = Locals.find(Local.Offset);
240165982Srwatson    assert(It != Locals.end() && "Missing local variable");
241165982Srwatson    S.deallocate(reinterpret_cast<Block *>(It->second.get()));
242165982Srwatson  }
243165982Srwatson
244165982Srwatson  return true;
245294485Sngie}
246165982Srwatson
247165982Srwatson//===----------------------------------------------------------------------===//
248165982Srwatson// Opcode evaluators
249165982Srwatson//===----------------------------------------------------------------------===//
250165982Srwatson
251165982Srwatson#define GET_EVAL_IMPL
252165982Srwatson#include "Opcodes.inc"
253165982Srwatson#undef GET_EVAL_IMPL
254165982Srwatson