ByteCodeStmtGen.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  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. // Constructor. Set up field initializers.
  82. if (const auto Ctor = dyn_cast<CXXConstructorDecl>(F)) {
  83. const RecordDecl *RD = Ctor->getParent();
  84. const Record *R = this->getRecord(RD);
  85. if (!R)
  86. return false;
  87. for (const auto *Init : Ctor->inits()) {
  88. const Expr *InitExpr = Init->getInit();
  89. if (const FieldDecl *Member = Init->getMember()) {
  90. const Record::Field *F = R->getField(Member);
  91. if (std::optional<PrimType> T = this->classify(InitExpr)) {
  92. if (!this->emitThis(InitExpr))
  93. return false;
  94. if (!this->visit(InitExpr))
  95. return false;
  96. if (!this->emitInitField(*T, F->Offset, InitExpr))
  97. return false;
  98. if (!this->emitPopPtr(InitExpr))
  99. return false;
  100. } else {
  101. // Non-primitive case. Get a pointer to the field-to-initialize
  102. // on the stack and call visitInitialzer() for it.
  103. if (!this->emitThis(InitExpr))
  104. return false;
  105. if (!this->emitGetPtrField(F->Offset, InitExpr))
  106. return false;
  107. if (!this->visitInitializer(InitExpr))
  108. return false;
  109. if (!this->emitPopPtr(InitExpr))
  110. return false;
  111. }
  112. } else if (const Type *Base = Init->getBaseClass()) {
  113. // Base class initializer.
  114. // Get This Base and call initializer on it.
  115. auto *BaseDecl = Base->getAsCXXRecordDecl();
  116. assert(BaseDecl);
  117. const Record::Base *B = R->getBase(BaseDecl);
  118. assert(B);
  119. if (!this->emitGetPtrThisBase(B->Offset, InitExpr))
  120. return false;
  121. if (!this->visitInitializer(InitExpr))
  122. return false;
  123. if (!this->emitPopPtr(InitExpr))
  124. return false;
  125. }
  126. }
  127. }
  128. if (const auto *Body = F->getBody())
  129. if (!visitStmt(Body))
  130. return false;
  131. // Emit a guard return to protect against a code path missing one.
  132. if (F->getReturnType()->isVoidType())
  133. return this->emitRetVoid(SourceInfo{});
  134. else
  135. return this->emitNoRet(SourceInfo{});
  136. }
  137. template <class Emitter>
  138. bool ByteCodeStmtGen<Emitter>::visitStmt(const Stmt *S) {
  139. switch (S->getStmtClass()) {
  140. case Stmt::CompoundStmtClass:
  141. return visitCompoundStmt(cast<CompoundStmt>(S));
  142. case Stmt::DeclStmtClass:
  143. return visitDeclStmt(cast<DeclStmt>(S));
  144. case Stmt::ReturnStmtClass:
  145. return visitReturnStmt(cast<ReturnStmt>(S));
  146. case Stmt::IfStmtClass:
  147. return visitIfStmt(cast<IfStmt>(S));
  148. case Stmt::WhileStmtClass:
  149. return visitWhileStmt(cast<WhileStmt>(S));
  150. case Stmt::DoStmtClass:
  151. return visitDoStmt(cast<DoStmt>(S));
  152. case Stmt::ForStmtClass:
  153. return visitForStmt(cast<ForStmt>(S));
  154. case Stmt::BreakStmtClass:
  155. return visitBreakStmt(cast<BreakStmt>(S));
  156. case Stmt::ContinueStmtClass:
  157. return visitContinueStmt(cast<ContinueStmt>(S));
  158. case Stmt::NullStmtClass:
  159. return true;
  160. default: {
  161. if (auto *Exp = dyn_cast<Expr>(S))
  162. return this->discard(Exp);
  163. return this->bail(S);
  164. }
  165. }
  166. }
  167. template <class Emitter>
  168. bool ByteCodeStmtGen<Emitter>::visitCompoundStmt(
  169. const CompoundStmt *CompoundStmt) {
  170. BlockScope<Emitter> Scope(this);
  171. for (auto *InnerStmt : CompoundStmt->body())
  172. if (!visitStmt(InnerStmt))
  173. return false;
  174. return true;
  175. }
  176. template <class Emitter>
  177. bool ByteCodeStmtGen<Emitter>::visitDeclStmt(const DeclStmt *DS) {
  178. for (auto *D : DS->decls()) {
  179. // Variable declarator.
  180. if (auto *VD = dyn_cast<VarDecl>(D)) {
  181. if (!this->visitVarDecl(VD))
  182. return false;
  183. continue;
  184. }
  185. // Decomposition declarator.
  186. if (auto *DD = dyn_cast<DecompositionDecl>(D)) {
  187. return this->bail(DD);
  188. }
  189. }
  190. return true;
  191. }
  192. template <class Emitter>
  193. bool ByteCodeStmtGen<Emitter>::visitReturnStmt(const ReturnStmt *RS) {
  194. if (const Expr *RE = RS->getRetValue()) {
  195. ExprScope<Emitter> RetScope(this);
  196. if (ReturnType) {
  197. // Primitive types are simply returned.
  198. if (!this->visit(RE))
  199. return false;
  200. this->emitCleanup();
  201. return this->emitRet(*ReturnType, RS);
  202. } else {
  203. // RVO - construct the value in the return location.
  204. if (!this->emitRVOPtr(RE))
  205. return false;
  206. if (!this->visitInitializer(RE))
  207. return false;
  208. if (!this->emitPopPtr(RE))
  209. return false;
  210. this->emitCleanup();
  211. return this->emitRetVoid(RS);
  212. }
  213. }
  214. // Void return.
  215. this->emitCleanup();
  216. return this->emitRetVoid(RS);
  217. }
  218. template <class Emitter>
  219. bool ByteCodeStmtGen<Emitter>::visitIfStmt(const IfStmt *IS) {
  220. BlockScope<Emitter> IfScope(this);
  221. if (IS->isNonNegatedConsteval())
  222. return visitStmt(IS->getThen());
  223. if (IS->isNegatedConsteval())
  224. return IS->getElse() ? visitStmt(IS->getElse()) : true;
  225. if (auto *CondInit = IS->getInit())
  226. if (!visitStmt(IS->getInit()))
  227. return false;
  228. if (const DeclStmt *CondDecl = IS->getConditionVariableDeclStmt())
  229. if (!visitDeclStmt(CondDecl))
  230. return false;
  231. if (!this->visitBool(IS->getCond()))
  232. return false;
  233. if (const Stmt *Else = IS->getElse()) {
  234. LabelTy LabelElse = this->getLabel();
  235. LabelTy LabelEnd = this->getLabel();
  236. if (!this->jumpFalse(LabelElse))
  237. return false;
  238. if (!visitStmt(IS->getThen()))
  239. return false;
  240. if (!this->jump(LabelEnd))
  241. return false;
  242. this->emitLabel(LabelElse);
  243. if (!visitStmt(Else))
  244. return false;
  245. this->emitLabel(LabelEnd);
  246. } else {
  247. LabelTy LabelEnd = this->getLabel();
  248. if (!this->jumpFalse(LabelEnd))
  249. return false;
  250. if (!visitStmt(IS->getThen()))
  251. return false;
  252. this->emitLabel(LabelEnd);
  253. }
  254. return true;
  255. }
  256. template <class Emitter>
  257. bool ByteCodeStmtGen<Emitter>::visitWhileStmt(const WhileStmt *S) {
  258. const Expr *Cond = S->getCond();
  259. const Stmt *Body = S->getBody();
  260. LabelTy CondLabel = this->getLabel(); // Label before the condition.
  261. LabelTy EndLabel = this->getLabel(); // Label after the loop.
  262. LoopScope<Emitter> LS(this, EndLabel, CondLabel);
  263. this->emitLabel(CondLabel);
  264. if (!this->visitBool(Cond))
  265. return false;
  266. if (!this->jumpFalse(EndLabel))
  267. return false;
  268. if (!this->visitStmt(Body))
  269. return false;
  270. if (!this->jump(CondLabel))
  271. return false;
  272. this->emitLabel(EndLabel);
  273. return true;
  274. }
  275. template <class Emitter>
  276. bool ByteCodeStmtGen<Emitter>::visitDoStmt(const DoStmt *S) {
  277. const Expr *Cond = S->getCond();
  278. const Stmt *Body = S->getBody();
  279. LabelTy StartLabel = this->getLabel();
  280. LabelTy EndLabel = this->getLabel();
  281. LabelTy CondLabel = this->getLabel();
  282. LoopScope<Emitter> LS(this, EndLabel, CondLabel);
  283. this->emitLabel(StartLabel);
  284. if (!this->visitStmt(Body))
  285. return false;
  286. this->emitLabel(CondLabel);
  287. if (!this->visitBool(Cond))
  288. return false;
  289. if (!this->jumpTrue(StartLabel))
  290. return false;
  291. this->emitLabel(EndLabel);
  292. return true;
  293. }
  294. template <class Emitter>
  295. bool ByteCodeStmtGen<Emitter>::visitForStmt(const ForStmt *S) {
  296. // for (Init; Cond; Inc) { Body }
  297. const Stmt *Init = S->getInit();
  298. const Expr *Cond = S->getCond();
  299. const Expr *Inc = S->getInc();
  300. const Stmt *Body = S->getBody();
  301. LabelTy EndLabel = this->getLabel();
  302. LabelTy CondLabel = this->getLabel();
  303. LabelTy IncLabel = this->getLabel();
  304. LoopScope<Emitter> LS(this, EndLabel, IncLabel);
  305. if (Init && !this->visitStmt(Init))
  306. return false;
  307. this->emitLabel(CondLabel);
  308. if (Cond) {
  309. if (!this->visitBool(Cond))
  310. return false;
  311. if (!this->jumpFalse(EndLabel))
  312. return false;
  313. }
  314. if (Body && !this->visitStmt(Body))
  315. return false;
  316. this->emitLabel(IncLabel);
  317. if (Inc && !this->discard(Inc))
  318. return false;
  319. if (!this->jump(CondLabel))
  320. return false;
  321. this->emitLabel(EndLabel);
  322. return true;
  323. }
  324. template <class Emitter>
  325. bool ByteCodeStmtGen<Emitter>::visitBreakStmt(const BreakStmt *S) {
  326. if (!BreakLabel)
  327. return false;
  328. return this->jump(*BreakLabel);
  329. }
  330. template <class Emitter>
  331. bool ByteCodeStmtGen<Emitter>::visitContinueStmt(const ContinueStmt *S) {
  332. if (!ContinueLabel)
  333. return false;
  334. return this->jump(*ContinueLabel);
  335. }
  336. namespace clang {
  337. namespace interp {
  338. template class ByteCodeStmtGen<ByteCodeEmitter>;
  339. } // namespace interp
  340. } // namespace clang