1950b70dcSNandor Licker //===--- ByteCodeStmtGen.cpp - Code generator for expressions ---*- C++ -*-===//
2950b70dcSNandor Licker //
3950b70dcSNandor Licker // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4950b70dcSNandor Licker // See https://llvm.org/LICENSE.txt for license information.
5950b70dcSNandor Licker // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6950b70dcSNandor Licker //
7950b70dcSNandor Licker //===----------------------------------------------------------------------===//
8950b70dcSNandor Licker
9950b70dcSNandor Licker #include "ByteCodeStmtGen.h"
10950b70dcSNandor Licker #include "ByteCodeEmitter.h"
11950b70dcSNandor Licker #include "ByteCodeGenError.h"
12950b70dcSNandor Licker #include "Context.h"
13950b70dcSNandor Licker #include "Function.h"
14950b70dcSNandor Licker #include "PrimType.h"
15950b70dcSNandor Licker #include "Program.h"
16950b70dcSNandor Licker #include "State.h"
1719f1dc7bSReid Kleckner #include "clang/Basic/LLVM.h"
18950b70dcSNandor Licker
19950b70dcSNandor Licker using namespace clang;
20950b70dcSNandor Licker using namespace clang::interp;
21950b70dcSNandor Licker
22950b70dcSNandor Licker namespace clang {
23950b70dcSNandor Licker namespace interp {
24950b70dcSNandor Licker
25950b70dcSNandor Licker /// Scope managing label targets.
26950b70dcSNandor Licker template <class Emitter> class LabelScope {
27950b70dcSNandor Licker public:
~LabelScope()28950b70dcSNandor Licker virtual ~LabelScope() { }
29950b70dcSNandor Licker
30950b70dcSNandor Licker protected:
LabelScope(ByteCodeStmtGen<Emitter> * Ctx)31950b70dcSNandor Licker LabelScope(ByteCodeStmtGen<Emitter> *Ctx) : Ctx(Ctx) {}
32950b70dcSNandor Licker /// ByteCodeStmtGen instance.
33950b70dcSNandor Licker ByteCodeStmtGen<Emitter> *Ctx;
34950b70dcSNandor Licker };
35950b70dcSNandor Licker
36950b70dcSNandor Licker /// Sets the context for break/continue statements.
37950b70dcSNandor Licker template <class Emitter> class LoopScope final : public LabelScope<Emitter> {
38950b70dcSNandor Licker public:
39950b70dcSNandor Licker using LabelTy = typename ByteCodeStmtGen<Emitter>::LabelTy;
40950b70dcSNandor Licker using OptLabelTy = typename ByteCodeStmtGen<Emitter>::OptLabelTy;
41950b70dcSNandor Licker
LoopScope(ByteCodeStmtGen<Emitter> * Ctx,LabelTy BreakLabel,LabelTy ContinueLabel)42950b70dcSNandor Licker LoopScope(ByteCodeStmtGen<Emitter> *Ctx, LabelTy BreakLabel,
43950b70dcSNandor Licker LabelTy ContinueLabel)
44950b70dcSNandor Licker : LabelScope<Emitter>(Ctx), OldBreakLabel(Ctx->BreakLabel),
45950b70dcSNandor Licker OldContinueLabel(Ctx->ContinueLabel) {
46950b70dcSNandor Licker this->Ctx->BreakLabel = BreakLabel;
47950b70dcSNandor Licker this->Ctx->ContinueLabel = ContinueLabel;
48950b70dcSNandor Licker }
49950b70dcSNandor Licker
~LoopScope()50950b70dcSNandor Licker ~LoopScope() {
51950b70dcSNandor Licker this->Ctx->BreakLabel = OldBreakLabel;
52950b70dcSNandor Licker this->Ctx->ContinueLabel = OldContinueLabel;
53950b70dcSNandor Licker }
54950b70dcSNandor Licker
55950b70dcSNandor Licker private:
56950b70dcSNandor Licker OptLabelTy OldBreakLabel;
57950b70dcSNandor Licker OptLabelTy OldContinueLabel;
58950b70dcSNandor Licker };
59950b70dcSNandor Licker
60950b70dcSNandor Licker // Sets the context for a switch scope, mapping labels.
61950b70dcSNandor Licker template <class Emitter> class SwitchScope final : public LabelScope<Emitter> {
62950b70dcSNandor Licker public:
63950b70dcSNandor Licker using LabelTy = typename ByteCodeStmtGen<Emitter>::LabelTy;
64950b70dcSNandor Licker using OptLabelTy = typename ByteCodeStmtGen<Emitter>::OptLabelTy;
65950b70dcSNandor Licker using CaseMap = typename ByteCodeStmtGen<Emitter>::CaseMap;
66950b70dcSNandor Licker
SwitchScope(ByteCodeStmtGen<Emitter> * Ctx,CaseMap && CaseLabels,LabelTy BreakLabel,OptLabelTy DefaultLabel)67950b70dcSNandor Licker SwitchScope(ByteCodeStmtGen<Emitter> *Ctx, CaseMap &&CaseLabels,
68950b70dcSNandor Licker LabelTy BreakLabel, OptLabelTy DefaultLabel)
69950b70dcSNandor Licker : LabelScope<Emitter>(Ctx), OldBreakLabel(Ctx->BreakLabel),
70950b70dcSNandor Licker OldDefaultLabel(this->Ctx->DefaultLabel),
71950b70dcSNandor Licker OldCaseLabels(std::move(this->Ctx->CaseLabels)) {
72950b70dcSNandor Licker this->Ctx->BreakLabel = BreakLabel;
73950b70dcSNandor Licker this->Ctx->DefaultLabel = DefaultLabel;
74950b70dcSNandor Licker this->Ctx->CaseLabels = std::move(CaseLabels);
75950b70dcSNandor Licker }
76950b70dcSNandor Licker
~SwitchScope()77950b70dcSNandor Licker ~SwitchScope() {
78950b70dcSNandor Licker this->Ctx->BreakLabel = OldBreakLabel;
79950b70dcSNandor Licker this->Ctx->DefaultLabel = OldDefaultLabel;
80950b70dcSNandor Licker this->Ctx->CaseLabels = std::move(OldCaseLabels);
81950b70dcSNandor Licker }
82950b70dcSNandor Licker
83950b70dcSNandor Licker private:
84950b70dcSNandor Licker OptLabelTy OldBreakLabel;
85950b70dcSNandor Licker OptLabelTy OldDefaultLabel;
86950b70dcSNandor Licker CaseMap OldCaseLabels;
87950b70dcSNandor Licker };
88950b70dcSNandor Licker
89950b70dcSNandor Licker } // namespace interp
90950b70dcSNandor Licker } // namespace clang
91950b70dcSNandor Licker
92950b70dcSNandor Licker template <class Emitter>
visitFunc(const FunctionDecl * F)93950b70dcSNandor Licker bool ByteCodeStmtGen<Emitter>::visitFunc(const FunctionDecl *F) {
94950b70dcSNandor Licker // Classify the return type.
95950b70dcSNandor Licker ReturnType = this->classify(F->getReturnType());
96950b70dcSNandor Licker
97950b70dcSNandor Licker // Set up fields and context if a constructor.
98950b70dcSNandor Licker if (auto *MD = dyn_cast<CXXMethodDecl>(F))
99950b70dcSNandor Licker return this->bail(MD);
100950b70dcSNandor Licker
101950b70dcSNandor Licker if (auto *Body = F->getBody())
102950b70dcSNandor Licker if (!visitStmt(Body))
103950b70dcSNandor Licker return false;
104950b70dcSNandor Licker
105950b70dcSNandor Licker // Emit a guard return to protect against a code path missing one.
106950b70dcSNandor Licker if (F->getReturnType()->isVoidType())
107950b70dcSNandor Licker return this->emitRetVoid(SourceInfo{});
108950b70dcSNandor Licker else
109950b70dcSNandor Licker return this->emitNoRet(SourceInfo{});
110950b70dcSNandor Licker }
111950b70dcSNandor Licker
112950b70dcSNandor Licker template <class Emitter>
visitStmt(const Stmt * S)113950b70dcSNandor Licker bool ByteCodeStmtGen<Emitter>::visitStmt(const Stmt *S) {
114950b70dcSNandor Licker switch (S->getStmtClass()) {
115950b70dcSNandor Licker case Stmt::CompoundStmtClass:
116950b70dcSNandor Licker return visitCompoundStmt(cast<CompoundStmt>(S));
117950b70dcSNandor Licker case Stmt::DeclStmtClass:
118950b70dcSNandor Licker return visitDeclStmt(cast<DeclStmt>(S));
119950b70dcSNandor Licker case Stmt::ReturnStmtClass:
120950b70dcSNandor Licker return visitReturnStmt(cast<ReturnStmt>(S));
121950b70dcSNandor Licker case Stmt::IfStmtClass:
122950b70dcSNandor Licker return visitIfStmt(cast<IfStmt>(S));
123950b70dcSNandor Licker case Stmt::NullStmtClass:
124950b70dcSNandor Licker return true;
125950b70dcSNandor Licker default: {
126950b70dcSNandor Licker if (auto *Exp = dyn_cast<Expr>(S))
127950b70dcSNandor Licker return this->discard(Exp);
128950b70dcSNandor Licker return this->bail(S);
129950b70dcSNandor Licker }
130950b70dcSNandor Licker }
131950b70dcSNandor Licker }
132950b70dcSNandor Licker
133950b70dcSNandor Licker template <class Emitter>
visitCompoundStmt(const CompoundStmt * CompoundStmt)134950b70dcSNandor Licker bool ByteCodeStmtGen<Emitter>::visitCompoundStmt(
135950b70dcSNandor Licker const CompoundStmt *CompoundStmt) {
136950b70dcSNandor Licker BlockScope<Emitter> Scope(this);
137950b70dcSNandor Licker for (auto *InnerStmt : CompoundStmt->body())
138950b70dcSNandor Licker if (!visitStmt(InnerStmt))
139950b70dcSNandor Licker return false;
140950b70dcSNandor Licker return true;
141950b70dcSNandor Licker }
142950b70dcSNandor Licker
143950b70dcSNandor Licker template <class Emitter>
visitDeclStmt(const DeclStmt * DS)144950b70dcSNandor Licker bool ByteCodeStmtGen<Emitter>::visitDeclStmt(const DeclStmt *DS) {
145950b70dcSNandor Licker for (auto *D : DS->decls()) {
146950b70dcSNandor Licker // Variable declarator.
147950b70dcSNandor Licker if (auto *VD = dyn_cast<VarDecl>(D)) {
148950b70dcSNandor Licker if (!visitVarDecl(VD))
149950b70dcSNandor Licker return false;
150950b70dcSNandor Licker continue;
151950b70dcSNandor Licker }
152950b70dcSNandor Licker
153950b70dcSNandor Licker // Decomposition declarator.
154950b70dcSNandor Licker if (auto *DD = dyn_cast<DecompositionDecl>(D)) {
155950b70dcSNandor Licker return this->bail(DD);
156950b70dcSNandor Licker }
157950b70dcSNandor Licker }
158950b70dcSNandor Licker
159950b70dcSNandor Licker return true;
160950b70dcSNandor Licker }
161950b70dcSNandor Licker
162950b70dcSNandor Licker template <class Emitter>
visitReturnStmt(const ReturnStmt * RS)163950b70dcSNandor Licker bool ByteCodeStmtGen<Emitter>::visitReturnStmt(const ReturnStmt *RS) {
164950b70dcSNandor Licker if (const Expr *RE = RS->getRetValue()) {
165950b70dcSNandor Licker ExprScope<Emitter> RetScope(this);
166950b70dcSNandor Licker if (ReturnType) {
167950b70dcSNandor Licker // Primitive types are simply returned.
168950b70dcSNandor Licker if (!this->visit(RE))
169950b70dcSNandor Licker return false;
170950b70dcSNandor Licker this->emitCleanup();
171950b70dcSNandor Licker return this->emitRet(*ReturnType, RS);
172950b70dcSNandor Licker } else {
173950b70dcSNandor Licker // RVO - construct the value in the return location.
174950b70dcSNandor Licker auto ReturnLocation = [this, RE] { return this->emitGetParamPtr(0, RE); };
175950b70dcSNandor Licker if (!this->visitInitializer(RE, ReturnLocation))
176950b70dcSNandor Licker return false;
177950b70dcSNandor Licker this->emitCleanup();
178950b70dcSNandor Licker return this->emitRetVoid(RS);
179950b70dcSNandor Licker }
180950b70dcSNandor Licker } else {
181950b70dcSNandor Licker this->emitCleanup();
182950b70dcSNandor Licker if (!this->emitRetVoid(RS))
183950b70dcSNandor Licker return false;
184950b70dcSNandor Licker return true;
185950b70dcSNandor Licker }
186950b70dcSNandor Licker }
187950b70dcSNandor Licker
188950b70dcSNandor Licker template <class Emitter>
visitIfStmt(const IfStmt * IS)189950b70dcSNandor Licker bool ByteCodeStmtGen<Emitter>::visitIfStmt(const IfStmt *IS) {
190950b70dcSNandor Licker BlockScope<Emitter> IfScope(this);
191*424733c1SCorentin Jabot
192*424733c1SCorentin Jabot if (IS->isNonNegatedConsteval())
193*424733c1SCorentin Jabot return visitStmt(IS->getThen());
194*424733c1SCorentin Jabot if (IS->isNegatedConsteval())
195*424733c1SCorentin Jabot return IS->getElse() ? visitStmt(IS->getElse()) : true;
196*424733c1SCorentin Jabot
197950b70dcSNandor Licker if (auto *CondInit = IS->getInit())
198950b70dcSNandor Licker if (!visitStmt(IS->getInit()))
199950b70dcSNandor Licker return false;
200950b70dcSNandor Licker
201950b70dcSNandor Licker if (const DeclStmt *CondDecl = IS->getConditionVariableDeclStmt())
202950b70dcSNandor Licker if (!visitDeclStmt(CondDecl))
203950b70dcSNandor Licker return false;
204950b70dcSNandor Licker
205950b70dcSNandor Licker if (!this->visitBool(IS->getCond()))
206950b70dcSNandor Licker return false;
207950b70dcSNandor Licker
208950b70dcSNandor Licker if (const Stmt *Else = IS->getElse()) {
209950b70dcSNandor Licker LabelTy LabelElse = this->getLabel();
210950b70dcSNandor Licker LabelTy LabelEnd = this->getLabel();
211950b70dcSNandor Licker if (!this->jumpFalse(LabelElse))
212950b70dcSNandor Licker return false;
213950b70dcSNandor Licker if (!visitStmt(IS->getThen()))
214950b70dcSNandor Licker return false;
215950b70dcSNandor Licker if (!this->jump(LabelEnd))
216950b70dcSNandor Licker return false;
217950b70dcSNandor Licker this->emitLabel(LabelElse);
218950b70dcSNandor Licker if (!visitStmt(Else))
219950b70dcSNandor Licker return false;
220950b70dcSNandor Licker this->emitLabel(LabelEnd);
221950b70dcSNandor Licker } else {
222950b70dcSNandor Licker LabelTy LabelEnd = this->getLabel();
223950b70dcSNandor Licker if (!this->jumpFalse(LabelEnd))
224950b70dcSNandor Licker return false;
225950b70dcSNandor Licker if (!visitStmt(IS->getThen()))
226950b70dcSNandor Licker return false;
227950b70dcSNandor Licker this->emitLabel(LabelEnd);
228950b70dcSNandor Licker }
229950b70dcSNandor Licker
230950b70dcSNandor Licker return true;
231950b70dcSNandor Licker }
232950b70dcSNandor Licker
233950b70dcSNandor Licker template <class Emitter>
visitVarDecl(const VarDecl * VD)234950b70dcSNandor Licker bool ByteCodeStmtGen<Emitter>::visitVarDecl(const VarDecl *VD) {
235950b70dcSNandor Licker auto DT = VD->getType();
236950b70dcSNandor Licker
237950b70dcSNandor Licker if (!VD->hasLocalStorage()) {
238950b70dcSNandor Licker // No code generation required.
239950b70dcSNandor Licker return true;
240950b70dcSNandor Licker }
241950b70dcSNandor Licker
242950b70dcSNandor Licker // Integers, pointers, primitives.
243950b70dcSNandor Licker if (Optional<PrimType> T = this->classify(DT)) {
244950b70dcSNandor Licker auto Off = this->allocateLocalPrimitive(VD, *T, DT.isConstQualified());
245950b70dcSNandor Licker // Compile the initialiser in its own scope.
246950b70dcSNandor Licker {
247950b70dcSNandor Licker ExprScope<Emitter> Scope(this);
248950b70dcSNandor Licker if (!this->visit(VD->getInit()))
249950b70dcSNandor Licker return false;
250950b70dcSNandor Licker }
251950b70dcSNandor Licker // Set the value.
252950b70dcSNandor Licker return this->emitSetLocal(*T, Off, VD);
253950b70dcSNandor Licker } else {
254950b70dcSNandor Licker // Composite types - allocate storage and initialize it.
255950b70dcSNandor Licker if (auto Off = this->allocateLocal(VD)) {
256950b70dcSNandor Licker return this->visitLocalInitializer(VD->getInit(), *Off);
257950b70dcSNandor Licker } else {
258950b70dcSNandor Licker return this->bail(VD);
259950b70dcSNandor Licker }
260950b70dcSNandor Licker }
261950b70dcSNandor Licker }
262950b70dcSNandor Licker
263950b70dcSNandor Licker namespace clang {
264950b70dcSNandor Licker namespace interp {
265950b70dcSNandor Licker
266950b70dcSNandor Licker template class ByteCodeStmtGen<ByteCodeEmitter>;
267950b70dcSNandor Licker
268950b70dcSNandor Licker } // namespace interp
269950b70dcSNandor Licker } // namespace clang
270