ByteCodeStmtGen.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  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. #include "ByteCodeStmtGen.h"
  9. #include "ByteCodeEmitter.h"
  10. #include "ByteCodeGenError.h"
  11. #include "Context.h"
  12. #include "Function.h"
  13. #include "Program.h"
  14. #include "State.h"
  15. #include "Type.h"
  16. using namespace clang;
  17. using namespace clang::interp;
  18. template <typename T> using Expected = llvm::Expected<T>;
  19. template <typename T> using Optional = llvm::Optional<T>;
  20. namespace clang {
  21. namespace interp {
  22. /// Scope managing label targets.
  23. template <class Emitter> class LabelScope {
  24. public:
  25. virtual ~LabelScope() { }
  26. protected:
  27. LabelScope(ByteCodeStmtGen<Emitter> *Ctx) : Ctx(Ctx) {}
  28. /// ByteCodeStmtGen instance.
  29. ByteCodeStmtGen<Emitter> *Ctx;
  30. };
  31. /// Sets the context for break/continue statements.
  32. template <class Emitter> class LoopScope final : public LabelScope<Emitter> {
  33. public:
  34. using LabelTy = typename ByteCodeStmtGen<Emitter>::LabelTy;
  35. using OptLabelTy = typename ByteCodeStmtGen<Emitter>::OptLabelTy;
  36. LoopScope(ByteCodeStmtGen<Emitter> *Ctx, LabelTy BreakLabel,
  37. LabelTy ContinueLabel)
  38. : LabelScope<Emitter>(Ctx), OldBreakLabel(Ctx->BreakLabel),
  39. OldContinueLabel(Ctx->ContinueLabel) {
  40. this->Ctx->BreakLabel = BreakLabel;
  41. this->Ctx->ContinueLabel = ContinueLabel;
  42. }
  43. ~LoopScope() {
  44. this->Ctx->BreakLabel = OldBreakLabel;
  45. this->Ctx->ContinueLabel = OldContinueLabel;
  46. }
  47. private:
  48. OptLabelTy OldBreakLabel;
  49. OptLabelTy OldContinueLabel;
  50. };
  51. // Sets the context for a switch scope, mapping labels.
  52. template <class Emitter> class SwitchScope final : public LabelScope<Emitter> {
  53. public:
  54. using LabelTy = typename ByteCodeStmtGen<Emitter>::LabelTy;
  55. using OptLabelTy = typename ByteCodeStmtGen<Emitter>::OptLabelTy;
  56. using CaseMap = typename ByteCodeStmtGen<Emitter>::CaseMap;
  57. SwitchScope(ByteCodeStmtGen<Emitter> *Ctx, CaseMap &&CaseLabels,
  58. LabelTy BreakLabel, OptLabelTy DefaultLabel)
  59. : LabelScope<Emitter>(Ctx), OldBreakLabel(Ctx->BreakLabel),
  60. OldDefaultLabel(this->Ctx->DefaultLabel),
  61. OldCaseLabels(std::move(this->Ctx->CaseLabels)) {
  62. this->Ctx->BreakLabel = BreakLabel;
  63. this->Ctx->DefaultLabel = DefaultLabel;
  64. this->Ctx->CaseLabels = std::move(CaseLabels);
  65. }
  66. ~SwitchScope() {
  67. this->Ctx->BreakLabel = OldBreakLabel;
  68. this->Ctx->DefaultLabel = OldDefaultLabel;
  69. this->Ctx->CaseLabels = std::move(OldCaseLabels);
  70. }
  71. private:
  72. OptLabelTy OldBreakLabel;
  73. OptLabelTy OldDefaultLabel;
  74. CaseMap OldCaseLabels;
  75. };
  76. } // namespace interp
  77. } // namespace clang
  78. template <class Emitter>
  79. bool ByteCodeStmtGen<Emitter>::visitFunc(const FunctionDecl *F) {
  80. // Classify the return type.
  81. ReturnType = this->classify(F->getReturnType());
  82. // Set up fields and context if a constructor.
  83. if (auto *MD = dyn_cast<CXXMethodDecl>(F))
  84. return this->bail(MD);
  85. if (auto *Body = F->getBody())
  86. if (!visitStmt(Body))
  87. return false;
  88. // Emit a guard return to protect against a code path missing one.
  89. if (F->getReturnType()->isVoidType())
  90. return this->emitRetVoid(SourceInfo{});
  91. else
  92. return this->emitNoRet(SourceInfo{});
  93. }
  94. template <class Emitter>
  95. bool ByteCodeStmtGen<Emitter>::visitStmt(const Stmt *S) {
  96. switch (S->getStmtClass()) {
  97. case Stmt::CompoundStmtClass:
  98. return visitCompoundStmt(cast<CompoundStmt>(S));
  99. case Stmt::DeclStmtClass:
  100. return visitDeclStmt(cast<DeclStmt>(S));
  101. case Stmt::ReturnStmtClass:
  102. return visitReturnStmt(cast<ReturnStmt>(S));
  103. case Stmt::IfStmtClass:
  104. return visitIfStmt(cast<IfStmt>(S));
  105. case Stmt::NullStmtClass:
  106. return true;
  107. default: {
  108. if (auto *Exp = dyn_cast<Expr>(S))
  109. return this->discard(Exp);
  110. return this->bail(S);
  111. }
  112. }
  113. }
  114. template <class Emitter>
  115. bool ByteCodeStmtGen<Emitter>::visitCompoundStmt(
  116. const CompoundStmt *CompoundStmt) {
  117. BlockScope<Emitter> Scope(this);
  118. for (auto *InnerStmt : CompoundStmt->body())
  119. if (!visitStmt(InnerStmt))
  120. return false;
  121. return true;
  122. }
  123. template <class Emitter>
  124. bool ByteCodeStmtGen<Emitter>::visitDeclStmt(const DeclStmt *DS) {
  125. for (auto *D : DS->decls()) {
  126. // Variable declarator.
  127. if (auto *VD = dyn_cast<VarDecl>(D)) {
  128. if (!visitVarDecl(VD))
  129. return false;
  130. continue;
  131. }
  132. // Decomposition declarator.
  133. if (auto *DD = dyn_cast<DecompositionDecl>(D)) {
  134. return this->bail(DD);
  135. }
  136. }
  137. return true;
  138. }
  139. template <class Emitter>
  140. bool ByteCodeStmtGen<Emitter>::visitReturnStmt(const ReturnStmt *RS) {
  141. if (const Expr *RE = RS->getRetValue()) {
  142. ExprScope<Emitter> RetScope(this);
  143. if (ReturnType) {
  144. // Primitive types are simply returned.
  145. if (!this->visit(RE))
  146. return false;
  147. this->emitCleanup();
  148. return this->emitRet(*ReturnType, RS);
  149. } else {
  150. // RVO - construct the value in the return location.
  151. auto ReturnLocation = [this, RE] { return this->emitGetParamPtr(0, RE); };
  152. if (!this->visitInitializer(RE, ReturnLocation))
  153. return false;
  154. this->emitCleanup();
  155. return this->emitRetVoid(RS);
  156. }
  157. } else {
  158. this->emitCleanup();
  159. if (!this->emitRetVoid(RS))
  160. return false;
  161. return true;
  162. }
  163. }
  164. template <class Emitter>
  165. bool ByteCodeStmtGen<Emitter>::visitIfStmt(const IfStmt *IS) {
  166. BlockScope<Emitter> IfScope(this);
  167. if (auto *CondInit = IS->getInit())
  168. if (!visitStmt(IS->getInit()))
  169. return false;
  170. if (const DeclStmt *CondDecl = IS->getConditionVariableDeclStmt())
  171. if (!visitDeclStmt(CondDecl))
  172. return false;
  173. if (!this->visitBool(IS->getCond()))
  174. return false;
  175. if (const Stmt *Else = IS->getElse()) {
  176. LabelTy LabelElse = this->getLabel();
  177. LabelTy LabelEnd = this->getLabel();
  178. if (!this->jumpFalse(LabelElse))
  179. return false;
  180. if (!visitStmt(IS->getThen()))
  181. return false;
  182. if (!this->jump(LabelEnd))
  183. return false;
  184. this->emitLabel(LabelElse);
  185. if (!visitStmt(Else))
  186. return false;
  187. this->emitLabel(LabelEnd);
  188. } else {
  189. LabelTy LabelEnd = this->getLabel();
  190. if (!this->jumpFalse(LabelEnd))
  191. return false;
  192. if (!visitStmt(IS->getThen()))
  193. return false;
  194. this->emitLabel(LabelEnd);
  195. }
  196. return true;
  197. }
  198. template <class Emitter>
  199. bool ByteCodeStmtGen<Emitter>::visitVarDecl(const VarDecl *VD) {
  200. auto DT = VD->getType();
  201. if (!VD->hasLocalStorage()) {
  202. // No code generation required.
  203. return true;
  204. }
  205. // Integers, pointers, primitives.
  206. if (Optional<PrimType> T = this->classify(DT)) {
  207. auto Off = this->allocateLocalPrimitive(VD, *T, DT.isConstQualified());
  208. // Compile the initialiser in its own scope.
  209. {
  210. ExprScope<Emitter> Scope(this);
  211. if (!this->visit(VD->getInit()))
  212. return false;
  213. }
  214. // Set the value.
  215. return this->emitSetLocal(*T, Off, VD);
  216. } else {
  217. // Composite types - allocate storage and initialize it.
  218. if (auto Off = this->allocateLocal(VD)) {
  219. return this->visitLocalInitializer(VD->getInit(), *Off);
  220. } else {
  221. return this->bail(VD);
  222. }
  223. }
  224. }
  225. namespace clang {
  226. namespace interp {
  227. template class ByteCodeStmtGen<ByteCodeEmitter>;
  228. } // namespace interp
  229. } // namespace clang