ByteCodeStmtGen.cpp 7.4 KB

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