xref: /freebsd-src/contrib/llvm-project/clang/lib/AST/Interp/EvalEmitter.cpp (revision a7dea1671b87c07d2d266f836bfa8b58efc7c134)
1*a7dea167SDimitry Andric //===--- EvalEmitter.cpp - Instruction emitter for the VM -------*- C++ -*-===//
2*a7dea167SDimitry Andric //
3*a7dea167SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*a7dea167SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*a7dea167SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*a7dea167SDimitry Andric //
7*a7dea167SDimitry Andric //===----------------------------------------------------------------------===//
8*a7dea167SDimitry Andric 
9*a7dea167SDimitry Andric #include "EvalEmitter.h"
10*a7dea167SDimitry Andric #include "Context.h"
11*a7dea167SDimitry Andric #include "Interp.h"
12*a7dea167SDimitry Andric #include "Opcode.h"
13*a7dea167SDimitry Andric #include "Program.h"
14*a7dea167SDimitry Andric #include "clang/AST/DeclCXX.h"
15*a7dea167SDimitry Andric 
16*a7dea167SDimitry Andric using namespace clang;
17*a7dea167SDimitry Andric using namespace clang::interp;
18*a7dea167SDimitry Andric 
19*a7dea167SDimitry Andric using APSInt = llvm::APSInt;
20*a7dea167SDimitry Andric template <typename T> using Expected = llvm::Expected<T>;
21*a7dea167SDimitry Andric 
22*a7dea167SDimitry Andric EvalEmitter::EvalEmitter(Context &Ctx, Program &P, State &Parent,
23*a7dea167SDimitry Andric                          InterpStack &Stk, APValue &Result)
24*a7dea167SDimitry Andric     : Ctx(Ctx), P(P), S(Parent, P, Stk, Ctx, this), Result(Result) {
25*a7dea167SDimitry Andric   // Create a dummy frame for the interpreter which does not have locals.
26*a7dea167SDimitry Andric   S.Current = new InterpFrame(S, nullptr, nullptr, CodePtr(), Pointer());
27*a7dea167SDimitry Andric }
28*a7dea167SDimitry Andric 
29*a7dea167SDimitry Andric llvm::Expected<bool> EvalEmitter::interpretExpr(const Expr *E) {
30*a7dea167SDimitry Andric   if (this->visitExpr(E))
31*a7dea167SDimitry Andric     return true;
32*a7dea167SDimitry Andric   if (BailLocation)
33*a7dea167SDimitry Andric     return llvm::make_error<ByteCodeGenError>(*BailLocation);
34*a7dea167SDimitry Andric   return false;
35*a7dea167SDimitry Andric }
36*a7dea167SDimitry Andric 
37*a7dea167SDimitry Andric llvm::Expected<bool> EvalEmitter::interpretDecl(const VarDecl *VD) {
38*a7dea167SDimitry Andric   if (this->visitDecl(VD))
39*a7dea167SDimitry Andric     return true;
40*a7dea167SDimitry Andric   if (BailLocation)
41*a7dea167SDimitry Andric     return llvm::make_error<ByteCodeGenError>(*BailLocation);
42*a7dea167SDimitry Andric   return false;
43*a7dea167SDimitry Andric }
44*a7dea167SDimitry Andric 
45*a7dea167SDimitry Andric void EvalEmitter::emitLabel(LabelTy Label) {
46*a7dea167SDimitry Andric   CurrentLabel = Label;
47*a7dea167SDimitry Andric }
48*a7dea167SDimitry Andric 
49*a7dea167SDimitry Andric EvalEmitter::LabelTy EvalEmitter::getLabel() { return NextLabel++; }
50*a7dea167SDimitry Andric 
51*a7dea167SDimitry Andric Scope::Local EvalEmitter::createLocal(Descriptor *D) {
52*a7dea167SDimitry Andric   // Allocate memory for a local.
53*a7dea167SDimitry Andric   auto Memory = std::make_unique<char[]>(sizeof(Block) + D->getAllocSize());
54*a7dea167SDimitry Andric   auto *B = new (Memory.get()) Block(D, /*isStatic=*/false);
55*a7dea167SDimitry Andric   B->invokeCtor();
56*a7dea167SDimitry Andric 
57*a7dea167SDimitry Andric   // Register the local.
58*a7dea167SDimitry Andric   unsigned Off = Locals.size();
59*a7dea167SDimitry Andric   Locals.insert({Off, std::move(Memory)});
60*a7dea167SDimitry Andric   return {Off, D};
61*a7dea167SDimitry Andric }
62*a7dea167SDimitry Andric 
63*a7dea167SDimitry Andric bool EvalEmitter::bail(const SourceLocation &Loc) {
64*a7dea167SDimitry Andric   if (!BailLocation)
65*a7dea167SDimitry Andric     BailLocation = Loc;
66*a7dea167SDimitry Andric   return false;
67*a7dea167SDimitry Andric }
68*a7dea167SDimitry Andric 
69*a7dea167SDimitry Andric bool EvalEmitter::jumpTrue(const LabelTy &Label) {
70*a7dea167SDimitry Andric   if (isActive()) {
71*a7dea167SDimitry Andric     if (S.Stk.pop<bool>())
72*a7dea167SDimitry Andric       ActiveLabel = Label;
73*a7dea167SDimitry Andric   }
74*a7dea167SDimitry Andric   return true;
75*a7dea167SDimitry Andric }
76*a7dea167SDimitry Andric 
77*a7dea167SDimitry Andric bool EvalEmitter::jumpFalse(const LabelTy &Label) {
78*a7dea167SDimitry Andric   if (isActive()) {
79*a7dea167SDimitry Andric     if (!S.Stk.pop<bool>())
80*a7dea167SDimitry Andric       ActiveLabel = Label;
81*a7dea167SDimitry Andric   }
82*a7dea167SDimitry Andric   return true;
83*a7dea167SDimitry Andric }
84*a7dea167SDimitry Andric 
85*a7dea167SDimitry Andric bool EvalEmitter::jump(const LabelTy &Label) {
86*a7dea167SDimitry Andric   if (isActive())
87*a7dea167SDimitry Andric     CurrentLabel = ActiveLabel = Label;
88*a7dea167SDimitry Andric   return true;
89*a7dea167SDimitry Andric }
90*a7dea167SDimitry Andric 
91*a7dea167SDimitry Andric bool EvalEmitter::fallthrough(const LabelTy &Label) {
92*a7dea167SDimitry Andric   if (isActive())
93*a7dea167SDimitry Andric     ActiveLabel = Label;
94*a7dea167SDimitry Andric   CurrentLabel = Label;
95*a7dea167SDimitry Andric   return true;
96*a7dea167SDimitry Andric }
97*a7dea167SDimitry Andric 
98*a7dea167SDimitry Andric template <PrimType OpType> bool EvalEmitter::emitRet(const SourceInfo &Info) {
99*a7dea167SDimitry Andric   if (!isActive())
100*a7dea167SDimitry Andric     return true;
101*a7dea167SDimitry Andric   using T = typename PrimConv<OpType>::T;
102*a7dea167SDimitry Andric   return ReturnValue<T>(S.Stk.pop<T>(), Result);
103*a7dea167SDimitry Andric }
104*a7dea167SDimitry Andric 
105*a7dea167SDimitry Andric bool EvalEmitter::emitRetVoid(const SourceInfo &Info) { return true; }
106*a7dea167SDimitry Andric 
107*a7dea167SDimitry Andric bool EvalEmitter::emitRetValue(const SourceInfo &Info) {
108*a7dea167SDimitry Andric   // Method to recursively traverse composites.
109*a7dea167SDimitry Andric   std::function<bool(QualType, const Pointer &, APValue &)> Composite;
110*a7dea167SDimitry Andric   Composite = [this, &Composite](QualType Ty, const Pointer &Ptr, APValue &R) {
111*a7dea167SDimitry Andric     if (auto *AT = Ty->getAs<AtomicType>())
112*a7dea167SDimitry Andric       Ty = AT->getValueType();
113*a7dea167SDimitry Andric 
114*a7dea167SDimitry Andric     if (auto *RT = Ty->getAs<RecordType>()) {
115*a7dea167SDimitry Andric       auto *Record = Ptr.getRecord();
116*a7dea167SDimitry Andric       assert(Record && "Missing record descriptor");
117*a7dea167SDimitry Andric 
118*a7dea167SDimitry Andric       bool Ok = true;
119*a7dea167SDimitry Andric       if (RT->getDecl()->isUnion()) {
120*a7dea167SDimitry Andric         const FieldDecl *ActiveField = nullptr;
121*a7dea167SDimitry Andric         APValue Value;
122*a7dea167SDimitry Andric         for (auto &F : Record->fields()) {
123*a7dea167SDimitry Andric           const Pointer &FP = Ptr.atField(F.Offset);
124*a7dea167SDimitry Andric           QualType FieldTy = F.Decl->getType();
125*a7dea167SDimitry Andric           if (FP.isActive()) {
126*a7dea167SDimitry Andric             if (llvm::Optional<PrimType> T = Ctx.classify(FieldTy)) {
127*a7dea167SDimitry Andric               TYPE_SWITCH(*T, Ok &= ReturnValue<T>(FP.deref<T>(), Value));
128*a7dea167SDimitry Andric             } else {
129*a7dea167SDimitry Andric               Ok &= Composite(FieldTy, FP, Value);
130*a7dea167SDimitry Andric             }
131*a7dea167SDimitry Andric             break;
132*a7dea167SDimitry Andric           }
133*a7dea167SDimitry Andric         }
134*a7dea167SDimitry Andric         R = APValue(ActiveField, Value);
135*a7dea167SDimitry Andric       } else {
136*a7dea167SDimitry Andric         unsigned NF = Record->getNumFields();
137*a7dea167SDimitry Andric         unsigned NB = Record->getNumBases();
138*a7dea167SDimitry Andric         unsigned NV = Ptr.isBaseClass() ? 0 : Record->getNumVirtualBases();
139*a7dea167SDimitry Andric 
140*a7dea167SDimitry Andric         R = APValue(APValue::UninitStruct(), NB, NF);
141*a7dea167SDimitry Andric 
142*a7dea167SDimitry Andric         for (unsigned I = 0; I < NF; ++I) {
143*a7dea167SDimitry Andric           const Record::Field *FD = Record->getField(I);
144*a7dea167SDimitry Andric           QualType FieldTy = FD->Decl->getType();
145*a7dea167SDimitry Andric           const Pointer &FP = Ptr.atField(FD->Offset);
146*a7dea167SDimitry Andric           APValue &Value = R.getStructField(I);
147*a7dea167SDimitry Andric 
148*a7dea167SDimitry Andric           if (llvm::Optional<PrimType> T = Ctx.classify(FieldTy)) {
149*a7dea167SDimitry Andric             TYPE_SWITCH(*T, Ok &= ReturnValue<T>(FP.deref<T>(), Value));
150*a7dea167SDimitry Andric           } else {
151*a7dea167SDimitry Andric             Ok &= Composite(FieldTy, FP, Value);
152*a7dea167SDimitry Andric           }
153*a7dea167SDimitry Andric         }
154*a7dea167SDimitry Andric 
155*a7dea167SDimitry Andric         for (unsigned I = 0; I < NB; ++I) {
156*a7dea167SDimitry Andric           const Record::Base *BD = Record->getBase(I);
157*a7dea167SDimitry Andric           QualType BaseTy = Ctx.getASTContext().getRecordType(BD->Decl);
158*a7dea167SDimitry Andric           const Pointer &BP = Ptr.atField(BD->Offset);
159*a7dea167SDimitry Andric           Ok &= Composite(BaseTy, BP, R.getStructBase(I));
160*a7dea167SDimitry Andric         }
161*a7dea167SDimitry Andric 
162*a7dea167SDimitry Andric         for (unsigned I = 0; I < NV; ++I) {
163*a7dea167SDimitry Andric           const Record::Base *VD = Record->getVirtualBase(I);
164*a7dea167SDimitry Andric           QualType VirtBaseTy = Ctx.getASTContext().getRecordType(VD->Decl);
165*a7dea167SDimitry Andric           const Pointer &VP = Ptr.atField(VD->Offset);
166*a7dea167SDimitry Andric           Ok &= Composite(VirtBaseTy, VP, R.getStructBase(NB + I));
167*a7dea167SDimitry Andric         }
168*a7dea167SDimitry Andric       }
169*a7dea167SDimitry Andric       return Ok;
170*a7dea167SDimitry Andric     }
171*a7dea167SDimitry Andric     if (auto *AT = Ty->getAsArrayTypeUnsafe()) {
172*a7dea167SDimitry Andric       const size_t NumElems = Ptr.getNumElems();
173*a7dea167SDimitry Andric       QualType ElemTy = AT->getElementType();
174*a7dea167SDimitry Andric       R = APValue(APValue::UninitArray{}, NumElems, NumElems);
175*a7dea167SDimitry Andric 
176*a7dea167SDimitry Andric       bool Ok = true;
177*a7dea167SDimitry Andric       for (unsigned I = 0; I < NumElems; ++I) {
178*a7dea167SDimitry Andric         APValue &Slot = R.getArrayInitializedElt(I);
179*a7dea167SDimitry Andric         const Pointer &EP = Ptr.atIndex(I);
180*a7dea167SDimitry Andric         if (llvm::Optional<PrimType> T = Ctx.classify(ElemTy)) {
181*a7dea167SDimitry Andric           TYPE_SWITCH(*T, Ok &= ReturnValue<T>(EP.deref<T>(), Slot));
182*a7dea167SDimitry Andric         } else {
183*a7dea167SDimitry Andric           Ok &= Composite(ElemTy, EP.narrow(), Slot);
184*a7dea167SDimitry Andric         }
185*a7dea167SDimitry Andric       }
186*a7dea167SDimitry Andric       return Ok;
187*a7dea167SDimitry Andric     }
188*a7dea167SDimitry Andric     llvm_unreachable("invalid value to return");
189*a7dea167SDimitry Andric   };
190*a7dea167SDimitry Andric 
191*a7dea167SDimitry Andric   // Return the composite type.
192*a7dea167SDimitry Andric   const auto &Ptr = S.Stk.pop<Pointer>();
193*a7dea167SDimitry Andric   return Composite(Ptr.getType(), Ptr, Result);
194*a7dea167SDimitry Andric }
195*a7dea167SDimitry Andric 
196*a7dea167SDimitry Andric bool EvalEmitter::emitGetPtrLocal(uint32_t I, const SourceInfo &Info) {
197*a7dea167SDimitry Andric   if (!isActive())
198*a7dea167SDimitry Andric     return true;
199*a7dea167SDimitry Andric 
200*a7dea167SDimitry Andric   auto It = Locals.find(I);
201*a7dea167SDimitry Andric   assert(It != Locals.end() && "Missing local variable");
202*a7dea167SDimitry Andric   S.Stk.push<Pointer>(reinterpret_cast<Block *>(It->second.get()));
203*a7dea167SDimitry Andric   return true;
204*a7dea167SDimitry Andric }
205*a7dea167SDimitry Andric 
206*a7dea167SDimitry Andric template <PrimType OpType>
207*a7dea167SDimitry Andric bool EvalEmitter::emitGetLocal(uint32_t I, const SourceInfo &Info) {
208*a7dea167SDimitry Andric   if (!isActive())
209*a7dea167SDimitry Andric     return true;
210*a7dea167SDimitry Andric 
211*a7dea167SDimitry Andric   using T = typename PrimConv<OpType>::T;
212*a7dea167SDimitry Andric 
213*a7dea167SDimitry Andric   auto It = Locals.find(I);
214*a7dea167SDimitry Andric   assert(It != Locals.end() && "Missing local variable");
215*a7dea167SDimitry Andric   auto *B = reinterpret_cast<Block *>(It->second.get());
216*a7dea167SDimitry Andric   S.Stk.push<T>(*reinterpret_cast<T *>(B + 1));
217*a7dea167SDimitry Andric   return true;
218*a7dea167SDimitry Andric }
219*a7dea167SDimitry Andric 
220*a7dea167SDimitry Andric template <PrimType OpType>
221*a7dea167SDimitry Andric bool EvalEmitter::emitSetLocal(uint32_t I, const SourceInfo &Info) {
222*a7dea167SDimitry Andric   if (!isActive())
223*a7dea167SDimitry Andric     return true;
224*a7dea167SDimitry Andric 
225*a7dea167SDimitry Andric   using T = typename PrimConv<OpType>::T;
226*a7dea167SDimitry Andric 
227*a7dea167SDimitry Andric   auto It = Locals.find(I);
228*a7dea167SDimitry Andric   assert(It != Locals.end() && "Missing local variable");
229*a7dea167SDimitry Andric   auto *B = reinterpret_cast<Block *>(It->second.get());
230*a7dea167SDimitry Andric   *reinterpret_cast<T *>(B + 1) = S.Stk.pop<T>();
231*a7dea167SDimitry Andric   return true;
232*a7dea167SDimitry Andric }
233*a7dea167SDimitry Andric 
234*a7dea167SDimitry Andric bool EvalEmitter::emitDestroy(uint32_t I, const SourceInfo &Info) {
235*a7dea167SDimitry Andric   if (!isActive())
236*a7dea167SDimitry Andric     return true;
237*a7dea167SDimitry Andric 
238*a7dea167SDimitry Andric   for (auto &Local : Descriptors[I]) {
239*a7dea167SDimitry Andric     auto It = Locals.find(Local.Offset);
240*a7dea167SDimitry Andric     assert(It != Locals.end() && "Missing local variable");
241*a7dea167SDimitry Andric     S.deallocate(reinterpret_cast<Block *>(It->second.get()));
242*a7dea167SDimitry Andric   }
243*a7dea167SDimitry Andric 
244*a7dea167SDimitry Andric   return true;
245*a7dea167SDimitry Andric }
246*a7dea167SDimitry Andric 
247*a7dea167SDimitry Andric //===----------------------------------------------------------------------===//
248*a7dea167SDimitry Andric // Opcode evaluators
249*a7dea167SDimitry Andric //===----------------------------------------------------------------------===//
250*a7dea167SDimitry Andric 
251*a7dea167SDimitry Andric #define GET_EVAL_IMPL
252*a7dea167SDimitry Andric #include "Opcodes.inc"
253*a7dea167SDimitry Andric #undef GET_EVAL_IMPL
254