ByteCodeExprGen.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  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 "llvm/ADT/Optional.h"
  23. namespace clang {
  24. class QualType;
  25. namespace interp {
  26. class Function;
  27. class State;
  28. template <class Emitter> class LocalScope;
  29. template <class Emitter> class RecordScope;
  30. template <class Emitter> class VariableScope;
  31. template <class Emitter> class DeclScope;
  32. template <class Emitter> class OptionScope;
  33. /// Compilation context for expressions.
  34. template <class Emitter>
  35. class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
  36. public Emitter {
  37. protected:
  38. // Emitters for opcodes of various arities.
  39. using NullaryFn = bool (ByteCodeExprGen::*)(const SourceInfo &);
  40. using UnaryFn = bool (ByteCodeExprGen::*)(PrimType, const SourceInfo &);
  41. using BinaryFn = bool (ByteCodeExprGen::*)(PrimType, PrimType,
  42. const SourceInfo &);
  43. // Aliases for types defined in the emitter.
  44. using LabelTy = typename Emitter::LabelTy;
  45. using AddrTy = typename Emitter::AddrTy;
  46. // Reference to a function generating the pointer of an initialized object.s
  47. using InitFnRef = std::function<bool()>;
  48. /// Current compilation context.
  49. Context &Ctx;
  50. /// Program to link to.
  51. Program &P;
  52. public:
  53. /// Initializes the compiler and the backend emitter.
  54. template <typename... Tys>
  55. ByteCodeExprGen(Context &Ctx, Program &P, Tys &&... Args)
  56. : Emitter(Ctx, P, Args...), Ctx(Ctx), P(P) {}
  57. // Expression visitors - result returned on stack.
  58. bool VisitCastExpr(const CastExpr *E);
  59. bool VisitIntegerLiteral(const IntegerLiteral *E);
  60. bool VisitParenExpr(const ParenExpr *E);
  61. bool VisitBinaryOperator(const BinaryOperator *E);
  62. protected:
  63. bool visitExpr(const Expr *E) override;
  64. bool visitDecl(const VarDecl *VD) override;
  65. protected:
  66. /// Emits scope cleanup instructions.
  67. void emitCleanup();
  68. /// Returns a record type from a record or pointer type.
  69. const RecordType *getRecordTy(QualType Ty);
  70. /// Returns a record from a record or pointer type.
  71. Record *getRecord(QualType Ty);
  72. Record *getRecord(const RecordDecl *RD);
  73. /// Returns the size int bits of an integer.
  74. unsigned getIntWidth(QualType Ty) {
  75. auto &ASTContext = Ctx.getASTContext();
  76. return ASTContext.getIntWidth(Ty);
  77. }
  78. /// Returns the value of CHAR_BIT.
  79. unsigned getCharBit() const {
  80. auto &ASTContext = Ctx.getASTContext();
  81. return ASTContext.getTargetInfo().getCharWidth();
  82. }
  83. /// Classifies a type.
  84. llvm::Optional<PrimType> classify(const Expr *E) const {
  85. return E->isGLValue() ? PT_Ptr : classify(E->getType());
  86. }
  87. llvm::Optional<PrimType> classify(QualType Ty) const {
  88. return Ctx.classify(Ty);
  89. }
  90. /// Checks if a pointer needs adjustment.
  91. bool needsAdjust(QualType Ty) const {
  92. return true;
  93. }
  94. /// Classifies a known primitive type
  95. PrimType classifyPrim(QualType Ty) const {
  96. if (auto T = classify(Ty)) {
  97. return *T;
  98. }
  99. llvm_unreachable("not a primitive type");
  100. }
  101. /// Evaluates an expression for side effects and discards the result.
  102. bool discard(const Expr *E);
  103. /// Evaluates an expression and places result on stack.
  104. bool visit(const Expr *E);
  105. /// Compiles an initializer for a local.
  106. bool visitInitializer(const Expr *E, InitFnRef GenPtr);
  107. /// Visits an expression and converts it to a boolean.
  108. bool visitBool(const Expr *E);
  109. /// Visits an initializer for a local.
  110. bool visitLocalInitializer(const Expr *Init, unsigned I) {
  111. return visitInitializer(Init, [this, I, Init] {
  112. return this->emitGetPtrLocal(I, Init);
  113. });
  114. }
  115. /// Visits an initializer for a global.
  116. bool visitGlobalInitializer(const Expr *Init, unsigned I) {
  117. return visitInitializer(Init, [this, I, Init] {
  118. return this->emitGetPtrGlobal(I, Init);
  119. });
  120. }
  121. /// Visits a delegated initializer.
  122. bool visitThisInitializer(const Expr *I) {
  123. return visitInitializer(I, [this, I] { return this->emitThis(I); });
  124. }
  125. /// Creates a local primitive value.
  126. unsigned allocateLocalPrimitive(DeclTy &&Decl, PrimType Ty, bool IsMutable,
  127. bool IsExtended = false);
  128. /// Allocates a space storing a local given its type.
  129. llvm::Optional<unsigned> allocateLocal(DeclTy &&Decl,
  130. bool IsExtended = false);
  131. private:
  132. friend class VariableScope<Emitter>;
  133. friend class LocalScope<Emitter>;
  134. friend class RecordScope<Emitter>;
  135. friend class DeclScope<Emitter>;
  136. friend class OptionScope<Emitter>;
  137. /// Emits a zero initializer.
  138. bool visitZeroInitializer(PrimType T, const Expr *E);
  139. enum class DerefKind {
  140. /// Value is read and pushed to stack.
  141. Read,
  142. /// Direct method generates a value which is written. Returns pointer.
  143. Write,
  144. /// Direct method receives the value, pushes mutated value. Returns pointer.
  145. ReadWrite,
  146. };
  147. /// Method to directly load a value. If the value can be fetched directly,
  148. /// the direct handler is called. Otherwise, a pointer is left on the stack
  149. /// and the indirect handler is expected to operate on that.
  150. bool dereference(const Expr *LV, DerefKind AK,
  151. llvm::function_ref<bool(PrimType)> Direct,
  152. llvm::function_ref<bool(PrimType)> Indirect);
  153. bool dereferenceParam(const Expr *LV, PrimType T, const ParmVarDecl *PD,
  154. DerefKind AK,
  155. llvm::function_ref<bool(PrimType)> Direct,
  156. llvm::function_ref<bool(PrimType)> Indirect);
  157. bool dereferenceVar(const Expr *LV, PrimType T, const VarDecl *PD,
  158. DerefKind AK, llvm::function_ref<bool(PrimType)> Direct,
  159. llvm::function_ref<bool(PrimType)> Indirect);
  160. /// Emits an APInt constant.
  161. bool emitConst(PrimType T, unsigned NumBits, const llvm::APInt &Value,
  162. const Expr *E);
  163. /// Emits an integer constant.
  164. template <typename T> bool emitConst(const Expr *E, T Value) {
  165. QualType Ty = E->getType();
  166. unsigned NumBits = getIntWidth(Ty);
  167. APInt WrappedValue(NumBits, Value, std::is_signed<T>::value);
  168. return emitConst(*Ctx.classify(Ty), NumBits, WrappedValue, E);
  169. }
  170. /// Returns a pointer to a variable declaration.
  171. bool getPtrVarDecl(const VarDecl *VD, const Expr *E);
  172. /// Returns the index of a global.
  173. llvm::Optional<unsigned> getGlobalIdx(const VarDecl *VD);
  174. /// Emits the initialized pointer.
  175. bool emitInitFn() {
  176. assert(InitFn && "missing initializer");
  177. return (*InitFn)();
  178. }
  179. protected:
  180. /// Variable to storage mapping.
  181. llvm::DenseMap<const ValueDecl *, Scope::Local> Locals;
  182. /// OpaqueValueExpr to location mapping.
  183. llvm::DenseMap<const OpaqueValueExpr *, unsigned> OpaqueExprs;
  184. /// Current scope.
  185. VariableScope<Emitter> *VarScope = nullptr;
  186. /// Current argument index.
  187. llvm::Optional<uint64_t> ArrayIndex;
  188. /// Flag indicating if return value is to be discarded.
  189. bool DiscardResult = false;
  190. /// Expression being initialized.
  191. llvm::Optional<InitFnRef> InitFn = {};
  192. };
  193. extern template class ByteCodeExprGen<ByteCodeEmitter>;
  194. extern template class ByteCodeExprGen<EvalEmitter>;
  195. /// Scope chain managing the variable lifetimes.
  196. template <class Emitter> class VariableScope {
  197. public:
  198. virtual ~VariableScope() { Ctx->VarScope = this->Parent; }
  199. void add(const Scope::Local &Local, bool IsExtended) {
  200. if (IsExtended)
  201. this->addExtended(Local);
  202. else
  203. this->addLocal(Local);
  204. }
  205. virtual void addLocal(const Scope::Local &Local) {
  206. if (this->Parent)
  207. this->Parent->addLocal(Local);
  208. }
  209. virtual void addExtended(const Scope::Local &Local) {
  210. if (this->Parent)
  211. this->Parent->addExtended(Local);
  212. }
  213. virtual void emitDestruction() {}
  214. VariableScope *getParent() { return Parent; }
  215. protected:
  216. VariableScope(ByteCodeExprGen<Emitter> *Ctx)
  217. : Ctx(Ctx), Parent(Ctx->VarScope) {
  218. Ctx->VarScope = this;
  219. }
  220. /// ByteCodeExprGen instance.
  221. ByteCodeExprGen<Emitter> *Ctx;
  222. /// Link to the parent scope.
  223. VariableScope *Parent;
  224. };
  225. /// Scope for local variables.
  226. ///
  227. /// When the scope is destroyed, instructions are emitted to tear down
  228. /// all variables declared in this scope.
  229. template <class Emitter> class LocalScope : public VariableScope<Emitter> {
  230. public:
  231. LocalScope(ByteCodeExprGen<Emitter> *Ctx) : VariableScope<Emitter>(Ctx) {}
  232. ~LocalScope() override { this->emitDestruction(); }
  233. void addLocal(const Scope::Local &Local) override {
  234. if (!Idx.hasValue()) {
  235. Idx = this->Ctx->Descriptors.size();
  236. this->Ctx->Descriptors.emplace_back();
  237. }
  238. this->Ctx->Descriptors[*Idx].emplace_back(Local);
  239. }
  240. void emitDestruction() override {
  241. if (!Idx.hasValue())
  242. return;
  243. this->Ctx->emitDestroy(*Idx, SourceInfo{});
  244. }
  245. protected:
  246. /// Index of the scope in the chain.
  247. Optional<unsigned> Idx;
  248. };
  249. /// Scope for storage declared in a compound statement.
  250. template <class Emitter> class BlockScope final : public LocalScope<Emitter> {
  251. public:
  252. BlockScope(ByteCodeExprGen<Emitter> *Ctx) : LocalScope<Emitter>(Ctx) {}
  253. void addExtended(const Scope::Local &Local) override {
  254. llvm_unreachable("Cannot create temporaries in full scopes");
  255. }
  256. };
  257. /// Expression scope which tracks potentially lifetime extended
  258. /// temporaries which are hoisted to the parent scope on exit.
  259. template <class Emitter> class ExprScope final : public LocalScope<Emitter> {
  260. public:
  261. ExprScope(ByteCodeExprGen<Emitter> *Ctx) : LocalScope<Emitter>(Ctx) {}
  262. void addExtended(const Scope::Local &Local) override {
  263. this->Parent->addLocal(Local);
  264. }
  265. };
  266. } // namespace interp
  267. } // namespace clang
  268. #endif