ByteCodeExprGen.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. //===--- ByteCodeExprGen.h - 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. // Defines the constexpr bytecode compiler.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #ifndef LLVM_CLANG_AST_INTERP_BYTECODEEXPRGEN_H
  13. #define LLVM_CLANG_AST_INTERP_BYTECODEEXPRGEN_H
  14. #include "ByteCodeEmitter.h"
  15. #include "EvalEmitter.h"
  16. #include "Pointer.h"
  17. #include "PrimType.h"
  18. #include "Record.h"
  19. #include "clang/AST/Decl.h"
  20. #include "clang/AST/Expr.h"
  21. #include "clang/AST/StmtVisitor.h"
  22. #include "clang/Basic/TargetInfo.h"
  23. namespace clang {
  24. class QualType;
  25. namespace interp {
  26. template <class Emitter> class LocalScope;
  27. template <class Emitter> class RecordScope;
  28. template <class Emitter> class VariableScope;
  29. template <class Emitter> class DeclScope;
  30. template <class Emitter> class OptionScope;
  31. template <class Emitter> class ArrayIndexScope;
  32. /// Compilation context for expressions.
  33. template <class Emitter>
  34. class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
  35. public Emitter {
  36. protected:
  37. // Aliases for types defined in the emitter.
  38. using LabelTy = typename Emitter::LabelTy;
  39. using AddrTy = typename Emitter::AddrTy;
  40. /// Current compilation context.
  41. Context &Ctx;
  42. /// Program to link to.
  43. Program &P;
  44. public:
  45. /// Initializes the compiler and the backend emitter.
  46. template <typename... Tys>
  47. ByteCodeExprGen(Context &Ctx, Program &P, Tys &&... Args)
  48. : Emitter(Ctx, P, Args...), Ctx(Ctx), P(P) {}
  49. // Expression visitors - result returned on interp stack.
  50. bool VisitCastExpr(const CastExpr *E);
  51. bool VisitIntegerLiteral(const IntegerLiteral *E);
  52. bool VisitParenExpr(const ParenExpr *E);
  53. bool VisitBinaryOperator(const BinaryOperator *E);
  54. bool VisitPointerArithBinOp(const BinaryOperator *E);
  55. bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E);
  56. bool VisitCallExpr(const CallExpr *E);
  57. bool VisitCXXMemberCallExpr(const CXXMemberCallExpr *E);
  58. bool VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E);
  59. bool VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E);
  60. bool VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E);
  61. bool VisitCXXThisExpr(const CXXThisExpr *E);
  62. bool VisitUnaryOperator(const UnaryOperator *E);
  63. bool VisitDeclRefExpr(const DeclRefExpr *E);
  64. bool VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E);
  65. bool VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E);
  66. bool VisitArraySubscriptExpr(const ArraySubscriptExpr *E);
  67. bool VisitInitListExpr(const InitListExpr *E);
  68. bool VisitConstantExpr(const ConstantExpr *E);
  69. bool VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *E);
  70. bool VisitMemberExpr(const MemberExpr *E);
  71. bool VisitArrayInitIndexExpr(const ArrayInitIndexExpr *E);
  72. bool VisitOpaqueValueExpr(const OpaqueValueExpr *E);
  73. bool VisitAbstractConditionalOperator(const AbstractConditionalOperator *E);
  74. bool VisitStringLiteral(const StringLiteral *E);
  75. bool VisitCharacterLiteral(const CharacterLiteral *E);
  76. bool VisitCompoundAssignOperator(const CompoundAssignOperator *E);
  77. protected:
  78. bool visitExpr(const Expr *E) override;
  79. bool visitDecl(const VarDecl *VD) override;
  80. protected:
  81. /// Emits scope cleanup instructions.
  82. void emitCleanup();
  83. /// Returns a record type from a record or pointer type.
  84. const RecordType *getRecordTy(QualType Ty);
  85. /// Returns a record from a record or pointer type.
  86. Record *getRecord(QualType Ty);
  87. Record *getRecord(const RecordDecl *RD);
  88. // Returns a function for the given FunctionDecl.
  89. // If the function does not exist yet, it is compiled.
  90. const Function *getFunction(const FunctionDecl *FD);
  91. /// Classifies a type.
  92. std::optional<PrimType> classify(const Expr *E) const {
  93. return E->isGLValue() ? PT_Ptr : classify(E->getType());
  94. }
  95. std::optional<PrimType> classify(QualType Ty) const {
  96. return Ctx.classify(Ty);
  97. }
  98. /// Classifies a known primitive type
  99. PrimType classifyPrim(QualType Ty) const {
  100. if (auto T = classify(Ty)) {
  101. return *T;
  102. }
  103. llvm_unreachable("not a primitive type");
  104. }
  105. /// Evaluates an expression for side effects and discards the result.
  106. bool discard(const Expr *E);
  107. /// Evaluates an expression and places result on stack.
  108. bool visit(const Expr *E);
  109. /// Compiles an initializer.
  110. bool visitInitializer(const Expr *E);
  111. /// Compiles an array initializer.
  112. bool visitArrayInitializer(const Expr *Initializer);
  113. /// Compiles a record initializer.
  114. bool visitRecordInitializer(const Expr *Initializer);
  115. /// Creates and initializes a variable from the given decl.
  116. bool visitVarDecl(const VarDecl *VD);
  117. /// Visits an expression and converts it to a boolean.
  118. bool visitBool(const Expr *E);
  119. /// Visits an initializer for a local.
  120. bool visitLocalInitializer(const Expr *Init, unsigned I) {
  121. if (!this->emitGetPtrLocal(I, Init))
  122. return false;
  123. if (!visitInitializer(Init))
  124. return false;
  125. return this->emitPopPtr(Init);
  126. }
  127. /// Visits an initializer for a global.
  128. bool visitGlobalInitializer(const Expr *Init, unsigned I) {
  129. if (!this->emitGetPtrGlobal(I, Init))
  130. return false;
  131. if (!visitInitializer(Init))
  132. return false;
  133. return this->emitPopPtr(Init);
  134. }
  135. /// Visits a delegated initializer.
  136. bool visitThisInitializer(const Expr *I) {
  137. if (!this->emitThis(I))
  138. return false;
  139. if (!visitInitializer(I))
  140. return false;
  141. return this->emitPopPtr(I);
  142. }
  143. /// Creates a local primitive value.
  144. unsigned allocateLocalPrimitive(DeclTy &&Decl, PrimType Ty, bool IsMutable,
  145. bool IsExtended = false);
  146. /// Allocates a space storing a local given its type.
  147. std::optional<unsigned> allocateLocal(DeclTy &&Decl, bool IsExtended = false);
  148. private:
  149. friend class VariableScope<Emitter>;
  150. friend class LocalScope<Emitter>;
  151. friend class RecordScope<Emitter>;
  152. friend class DeclScope<Emitter>;
  153. friend class OptionScope<Emitter>;
  154. friend class ArrayIndexScope<Emitter>;
  155. /// Emits a zero initializer.
  156. bool visitZeroInitializer(PrimType T, const Expr *E);
  157. enum class DerefKind {
  158. /// Value is read and pushed to stack.
  159. Read,
  160. /// Direct method generates a value which is written. Returns pointer.
  161. Write,
  162. /// Direct method receives the value, pushes mutated value. Returns pointer.
  163. ReadWrite,
  164. };
  165. /// Method to directly load a value. If the value can be fetched directly,
  166. /// the direct handler is called. Otherwise, a pointer is left on the stack
  167. /// and the indirect handler is expected to operate on that.
  168. bool dereference(const Expr *LV, DerefKind AK,
  169. llvm::function_ref<bool(PrimType)> Direct,
  170. llvm::function_ref<bool(PrimType)> Indirect);
  171. bool dereferenceParam(const Expr *LV, PrimType T, const ParmVarDecl *PD,
  172. DerefKind AK,
  173. llvm::function_ref<bool(PrimType)> Direct,
  174. llvm::function_ref<bool(PrimType)> Indirect);
  175. bool dereferenceVar(const Expr *LV, PrimType T, const VarDecl *PD,
  176. DerefKind AK, llvm::function_ref<bool(PrimType)> Direct,
  177. llvm::function_ref<bool(PrimType)> Indirect);
  178. /// Emits an APSInt constant.
  179. bool emitConst(const APSInt &Value, const Expr *E);
  180. bool emitConst(const APInt &Value, const Expr *E) {
  181. return emitConst(static_cast<APSInt>(Value), E);
  182. }
  183. /// Emits an integer constant.
  184. template <typename T> bool emitConst(T Value, const Expr *E);
  185. /// Returns the CXXRecordDecl for the type of the given expression,
  186. /// or nullptr if no such decl exists.
  187. const CXXRecordDecl *getRecordDecl(const Expr *E) const {
  188. QualType T = E->getType();
  189. if (const auto *RD = T->getPointeeCXXRecordDecl())
  190. return RD;
  191. return T->getAsCXXRecordDecl();
  192. }
  193. /// Returns whether we should create a global variable for the
  194. /// given VarDecl.
  195. bool shouldBeGloballyIndexed(const VarDecl *VD) const {
  196. return VD->hasGlobalStorage() || VD->isConstexpr();
  197. }
  198. protected:
  199. /// Variable to storage mapping.
  200. llvm::DenseMap<const ValueDecl *, Scope::Local> Locals;
  201. /// OpaqueValueExpr to location mapping.
  202. llvm::DenseMap<const OpaqueValueExpr *, unsigned> OpaqueExprs;
  203. /// Current scope.
  204. VariableScope<Emitter> *VarScope = nullptr;
  205. /// Current argument index. Needed to emit ArrayInitIndexExpr.
  206. std::optional<uint64_t> ArrayIndex;
  207. /// Flag indicating if return value is to be discarded.
  208. bool DiscardResult = false;
  209. };
  210. extern template class ByteCodeExprGen<ByteCodeEmitter>;
  211. extern template class ByteCodeExprGen<EvalEmitter>;
  212. /// Scope chain managing the variable lifetimes.
  213. template <class Emitter> class VariableScope {
  214. public:
  215. VariableScope(ByteCodeExprGen<Emitter> *Ctx)
  216. : Ctx(Ctx), Parent(Ctx->VarScope) {
  217. Ctx->VarScope = this;
  218. }
  219. virtual ~VariableScope() { Ctx->VarScope = this->Parent; }
  220. void add(const Scope::Local &Local, bool IsExtended) {
  221. if (IsExtended)
  222. this->addExtended(Local);
  223. else
  224. this->addLocal(Local);
  225. }
  226. virtual void addLocal(const Scope::Local &Local) {
  227. if (this->Parent)
  228. this->Parent->addLocal(Local);
  229. }
  230. virtual void addExtended(const Scope::Local &Local) {
  231. if (this->Parent)
  232. this->Parent->addExtended(Local);
  233. }
  234. virtual void emitDestruction() {}
  235. VariableScope *getParent() { return Parent; }
  236. protected:
  237. /// ByteCodeExprGen instance.
  238. ByteCodeExprGen<Emitter> *Ctx;
  239. /// Link to the parent scope.
  240. VariableScope *Parent;
  241. };
  242. /// Scope for local variables.
  243. ///
  244. /// When the scope is destroyed, instructions are emitted to tear down
  245. /// all variables declared in this scope.
  246. template <class Emitter> class LocalScope : public VariableScope<Emitter> {
  247. public:
  248. LocalScope(ByteCodeExprGen<Emitter> *Ctx) : VariableScope<Emitter>(Ctx) {}
  249. ~LocalScope() override { this->emitDestruction(); }
  250. void addLocal(const Scope::Local &Local) override {
  251. if (!Idx) {
  252. Idx = this->Ctx->Descriptors.size();
  253. this->Ctx->Descriptors.emplace_back();
  254. }
  255. this->Ctx->Descriptors[*Idx].emplace_back(Local);
  256. }
  257. void emitDestruction() override {
  258. if (!Idx)
  259. return;
  260. this->Ctx->emitDestroy(*Idx, SourceInfo{});
  261. }
  262. protected:
  263. /// Index of the scope in the chain.
  264. std::optional<unsigned> Idx;
  265. };
  266. /// Scope for storage declared in a compound statement.
  267. template <class Emitter> class BlockScope final : public LocalScope<Emitter> {
  268. public:
  269. BlockScope(ByteCodeExprGen<Emitter> *Ctx) : LocalScope<Emitter>(Ctx) {}
  270. void addExtended(const Scope::Local &Local) override {
  271. llvm_unreachable("Cannot create temporaries in full scopes");
  272. }
  273. };
  274. /// Expression scope which tracks potentially lifetime extended
  275. /// temporaries which are hoisted to the parent scope on exit.
  276. template <class Emitter> class ExprScope final : public LocalScope<Emitter> {
  277. public:
  278. ExprScope(ByteCodeExprGen<Emitter> *Ctx) : LocalScope<Emitter>(Ctx) {}
  279. void addExtended(const Scope::Local &Local) override {
  280. assert(this->Parent);
  281. this->Parent->addLocal(Local);
  282. }
  283. };
  284. template <class Emitter> class ArrayIndexScope final {
  285. public:
  286. ArrayIndexScope(ByteCodeExprGen<Emitter> *Ctx, uint64_t Index) : Ctx(Ctx) {
  287. OldArrayIndex = Ctx->ArrayIndex;
  288. Ctx->ArrayIndex = Index;
  289. }
  290. ~ArrayIndexScope() { Ctx->ArrayIndex = OldArrayIndex; }
  291. private:
  292. ByteCodeExprGen<Emitter> *Ctx;
  293. std::optional<uint64_t> OldArrayIndex;
  294. };
  295. } // namespace interp
  296. } // namespace clang
  297. #endif