clang  10.0.0svn
ByteCodeStmtGen.cpp
Go to the documentation of this file.
1 //===--- ByteCodeStmtGen.cpp - Code generator for expressions ---*- 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 "ByteCodeStmtGen.h"
10 #include "ByteCodeEmitter.h"
11 #include "ByteCodeGenError.h"
12 #include "Context.h"
13 #include "Function.h"
14 #include "PrimType.h"
15 #include "Program.h"
16 #include "State.h"
17 
18 using namespace clang;
19 using namespace clang::interp;
20 
21 template <typename T> using Expected = llvm::Expected<T>;
22 template <typename T> using Optional = llvm::Optional<T>;
23 
24 namespace clang {
25 namespace interp {
26 
27 /// Scope managing label targets.
28 template <class Emitter> class LabelScope {
29 public:
30  virtual ~LabelScope() { }
31 
32 protected:
34  /// ByteCodeStmtGen instance.
36 };
37 
38 /// Sets the context for break/continue statements.
39 template <class Emitter> class LoopScope final : public LabelScope<Emitter> {
40 public:
41  using LabelTy = typename ByteCodeStmtGen<Emitter>::LabelTy;
43 
45  LabelTy ContinueLabel)
46  : LabelScope<Emitter>(Ctx), OldBreakLabel(Ctx->BreakLabel),
47  OldContinueLabel(Ctx->ContinueLabel) {
48  this->Ctx->BreakLabel = BreakLabel;
49  this->Ctx->ContinueLabel = ContinueLabel;
50  }
51 
53  this->Ctx->BreakLabel = OldBreakLabel;
54  this->Ctx->ContinueLabel = OldContinueLabel;
55  }
56 
57 private:
58  OptLabelTy OldBreakLabel;
59  OptLabelTy OldContinueLabel;
60 };
61 
62 // Sets the context for a switch scope, mapping labels.
63 template <class Emitter> class SwitchScope final : public LabelScope<Emitter> {
64 public:
65  using LabelTy = typename ByteCodeStmtGen<Emitter>::LabelTy;
67  using CaseMap = typename ByteCodeStmtGen<Emitter>::CaseMap;
68 
70  LabelTy BreakLabel, OptLabelTy DefaultLabel)
71  : LabelScope<Emitter>(Ctx), OldBreakLabel(Ctx->BreakLabel),
72  OldDefaultLabel(this->Ctx->DefaultLabel),
73  OldCaseLabels(std::move(this->Ctx->CaseLabels)) {
74  this->Ctx->BreakLabel = BreakLabel;
75  this->Ctx->DefaultLabel = DefaultLabel;
76  this->Ctx->CaseLabels = std::move(CaseLabels);
77  }
78 
80  this->Ctx->BreakLabel = OldBreakLabel;
81  this->Ctx->DefaultLabel = OldDefaultLabel;
82  this->Ctx->CaseLabels = std::move(OldCaseLabels);
83  }
84 
85 private:
86  OptLabelTy OldBreakLabel;
87  OptLabelTy OldDefaultLabel;
88  CaseMap OldCaseLabels;
89 };
90 
91 } // namespace interp
92 } // namespace clang
93 
94 template <class Emitter>
96  // Classify the return type.
97  ReturnType = this->classify(F->getReturnType());
98 
99  // Set up fields and context if a constructor.
100  if (auto *MD = dyn_cast<CXXMethodDecl>(F))
101  return this->bail(MD);
102 
103  if (auto *Body = F->getBody())
104  if (!visitStmt(Body))
105  return false;
106 
107  // Emit a guard return to protect against a code path missing one.
108  if (F->getReturnType()->isVoidType())
109  return this->emitRetVoid(SourceInfo{});
110  else
111  return this->emitNoRet(SourceInfo{});
112 }
113 
114 template <class Emitter>
116  switch (S->getStmtClass()) {
117  case Stmt::CompoundStmtClass:
118  return visitCompoundStmt(cast<CompoundStmt>(S));
119  case Stmt::DeclStmtClass:
120  return visitDeclStmt(cast<DeclStmt>(S));
121  case Stmt::ReturnStmtClass:
122  return visitReturnStmt(cast<ReturnStmt>(S));
123  case Stmt::IfStmtClass:
124  return visitIfStmt(cast<IfStmt>(S));
125  case Stmt::NullStmtClass:
126  return true;
127  default: {
128  if (auto *Exp = dyn_cast<Expr>(S))
129  return this->discard(Exp);
130  return this->bail(S);
131  }
132  }
133 }
134 
135 template <class Emitter>
137  const CompoundStmt *CompoundStmt) {
139  for (auto *InnerStmt : CompoundStmt->body())
140  if (!visitStmt(InnerStmt))
141  return false;
142  return true;
143 }
144 
145 template <class Emitter>
147  for (auto *D : DS->decls()) {
148  // Variable declarator.
149  if (auto *VD = dyn_cast<VarDecl>(D)) {
150  if (!visitVarDecl(VD))
151  return false;
152  continue;
153  }
154 
155  // Decomposition declarator.
156  if (auto *DD = dyn_cast<DecompositionDecl>(D)) {
157  return this->bail(DD);
158  }
159  }
160 
161  return true;
162 }
163 
164 template <class Emitter>
166  if (const Expr *RE = RS->getRetValue()) {
167  ExprScope<Emitter> RetScope(this);
168  if (ReturnType) {
169  // Primitive types are simply returned.
170  if (!this->visit(RE))
171  return false;
172  this->emitCleanup();
173  return this->emitRet(*ReturnType, RS);
174  } else {
175  // RVO - construct the value in the return location.
176  auto ReturnLocation = [this, RE] { return this->emitGetParamPtr(0, RE); };
177  if (!this->visitInitializer(RE, ReturnLocation))
178  return false;
179  this->emitCleanup();
180  return this->emitRetVoid(RS);
181  }
182  } else {
183  this->emitCleanup();
184  if (!this->emitRetVoid(RS))
185  return false;
186  return true;
187  }
188 }
189 
190 template <class Emitter>
192  BlockScope<Emitter> IfScope(this);
193  if (auto *CondInit = IS->getInit())
194  if (!visitStmt(IS->getInit()))
195  return false;
196 
197  if (const DeclStmt *CondDecl = IS->getConditionVariableDeclStmt())
198  if (!visitDeclStmt(CondDecl))
199  return false;
200 
201  if (!this->visitBool(IS->getCond()))
202  return false;
203 
204  if (const Stmt *Else = IS->getElse()) {
205  LabelTy LabelElse = this->getLabel();
206  LabelTy LabelEnd = this->getLabel();
207  if (!this->jumpFalse(LabelElse))
208  return false;
209  if (!visitStmt(IS->getThen()))
210  return false;
211  if (!this->jump(LabelEnd))
212  return false;
213  this->emitLabel(LabelElse);
214  if (!visitStmt(Else))
215  return false;
216  this->emitLabel(LabelEnd);
217  } else {
218  LabelTy LabelEnd = this->getLabel();
219  if (!this->jumpFalse(LabelEnd))
220  return false;
221  if (!visitStmt(IS->getThen()))
222  return false;
223  this->emitLabel(LabelEnd);
224  }
225 
226  return true;
227 }
228 
229 template <class Emitter>
231  auto DT = VD->getType();
232 
233  if (!VD->hasLocalStorage()) {
234  // No code generation required.
235  return true;
236  }
237 
238  // Integers, pointers, primitives.
239  if (Optional<PrimType> T = this->classify(DT)) {
240  auto Off = this->allocateLocalPrimitive(VD, *T, DT.isConstQualified());
241  // Compile the initialiser in its own scope.
242  {
244  if (!this->visit(VD->getInit()))
245  return false;
246  }
247  // Set the value.
248  return this->emitSetLocal(*T, Off, VD);
249  } else {
250  // Composite types - allocate storage and initialize it.
251  if (auto Off = this->allocateLocal(VD)) {
252  return this->visitLocalInitializer(VD->getInit(), *Off);
253  } else {
254  return this->bail(VD);
255  }
256  }
257 }
258 
259 namespace clang {
260 namespace interp {
261 
262 template class ByteCodeStmtGen<ByteCodeEmitter>;
263 
264 } // namespace interp
265 } // namespace clang
Represents a function declaration or definition.
Definition: Decl.h:1784
Sets the context for break/continue statements.
Stmt - This represents one statement.
Definition: Stmt.h:66
typename ByteCodeStmtGen< Emitter >::OptLabelTy OptLabelTy
IfStmt - This represents an if/then/else.
Definition: Stmt.h:1822
Scope managing label targets.
Represents a variable declaration or definition.
Definition: Decl.h:827
QualType getReturnType() const
Definition: Decl.h:2365
LoopScope(ByteCodeStmtGen< Emitter > *Ctx, LabelTy BreakLabel, LabelTy ContinueLabel)
Stmt * getThen()
Definition: Stmt.h:1909
Describes the statement/declaration an opcode was generated from.
Definition: Source.h:81
Compilation context for statements.
Definition: Format.h:2392
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
Definition: Decl.cpp:2849
typename ByteCodeStmtGen< Emitter >::OptLabelTy OptLabelTy
Stmt * getInit()
Definition: Stmt.h:1965
Expression scope which tracks potentially lifetime extended temporaries which are hoisted to the pare...
Scope for storage declared in a compound statement.
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition: Stmt.h:1320
This represents one expression.
Definition: Expr.h:108
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
Definition: Decl.h:1050
typename ByteCodeStmtGen< Emitter >::LabelTy LabelTy
ReturnStmt - This represents a return, optionally of an expression: return; return 4;...
Definition: Stmt.h:2620
Expr * getCond()
Definition: Stmt.h:1897
body_range body()
Definition: Stmt.h:1353
Expr * getRetValue()
Definition: Stmt.h:2653
Stmt * getElse()
Definition: Stmt.h:1918
DeclStmt - Adaptor class for mixing declarations with statements and expressions. ...
Definition: Stmt.h:1213
ByteCodeStmtGen< Emitter > * Ctx
ByteCodeStmtGen instance.
bool visitFunc(const FunctionDecl *F) override
typename ByteCodeStmtGen< Emitter >::CaseMap CaseMap
Dataflow Directional Tag Classes.
const Expr * getInit() const
Definition: Decl.h:1234
StmtClass getStmtClass() const
Definition: Stmt.h:1097
DeclStmt * getConditionVariableDeclStmt()
If this IfStmt has a condition variable, return the faux DeclStmt associated with the creation of tha...
Definition: Stmt.h:1953
decl_range decls()
Definition: Stmt.h:1261
LabelScope(ByteCodeStmtGen< Emitter > *Ctx)
bool isVoidType() const
Definition: Type.h:6650
typename Emitter::LabelTy LabelTy
Describes a scope block.
Definition: Function.h:32
typename ByteCodeStmtGen< Emitter >::LabelTy LabelTy
QualType getType() const
Definition: Decl.h:655
SwitchScope(ByteCodeStmtGen< Emitter > *Ctx, CaseMap &&CaseLabels, LabelTy BreakLabel, OptLabelTy DefaultLabel)