1a07aba5dSTimm Baeder //===--- Compiler.h - Code generator for expressions -----*- C++ -*-===// 2a07aba5dSTimm Baeder // 3a07aba5dSTimm Baeder // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4a07aba5dSTimm Baeder // See https://llvm.org/LICENSE.txt for license information. 5a07aba5dSTimm Baeder // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6a07aba5dSTimm Baeder // 7a07aba5dSTimm Baeder //===----------------------------------------------------------------------===// 8a07aba5dSTimm Baeder // 9a07aba5dSTimm Baeder // Defines the constexpr bytecode compiler. 10a07aba5dSTimm Baeder // 11a07aba5dSTimm Baeder //===----------------------------------------------------------------------===// 12a07aba5dSTimm Baeder 13a07aba5dSTimm Baeder #ifndef LLVM_CLANG_AST_INTERP_BYTECODEEXPRGEN_H 14a07aba5dSTimm Baeder #define LLVM_CLANG_AST_INTERP_BYTECODEEXPRGEN_H 15a07aba5dSTimm Baeder 16a07aba5dSTimm Baeder #include "ByteCodeEmitter.h" 17a07aba5dSTimm Baeder #include "EvalEmitter.h" 18a07aba5dSTimm Baeder #include "Pointer.h" 19a07aba5dSTimm Baeder #include "PrimType.h" 20a07aba5dSTimm Baeder #include "Record.h" 21a07aba5dSTimm Baeder #include "clang/AST/Decl.h" 22a07aba5dSTimm Baeder #include "clang/AST/Expr.h" 23a07aba5dSTimm Baeder #include "clang/AST/StmtVisitor.h" 24a07aba5dSTimm Baeder #include "clang/Basic/TargetInfo.h" 25a07aba5dSTimm Baeder 26a07aba5dSTimm Baeder namespace clang { 27a07aba5dSTimm Baeder class QualType; 28a07aba5dSTimm Baeder 29a07aba5dSTimm Baeder namespace interp { 30a07aba5dSTimm Baeder 31a07aba5dSTimm Baeder template <class Emitter> class LocalScope; 32a07aba5dSTimm Baeder template <class Emitter> class DestructorScope; 33a07aba5dSTimm Baeder template <class Emitter> class VariableScope; 34a07aba5dSTimm Baeder template <class Emitter> class DeclScope; 35a07aba5dSTimm Baeder template <class Emitter> class InitLinkScope; 36a07aba5dSTimm Baeder template <class Emitter> class InitStackScope; 37a07aba5dSTimm Baeder template <class Emitter> class OptionScope; 38a07aba5dSTimm Baeder template <class Emitter> class ArrayIndexScope; 39a07aba5dSTimm Baeder template <class Emitter> class SourceLocScope; 40a07aba5dSTimm Baeder template <class Emitter> class LoopScope; 41a07aba5dSTimm Baeder template <class Emitter> class LabelScope; 42a07aba5dSTimm Baeder template <class Emitter> class SwitchScope; 43a07aba5dSTimm Baeder template <class Emitter> class StmtExprScope; 44a07aba5dSTimm Baeder 45a07aba5dSTimm Baeder template <class Emitter> class Compiler; 46a07aba5dSTimm Baeder struct InitLink { 47a07aba5dSTimm Baeder public: 48a07aba5dSTimm Baeder enum { 49a07aba5dSTimm Baeder K_This = 0, 50a07aba5dSTimm Baeder K_Field = 1, 51a07aba5dSTimm Baeder K_Temp = 2, 52a07aba5dSTimm Baeder K_Decl = 3, 53a07aba5dSTimm Baeder K_Elem = 5, 54*58fa55c0STimm Baeder K_RVO = 6, 55*58fa55c0STimm Baeder K_InitList = 7 56a07aba5dSTimm Baeder }; 57a07aba5dSTimm Baeder 58a07aba5dSTimm Baeder static InitLink This() { return InitLink{K_This}; } 59ac857f9bSTimm Baeder static InitLink InitList() { return InitLink{K_InitList}; } 60*58fa55c0STimm Baeder static InitLink RVO() { return InitLink{K_RVO}; } 61a07aba5dSTimm Baeder static InitLink Field(unsigned Offset) { 62a07aba5dSTimm Baeder InitLink IL{K_Field}; 63a07aba5dSTimm Baeder IL.Offset = Offset; 64a07aba5dSTimm Baeder return IL; 65a07aba5dSTimm Baeder } 66a07aba5dSTimm Baeder static InitLink Temp(unsigned Offset) { 67a07aba5dSTimm Baeder InitLink IL{K_Temp}; 68a07aba5dSTimm Baeder IL.Offset = Offset; 69a07aba5dSTimm Baeder return IL; 70a07aba5dSTimm Baeder } 71a07aba5dSTimm Baeder static InitLink Decl(const ValueDecl *D) { 72a07aba5dSTimm Baeder InitLink IL{K_Decl}; 73a07aba5dSTimm Baeder IL.D = D; 74a07aba5dSTimm Baeder return IL; 75a07aba5dSTimm Baeder } 76a07aba5dSTimm Baeder static InitLink Elem(unsigned Index) { 77a07aba5dSTimm Baeder InitLink IL{K_Elem}; 78a07aba5dSTimm Baeder IL.Offset = Index; 79a07aba5dSTimm Baeder return IL; 80a07aba5dSTimm Baeder } 81a07aba5dSTimm Baeder 82a07aba5dSTimm Baeder InitLink(uint8_t Kind) : Kind(Kind) {} 83a07aba5dSTimm Baeder template <class Emitter> 84a07aba5dSTimm Baeder bool emit(Compiler<Emitter> *Ctx, const Expr *E) const; 85a07aba5dSTimm Baeder 86a07aba5dSTimm Baeder uint32_t Kind; 87a07aba5dSTimm Baeder union { 88a07aba5dSTimm Baeder unsigned Offset; 89a07aba5dSTimm Baeder const ValueDecl *D; 90a07aba5dSTimm Baeder }; 91a07aba5dSTimm Baeder }; 92a07aba5dSTimm Baeder 93a07aba5dSTimm Baeder /// State encapsulating if a the variable creation has been successful, 94a07aba5dSTimm Baeder /// unsuccessful, or no variable has been created at all. 95a07aba5dSTimm Baeder struct VarCreationState { 96a07aba5dSTimm Baeder std::optional<bool> S = std::nullopt; 97a07aba5dSTimm Baeder VarCreationState() = default; 98a07aba5dSTimm Baeder VarCreationState(bool b) : S(b) {} 99a07aba5dSTimm Baeder static VarCreationState NotCreated() { return VarCreationState(); } 100a07aba5dSTimm Baeder 101a07aba5dSTimm Baeder operator bool() const { return S && *S; } 102a07aba5dSTimm Baeder bool notCreated() const { return !S; } 103a07aba5dSTimm Baeder }; 104a07aba5dSTimm Baeder 105a07aba5dSTimm Baeder /// Compilation context for expressions. 106a07aba5dSTimm Baeder template <class Emitter> 107a07aba5dSTimm Baeder class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>, 108a07aba5dSTimm Baeder public Emitter { 109a07aba5dSTimm Baeder protected: 110a07aba5dSTimm Baeder // Aliases for types defined in the emitter. 111a07aba5dSTimm Baeder using LabelTy = typename Emitter::LabelTy; 112a07aba5dSTimm Baeder using AddrTy = typename Emitter::AddrTy; 113a07aba5dSTimm Baeder using OptLabelTy = std::optional<LabelTy>; 114a07aba5dSTimm Baeder using CaseMap = llvm::DenseMap<const SwitchCase *, LabelTy>; 115a07aba5dSTimm Baeder 116a07aba5dSTimm Baeder /// Current compilation context. 117a07aba5dSTimm Baeder Context &Ctx; 118a07aba5dSTimm Baeder /// Program to link to. 119a07aba5dSTimm Baeder Program &P; 120a07aba5dSTimm Baeder 121a07aba5dSTimm Baeder public: 122a07aba5dSTimm Baeder /// Initializes the compiler and the backend emitter. 123a07aba5dSTimm Baeder template <typename... Tys> 124a07aba5dSTimm Baeder Compiler(Context &Ctx, Program &P, Tys &&...Args) 125a07aba5dSTimm Baeder : Emitter(Ctx, P, Args...), Ctx(Ctx), P(P) {} 126a07aba5dSTimm Baeder 127a07aba5dSTimm Baeder // Expressions. 128a07aba5dSTimm Baeder bool VisitCastExpr(const CastExpr *E); 129a07aba5dSTimm Baeder bool VisitIntegerLiteral(const IntegerLiteral *E); 130a07aba5dSTimm Baeder bool VisitFloatingLiteral(const FloatingLiteral *E); 131a07aba5dSTimm Baeder bool VisitImaginaryLiteral(const ImaginaryLiteral *E); 132048bc672STimm Baeder bool VisitFixedPointLiteral(const FixedPointLiteral *E); 133a07aba5dSTimm Baeder bool VisitParenExpr(const ParenExpr *E); 134a07aba5dSTimm Baeder bool VisitBinaryOperator(const BinaryOperator *E); 135a07aba5dSTimm Baeder bool VisitLogicalBinOp(const BinaryOperator *E); 136a07aba5dSTimm Baeder bool VisitPointerArithBinOp(const BinaryOperator *E); 137a07aba5dSTimm Baeder bool VisitComplexBinOp(const BinaryOperator *E); 13867f9183cSyronglin bool VisitVectorBinOp(const BinaryOperator *E); 1396b62e04eSTimm Baeder bool VisitFixedPointBinOp(const BinaryOperator *E); 14095ce78b7STimm Baeder bool VisitFixedPointUnaryOperator(const UnaryOperator *E); 141a07aba5dSTimm Baeder bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E); 142a07aba5dSTimm Baeder bool VisitCallExpr(const CallExpr *E); 14378cf9b83STimm Baeder bool VisitBuiltinCallExpr(const CallExpr *E, unsigned BuiltinID); 144a07aba5dSTimm Baeder bool VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E); 145a07aba5dSTimm Baeder bool VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E); 146a07aba5dSTimm Baeder bool VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E); 147a07aba5dSTimm Baeder bool VisitGNUNullExpr(const GNUNullExpr *E); 148a07aba5dSTimm Baeder bool VisitCXXThisExpr(const CXXThisExpr *E); 149a07aba5dSTimm Baeder bool VisitUnaryOperator(const UnaryOperator *E); 150ee0d7063Syronglin bool VisitVectorUnaryOperator(const UnaryOperator *E); 151a07aba5dSTimm Baeder bool VisitComplexUnaryOperator(const UnaryOperator *E); 152a07aba5dSTimm Baeder bool VisitDeclRefExpr(const DeclRefExpr *E); 153a07aba5dSTimm Baeder bool VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E); 154a07aba5dSTimm Baeder bool VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E); 155a07aba5dSTimm Baeder bool VisitArraySubscriptExpr(const ArraySubscriptExpr *E); 156a07aba5dSTimm Baeder bool VisitInitListExpr(const InitListExpr *E); 157a07aba5dSTimm Baeder bool VisitCXXParenListInitExpr(const CXXParenListInitExpr *E); 158a07aba5dSTimm Baeder bool VisitConstantExpr(const ConstantExpr *E); 159a07aba5dSTimm Baeder bool VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *E); 160a07aba5dSTimm Baeder bool VisitMemberExpr(const MemberExpr *E); 161a07aba5dSTimm Baeder bool VisitArrayInitIndexExpr(const ArrayInitIndexExpr *E); 162a07aba5dSTimm Baeder bool VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E); 163a07aba5dSTimm Baeder bool VisitOpaqueValueExpr(const OpaqueValueExpr *E); 164a07aba5dSTimm Baeder bool VisitAbstractConditionalOperator(const AbstractConditionalOperator *E); 165a07aba5dSTimm Baeder bool VisitStringLiteral(const StringLiteral *E); 166a07aba5dSTimm Baeder bool VisitObjCStringLiteral(const ObjCStringLiteral *E); 167a07aba5dSTimm Baeder bool VisitObjCEncodeExpr(const ObjCEncodeExpr *E); 168a07aba5dSTimm Baeder bool VisitSYCLUniqueStableNameExpr(const SYCLUniqueStableNameExpr *E); 169a07aba5dSTimm Baeder bool VisitCharacterLiteral(const CharacterLiteral *E); 170a07aba5dSTimm Baeder bool VisitCompoundAssignOperator(const CompoundAssignOperator *E); 171a07aba5dSTimm Baeder bool VisitFloatCompoundAssignOperator(const CompoundAssignOperator *E); 172a07aba5dSTimm Baeder bool VisitPointerCompoundAssignOperator(const CompoundAssignOperator *E); 173a07aba5dSTimm Baeder bool VisitExprWithCleanups(const ExprWithCleanups *E); 174a07aba5dSTimm Baeder bool VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E); 175a07aba5dSTimm Baeder bool VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *E); 176a07aba5dSTimm Baeder bool VisitCompoundLiteralExpr(const CompoundLiteralExpr *E); 177a07aba5dSTimm Baeder bool VisitTypeTraitExpr(const TypeTraitExpr *E); 178a07aba5dSTimm Baeder bool VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E); 179a07aba5dSTimm Baeder bool VisitLambdaExpr(const LambdaExpr *E); 180a07aba5dSTimm Baeder bool VisitPredefinedExpr(const PredefinedExpr *E); 181a07aba5dSTimm Baeder bool VisitCXXThrowExpr(const CXXThrowExpr *E); 182a07aba5dSTimm Baeder bool VisitCXXReinterpretCastExpr(const CXXReinterpretCastExpr *E); 183a07aba5dSTimm Baeder bool VisitCXXNoexceptExpr(const CXXNoexceptExpr *E); 184a07aba5dSTimm Baeder bool VisitCXXConstructExpr(const CXXConstructExpr *E); 185a07aba5dSTimm Baeder bool VisitSourceLocExpr(const SourceLocExpr *E); 186a07aba5dSTimm Baeder bool VisitOffsetOfExpr(const OffsetOfExpr *E); 187a07aba5dSTimm Baeder bool VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E); 188a07aba5dSTimm Baeder bool VisitSizeOfPackExpr(const SizeOfPackExpr *E); 189a07aba5dSTimm Baeder bool VisitGenericSelectionExpr(const GenericSelectionExpr *E); 190a07aba5dSTimm Baeder bool VisitChooseExpr(const ChooseExpr *E); 191a07aba5dSTimm Baeder bool VisitEmbedExpr(const EmbedExpr *E); 192a07aba5dSTimm Baeder bool VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *E); 193a07aba5dSTimm Baeder bool VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *E); 194a07aba5dSTimm Baeder bool VisitExpressionTraitExpr(const ExpressionTraitExpr *E); 195a07aba5dSTimm Baeder bool VisitCXXUuidofExpr(const CXXUuidofExpr *E); 196a07aba5dSTimm Baeder bool VisitRequiresExpr(const RequiresExpr *E); 197a07aba5dSTimm Baeder bool VisitConceptSpecializationExpr(const ConceptSpecializationExpr *E); 198a07aba5dSTimm Baeder bool VisitCXXRewrittenBinaryOperator(const CXXRewrittenBinaryOperator *E); 199a07aba5dSTimm Baeder bool VisitPseudoObjectExpr(const PseudoObjectExpr *E); 200a07aba5dSTimm Baeder bool VisitPackIndexingExpr(const PackIndexingExpr *E); 201a07aba5dSTimm Baeder bool VisitRecoveryExpr(const RecoveryExpr *E); 202a07aba5dSTimm Baeder bool VisitAddrLabelExpr(const AddrLabelExpr *E); 203a07aba5dSTimm Baeder bool VisitConvertVectorExpr(const ConvertVectorExpr *E); 204a07aba5dSTimm Baeder bool VisitShuffleVectorExpr(const ShuffleVectorExpr *E); 205a07aba5dSTimm Baeder bool VisitExtVectorElementExpr(const ExtVectorElementExpr *E); 206a07aba5dSTimm Baeder bool VisitObjCBoxedExpr(const ObjCBoxedExpr *E); 207a07aba5dSTimm Baeder bool VisitCXXStdInitializerListExpr(const CXXStdInitializerListExpr *E); 208a07aba5dSTimm Baeder bool VisitStmtExpr(const StmtExpr *E); 209a07aba5dSTimm Baeder bool VisitCXXNewExpr(const CXXNewExpr *E); 210a07aba5dSTimm Baeder bool VisitCXXDeleteExpr(const CXXDeleteExpr *E); 211ca148b21STimm Baeder bool VisitBlockExpr(const BlockExpr *E); 212e86b68ffSTimm Baeder bool VisitCXXTypeidExpr(const CXXTypeidExpr *E); 213a07aba5dSTimm Baeder 214a07aba5dSTimm Baeder // Statements. 215a07aba5dSTimm Baeder bool visitCompoundStmt(const CompoundStmt *S); 216a07aba5dSTimm Baeder bool visitDeclStmt(const DeclStmt *DS); 217a07aba5dSTimm Baeder bool visitReturnStmt(const ReturnStmt *RS); 218a07aba5dSTimm Baeder bool visitIfStmt(const IfStmt *IS); 219a07aba5dSTimm Baeder bool visitWhileStmt(const WhileStmt *S); 220a07aba5dSTimm Baeder bool visitDoStmt(const DoStmt *S); 221a07aba5dSTimm Baeder bool visitForStmt(const ForStmt *S); 222a07aba5dSTimm Baeder bool visitCXXForRangeStmt(const CXXForRangeStmt *S); 223a07aba5dSTimm Baeder bool visitBreakStmt(const BreakStmt *S); 224a07aba5dSTimm Baeder bool visitContinueStmt(const ContinueStmt *S); 225a07aba5dSTimm Baeder bool visitSwitchStmt(const SwitchStmt *S); 226a07aba5dSTimm Baeder bool visitCaseStmt(const CaseStmt *S); 227a07aba5dSTimm Baeder bool visitDefaultStmt(const DefaultStmt *S); 228a07aba5dSTimm Baeder bool visitAttributedStmt(const AttributedStmt *S); 229a07aba5dSTimm Baeder bool visitCXXTryStmt(const CXXTryStmt *S); 230a07aba5dSTimm Baeder 231a07aba5dSTimm Baeder protected: 232a07aba5dSTimm Baeder bool visitStmt(const Stmt *S); 23383fea8b8STimm Baeder bool visitExpr(const Expr *E, bool DestroyToplevelScope) override; 234a07aba5dSTimm Baeder bool visitFunc(const FunctionDecl *F) override; 235a07aba5dSTimm Baeder 236a07aba5dSTimm Baeder bool visitDeclAndReturn(const VarDecl *VD, bool ConstantContext) override; 237a07aba5dSTimm Baeder 238a07aba5dSTimm Baeder protected: 239a07aba5dSTimm Baeder /// Emits scope cleanup instructions. 240a07aba5dSTimm Baeder void emitCleanup(); 241a07aba5dSTimm Baeder 242a07aba5dSTimm Baeder /// Returns a record type from a record or pointer type. 243a07aba5dSTimm Baeder const RecordType *getRecordTy(QualType Ty); 244a07aba5dSTimm Baeder 245a07aba5dSTimm Baeder /// Returns a record from a record or pointer type. 246a07aba5dSTimm Baeder Record *getRecord(QualType Ty); 247a07aba5dSTimm Baeder Record *getRecord(const RecordDecl *RD); 248a07aba5dSTimm Baeder 249a07aba5dSTimm Baeder /// Returns a function for the given FunctionDecl. 250a07aba5dSTimm Baeder /// If the function does not exist yet, it is compiled. 251a07aba5dSTimm Baeder const Function *getFunction(const FunctionDecl *FD); 252a07aba5dSTimm Baeder 253a07aba5dSTimm Baeder std::optional<PrimType> classify(const Expr *E) const { 254a07aba5dSTimm Baeder return Ctx.classify(E); 255a07aba5dSTimm Baeder } 256a07aba5dSTimm Baeder std::optional<PrimType> classify(QualType Ty) const { 257a07aba5dSTimm Baeder return Ctx.classify(Ty); 258a07aba5dSTimm Baeder } 259a07aba5dSTimm Baeder 260a07aba5dSTimm Baeder /// Classifies a known primitive type. 261a07aba5dSTimm Baeder PrimType classifyPrim(QualType Ty) const { 262a07aba5dSTimm Baeder if (auto T = classify(Ty)) { 263a07aba5dSTimm Baeder return *T; 264a07aba5dSTimm Baeder } 265a07aba5dSTimm Baeder llvm_unreachable("not a primitive type"); 266a07aba5dSTimm Baeder } 267a07aba5dSTimm Baeder /// Classifies a known primitive expression. 268a07aba5dSTimm Baeder PrimType classifyPrim(const Expr *E) const { 269a07aba5dSTimm Baeder if (auto T = classify(E)) 270a07aba5dSTimm Baeder return *T; 271a07aba5dSTimm Baeder llvm_unreachable("not a primitive type"); 272a07aba5dSTimm Baeder } 273a07aba5dSTimm Baeder 274a07aba5dSTimm Baeder /// Evaluates an expression and places the result on the stack. If the 275a07aba5dSTimm Baeder /// expression is of composite type, a local variable will be created 276a07aba5dSTimm Baeder /// and a pointer to said variable will be placed on the stack. 277a07aba5dSTimm Baeder bool visit(const Expr *E); 278a07aba5dSTimm Baeder /// Compiles an initializer. This is like visit() but it will never 279a07aba5dSTimm Baeder /// create a variable and instead rely on a variable already having 280a07aba5dSTimm Baeder /// been created. visitInitializer() then relies on a pointer to this 281a07aba5dSTimm Baeder /// variable being on top of the stack. 282a07aba5dSTimm Baeder bool visitInitializer(const Expr *E); 283a07aba5dSTimm Baeder /// Evaluates an expression for side effects and discards the result. 284a07aba5dSTimm Baeder bool discard(const Expr *E); 285a07aba5dSTimm Baeder /// Just pass evaluation on to \p E. This leaves all the parsing flags 286a07aba5dSTimm Baeder /// intact. 287a07aba5dSTimm Baeder bool delegate(const Expr *E); 288a07aba5dSTimm Baeder /// Creates and initializes a variable from the given decl. 289a07aba5dSTimm Baeder VarCreationState visitVarDecl(const VarDecl *VD, bool Toplevel = false); 290a07aba5dSTimm Baeder VarCreationState visitDecl(const VarDecl *VD); 291a07aba5dSTimm Baeder /// Visit an APValue. 292a07aba5dSTimm Baeder bool visitAPValue(const APValue &Val, PrimType ValType, const Expr *E); 293a07aba5dSTimm Baeder bool visitAPValueInitializer(const APValue &Val, const Expr *E); 294a07aba5dSTimm Baeder /// Visit the given decl as if we have a reference to it. 295a07aba5dSTimm Baeder bool visitDeclRef(const ValueDecl *D, const Expr *E); 296a07aba5dSTimm Baeder 297a07aba5dSTimm Baeder /// Visits an expression and converts it to a boolean. 298a07aba5dSTimm Baeder bool visitBool(const Expr *E); 299a07aba5dSTimm Baeder 300a07aba5dSTimm Baeder bool visitInitList(ArrayRef<const Expr *> Inits, const Expr *ArrayFiller, 301a07aba5dSTimm Baeder const Expr *E); 302a07aba5dSTimm Baeder bool visitArrayElemInit(unsigned ElemIndex, const Expr *Init); 303a07aba5dSTimm Baeder 304a07aba5dSTimm Baeder /// Creates a local primitive value. 305a07aba5dSTimm Baeder unsigned allocateLocalPrimitive(DeclTy &&Decl, PrimType Ty, bool IsConst, 306a07aba5dSTimm Baeder bool IsExtended = false); 307a07aba5dSTimm Baeder 308a07aba5dSTimm Baeder /// Allocates a space storing a local given its type. 309a07aba5dSTimm Baeder std::optional<unsigned> 31055d51dd9STimm Baeder allocateLocal(DeclTy &&Decl, QualType Ty = QualType(), 31155d51dd9STimm Baeder const ValueDecl *ExtendingDecl = nullptr); 312a07aba5dSTimm Baeder unsigned allocateTemporary(const Expr *E); 313a07aba5dSTimm Baeder 314a07aba5dSTimm Baeder private: 315a07aba5dSTimm Baeder friend class VariableScope<Emitter>; 316a07aba5dSTimm Baeder friend class LocalScope<Emitter>; 317a07aba5dSTimm Baeder friend class DestructorScope<Emitter>; 318a07aba5dSTimm Baeder friend class DeclScope<Emitter>; 319a07aba5dSTimm Baeder friend class InitLinkScope<Emitter>; 320a07aba5dSTimm Baeder friend class InitStackScope<Emitter>; 321a07aba5dSTimm Baeder friend class OptionScope<Emitter>; 322a07aba5dSTimm Baeder friend class ArrayIndexScope<Emitter>; 323a07aba5dSTimm Baeder friend class SourceLocScope<Emitter>; 324a07aba5dSTimm Baeder friend struct InitLink; 325a07aba5dSTimm Baeder friend class LoopScope<Emitter>; 326a07aba5dSTimm Baeder friend class LabelScope<Emitter>; 327a07aba5dSTimm Baeder friend class SwitchScope<Emitter>; 328a07aba5dSTimm Baeder friend class StmtExprScope<Emitter>; 329a07aba5dSTimm Baeder 330a07aba5dSTimm Baeder /// Emits a zero initializer. 331a07aba5dSTimm Baeder bool visitZeroInitializer(PrimType T, QualType QT, const Expr *E); 332a07aba5dSTimm Baeder bool visitZeroRecordInitializer(const Record *R, const Expr *E); 333ceaf6e91STimm Baeder bool visitZeroArrayInitializer(QualType T, const Expr *E); 334a07aba5dSTimm Baeder 335a07aba5dSTimm Baeder /// Emits an APSInt constant. 336a07aba5dSTimm Baeder bool emitConst(const llvm::APSInt &Value, PrimType Ty, const Expr *E); 337a07aba5dSTimm Baeder bool emitConst(const llvm::APSInt &Value, const Expr *E); 338a07aba5dSTimm Baeder bool emitConst(const llvm::APInt &Value, const Expr *E) { 339a07aba5dSTimm Baeder return emitConst(static_cast<llvm::APSInt>(Value), E); 340a07aba5dSTimm Baeder } 341a07aba5dSTimm Baeder 342a07aba5dSTimm Baeder /// Emits an integer constant. 343a07aba5dSTimm Baeder template <typename T> bool emitConst(T Value, PrimType Ty, const Expr *E); 344a07aba5dSTimm Baeder template <typename T> bool emitConst(T Value, const Expr *E); 345a07aba5dSTimm Baeder 346a07aba5dSTimm Baeder llvm::RoundingMode getRoundingMode(const Expr *E) const { 347a07aba5dSTimm Baeder FPOptions FPO = E->getFPFeaturesInEffect(Ctx.getLangOpts()); 348a07aba5dSTimm Baeder 349a07aba5dSTimm Baeder if (FPO.getRoundingMode() == llvm::RoundingMode::Dynamic) 350a07aba5dSTimm Baeder return llvm::RoundingMode::NearestTiesToEven; 351a07aba5dSTimm Baeder 352a07aba5dSTimm Baeder return FPO.getRoundingMode(); 353a07aba5dSTimm Baeder } 354a07aba5dSTimm Baeder 3550f5f440fSTimm Baeder uint32_t getFPOptions(const Expr *E) const { 3560f5f440fSTimm Baeder return E->getFPFeaturesInEffect(Ctx.getLangOpts()).getAsOpaqueInt(); 3570f5f440fSTimm Baeder } 3580f5f440fSTimm Baeder 359a07aba5dSTimm Baeder bool emitPrimCast(PrimType FromT, PrimType ToT, QualType ToQT, const Expr *E); 360a07aba5dSTimm Baeder PrimType classifyComplexElementType(QualType T) const { 361a07aba5dSTimm Baeder assert(T->isAnyComplexType()); 362a07aba5dSTimm Baeder 363a07aba5dSTimm Baeder QualType ElemType = T->getAs<ComplexType>()->getElementType(); 364a07aba5dSTimm Baeder 365a07aba5dSTimm Baeder return *this->classify(ElemType); 366a07aba5dSTimm Baeder } 367a07aba5dSTimm Baeder 368ee0d7063Syronglin PrimType classifyVectorElementType(QualType T) const { 369ee0d7063Syronglin assert(T->isVectorType()); 370ee0d7063Syronglin return *this->classify(T->getAs<VectorType>()->getElementType()); 371ee0d7063Syronglin } 372ee0d7063Syronglin 373a07aba5dSTimm Baeder bool emitComplexReal(const Expr *SubExpr); 374a07aba5dSTimm Baeder bool emitComplexBoolCast(const Expr *E); 375a07aba5dSTimm Baeder bool emitComplexComparison(const Expr *LHS, const Expr *RHS, 376a07aba5dSTimm Baeder const BinaryOperator *E); 3773ea55d3cSTimm Baeder bool emitRecordDestruction(const Record *R, SourceInfo Loc); 3783ea55d3cSTimm Baeder bool emitDestruction(const Descriptor *Desc, SourceInfo Loc); 3799ae41c24STimm Baeder bool emitDummyPtr(const DeclTy &D, const Expr *E); 380a07aba5dSTimm Baeder unsigned collectBaseOffset(const QualType BaseType, 381a07aba5dSTimm Baeder const QualType DerivedType); 382a07aba5dSTimm Baeder bool emitLambdaStaticInvokerBody(const CXXMethodDecl *MD); 383ef2a104cSTimm Baeder bool emitBuiltinBitCast(const CastExpr *E); 384a07aba5dSTimm Baeder bool compileConstructor(const CXXConstructorDecl *Ctor); 385a07aba5dSTimm Baeder bool compileDestructor(const CXXDestructorDecl *Dtor); 386a07aba5dSTimm Baeder 387a07aba5dSTimm Baeder bool checkLiteralType(const Expr *E); 388a07aba5dSTimm Baeder 389a07aba5dSTimm Baeder protected: 390a07aba5dSTimm Baeder /// Variable to storage mapping. 391a07aba5dSTimm Baeder llvm::DenseMap<const ValueDecl *, Scope::Local> Locals; 392a07aba5dSTimm Baeder 393a07aba5dSTimm Baeder /// OpaqueValueExpr to location mapping. 394a07aba5dSTimm Baeder llvm::DenseMap<const OpaqueValueExpr *, unsigned> OpaqueExprs; 395a07aba5dSTimm Baeder 396a07aba5dSTimm Baeder /// Current scope. 397a07aba5dSTimm Baeder VariableScope<Emitter> *VarScope = nullptr; 398a07aba5dSTimm Baeder 399a07aba5dSTimm Baeder /// Current argument index. Needed to emit ArrayInitIndexExpr. 400a07aba5dSTimm Baeder std::optional<uint64_t> ArrayIndex; 401a07aba5dSTimm Baeder 402a07aba5dSTimm Baeder /// DefaultInit- or DefaultArgExpr, needed for SourceLocExpr. 403a07aba5dSTimm Baeder const Expr *SourceLocDefaultExpr = nullptr; 404a07aba5dSTimm Baeder 405a07aba5dSTimm Baeder /// Flag indicating if return value is to be discarded. 406a07aba5dSTimm Baeder bool DiscardResult = false; 407a07aba5dSTimm Baeder 408a07aba5dSTimm Baeder bool InStmtExpr = false; 409a07aba5dSTimm Baeder 410a07aba5dSTimm Baeder /// Flag inidicating if we're initializing an already created 411a07aba5dSTimm Baeder /// variable. This is set in visitInitializer(). 412a07aba5dSTimm Baeder bool Initializing = false; 413a07aba5dSTimm Baeder const ValueDecl *InitializingDecl = nullptr; 414a07aba5dSTimm Baeder 415a07aba5dSTimm Baeder llvm::SmallVector<InitLink> InitStack; 416a07aba5dSTimm Baeder bool InitStackActive = false; 417a07aba5dSTimm Baeder 418a07aba5dSTimm Baeder /// Type of the expression returned by the function. 419a07aba5dSTimm Baeder std::optional<PrimType> ReturnType; 420a07aba5dSTimm Baeder 421a07aba5dSTimm Baeder /// Switch case mapping. 422a07aba5dSTimm Baeder CaseMap CaseLabels; 423a07aba5dSTimm Baeder 4243928edecSTimm Baeder /// Scope to cleanup until when we see a break statement. 4253928edecSTimm Baeder VariableScope<Emitter> *BreakVarScope = nullptr; 426a07aba5dSTimm Baeder /// Point to break to. 427a07aba5dSTimm Baeder OptLabelTy BreakLabel; 4283928edecSTimm Baeder /// Scope to cleanup until when we see a continue statement. 4293928edecSTimm Baeder VariableScope<Emitter> *ContinueVarScope = nullptr; 430a07aba5dSTimm Baeder /// Point to continue to. 431a07aba5dSTimm Baeder OptLabelTy ContinueLabel; 432a07aba5dSTimm Baeder /// Default case label. 433a07aba5dSTimm Baeder OptLabelTy DefaultLabel; 434a07aba5dSTimm Baeder }; 435a07aba5dSTimm Baeder 436a07aba5dSTimm Baeder extern template class Compiler<ByteCodeEmitter>; 437a07aba5dSTimm Baeder extern template class Compiler<EvalEmitter>; 438a07aba5dSTimm Baeder 439a07aba5dSTimm Baeder /// Scope chain managing the variable lifetimes. 440a07aba5dSTimm Baeder template <class Emitter> class VariableScope { 441a07aba5dSTimm Baeder public: 442a07aba5dSTimm Baeder VariableScope(Compiler<Emitter> *Ctx, const ValueDecl *VD) 443a07aba5dSTimm Baeder : Ctx(Ctx), Parent(Ctx->VarScope), ValDecl(VD) { 444a07aba5dSTimm Baeder Ctx->VarScope = this; 445a07aba5dSTimm Baeder } 446a07aba5dSTimm Baeder 447a07aba5dSTimm Baeder virtual ~VariableScope() { Ctx->VarScope = this->Parent; } 448a07aba5dSTimm Baeder 449a07aba5dSTimm Baeder void add(const Scope::Local &Local, bool IsExtended) { 450a07aba5dSTimm Baeder if (IsExtended) 451a07aba5dSTimm Baeder this->addExtended(Local); 452a07aba5dSTimm Baeder else 453a07aba5dSTimm Baeder this->addLocal(Local); 454a07aba5dSTimm Baeder } 455a07aba5dSTimm Baeder 456a07aba5dSTimm Baeder virtual void addLocal(const Scope::Local &Local) { 457a07aba5dSTimm Baeder if (this->Parent) 458a07aba5dSTimm Baeder this->Parent->addLocal(Local); 459a07aba5dSTimm Baeder } 460a07aba5dSTimm Baeder 461a07aba5dSTimm Baeder virtual void addExtended(const Scope::Local &Local) { 462a07aba5dSTimm Baeder if (this->Parent) 463a07aba5dSTimm Baeder this->Parent->addExtended(Local); 464a07aba5dSTimm Baeder } 465a07aba5dSTimm Baeder 466a07aba5dSTimm Baeder void addExtended(const Scope::Local &Local, const ValueDecl *ExtendingDecl) { 467a07aba5dSTimm Baeder // Walk up the chain of scopes until we find the one for ExtendingDecl. 468a07aba5dSTimm Baeder // If there is no such scope, attach it to the parent one. 469a07aba5dSTimm Baeder VariableScope *P = this; 470a07aba5dSTimm Baeder while (P) { 471a07aba5dSTimm Baeder if (P->ValDecl == ExtendingDecl) { 472a07aba5dSTimm Baeder P->addLocal(Local); 473a07aba5dSTimm Baeder return; 474a07aba5dSTimm Baeder } 475a07aba5dSTimm Baeder P = P->Parent; 476a07aba5dSTimm Baeder if (!P) 477a07aba5dSTimm Baeder break; 478a07aba5dSTimm Baeder } 479a07aba5dSTimm Baeder 480a07aba5dSTimm Baeder // Use the parent scope. 481a07aba5dSTimm Baeder if (this->Parent) 482a07aba5dSTimm Baeder this->Parent->addLocal(Local); 483a07aba5dSTimm Baeder else 484a07aba5dSTimm Baeder this->addLocal(Local); 485a07aba5dSTimm Baeder } 486a07aba5dSTimm Baeder 487a07aba5dSTimm Baeder virtual void emitDestruction() {} 488a07aba5dSTimm Baeder virtual bool emitDestructors(const Expr *E = nullptr) { return true; } 489a07aba5dSTimm Baeder virtual bool destroyLocals(const Expr *E = nullptr) { return true; } 490a07aba5dSTimm Baeder VariableScope *getParent() const { return Parent; } 491a07aba5dSTimm Baeder 492a07aba5dSTimm Baeder protected: 493a07aba5dSTimm Baeder /// Compiler instance. 494a07aba5dSTimm Baeder Compiler<Emitter> *Ctx; 495a07aba5dSTimm Baeder /// Link to the parent scope. 496a07aba5dSTimm Baeder VariableScope *Parent; 497a07aba5dSTimm Baeder const ValueDecl *ValDecl = nullptr; 498a07aba5dSTimm Baeder }; 499a07aba5dSTimm Baeder 500a07aba5dSTimm Baeder /// Generic scope for local variables. 501a07aba5dSTimm Baeder template <class Emitter> class LocalScope : public VariableScope<Emitter> { 502a07aba5dSTimm Baeder public: 503a07aba5dSTimm Baeder LocalScope(Compiler<Emitter> *Ctx) : VariableScope<Emitter>(Ctx, nullptr) {} 504a07aba5dSTimm Baeder LocalScope(Compiler<Emitter> *Ctx, const ValueDecl *VD) 505a07aba5dSTimm Baeder : VariableScope<Emitter>(Ctx, VD) {} 506a07aba5dSTimm Baeder 507a07aba5dSTimm Baeder /// Emit a Destroy op for this scope. 508a07aba5dSTimm Baeder ~LocalScope() override { 509a07aba5dSTimm Baeder if (!Idx) 510a07aba5dSTimm Baeder return; 511a07aba5dSTimm Baeder this->Ctx->emitDestroy(*Idx, SourceInfo{}); 512a07aba5dSTimm Baeder removeStoredOpaqueValues(); 513a07aba5dSTimm Baeder } 514a07aba5dSTimm Baeder 515a07aba5dSTimm Baeder /// Overriden to support explicit destruction. 516a07aba5dSTimm Baeder void emitDestruction() override { 517a07aba5dSTimm Baeder if (!Idx) 518a07aba5dSTimm Baeder return; 519a07aba5dSTimm Baeder 520a07aba5dSTimm Baeder this->emitDestructors(); 521a07aba5dSTimm Baeder this->Ctx->emitDestroy(*Idx, SourceInfo{}); 522a07aba5dSTimm Baeder } 523a07aba5dSTimm Baeder 524a07aba5dSTimm Baeder /// Explicit destruction of local variables. 525a07aba5dSTimm Baeder bool destroyLocals(const Expr *E = nullptr) override { 526a07aba5dSTimm Baeder if (!Idx) 527a07aba5dSTimm Baeder return true; 528a07aba5dSTimm Baeder 529a07aba5dSTimm Baeder bool Success = this->emitDestructors(E); 530a07aba5dSTimm Baeder this->Ctx->emitDestroy(*Idx, E); 531a07aba5dSTimm Baeder this->Idx = std::nullopt; 532a07aba5dSTimm Baeder return Success; 533a07aba5dSTimm Baeder } 534a07aba5dSTimm Baeder 535a07aba5dSTimm Baeder void addLocal(const Scope::Local &Local) override { 536a07aba5dSTimm Baeder if (!Idx) { 537a07aba5dSTimm Baeder Idx = this->Ctx->Descriptors.size(); 538a07aba5dSTimm Baeder this->Ctx->Descriptors.emplace_back(); 539a07aba5dSTimm Baeder this->Ctx->emitInitScope(*Idx, {}); 540a07aba5dSTimm Baeder } 541a07aba5dSTimm Baeder 542a07aba5dSTimm Baeder this->Ctx->Descriptors[*Idx].emplace_back(Local); 543a07aba5dSTimm Baeder } 544a07aba5dSTimm Baeder 545a07aba5dSTimm Baeder bool emitDestructors(const Expr *E = nullptr) override { 546a07aba5dSTimm Baeder if (!Idx) 547a07aba5dSTimm Baeder return true; 548a07aba5dSTimm Baeder // Emit destructor calls for local variables of record 549a07aba5dSTimm Baeder // type with a destructor. 5503928edecSTimm Baeder for (Scope::Local &Local : llvm::reverse(this->Ctx->Descriptors[*Idx])) { 551a07aba5dSTimm Baeder if (!Local.Desc->isPrimitive() && !Local.Desc->isPrimitiveArray()) { 552a07aba5dSTimm Baeder if (!this->Ctx->emitGetPtrLocal(Local.Offset, E)) 553a07aba5dSTimm Baeder return false; 554a07aba5dSTimm Baeder 5553ea55d3cSTimm Baeder if (!this->Ctx->emitDestruction(Local.Desc, Local.Desc->getLoc())) 556a07aba5dSTimm Baeder return false; 557a07aba5dSTimm Baeder 558a07aba5dSTimm Baeder if (!this->Ctx->emitPopPtr(E)) 559a07aba5dSTimm Baeder return false; 560a07aba5dSTimm Baeder removeIfStoredOpaqueValue(Local); 561a07aba5dSTimm Baeder } 562a07aba5dSTimm Baeder } 563a07aba5dSTimm Baeder return true; 564a07aba5dSTimm Baeder } 565a07aba5dSTimm Baeder 566a07aba5dSTimm Baeder void removeStoredOpaqueValues() { 567a07aba5dSTimm Baeder if (!Idx) 568a07aba5dSTimm Baeder return; 569a07aba5dSTimm Baeder 570a07aba5dSTimm Baeder for (const Scope::Local &Local : this->Ctx->Descriptors[*Idx]) { 571a07aba5dSTimm Baeder removeIfStoredOpaqueValue(Local); 572a07aba5dSTimm Baeder } 573a07aba5dSTimm Baeder } 574a07aba5dSTimm Baeder 575a07aba5dSTimm Baeder void removeIfStoredOpaqueValue(const Scope::Local &Local) { 576a07aba5dSTimm Baeder if (const auto *OVE = 577a07aba5dSTimm Baeder llvm::dyn_cast_if_present<OpaqueValueExpr>(Local.Desc->asExpr())) { 578a07aba5dSTimm Baeder if (auto It = this->Ctx->OpaqueExprs.find(OVE); 579a07aba5dSTimm Baeder It != this->Ctx->OpaqueExprs.end()) 580a07aba5dSTimm Baeder this->Ctx->OpaqueExprs.erase(It); 581a07aba5dSTimm Baeder }; 582a07aba5dSTimm Baeder } 583a07aba5dSTimm Baeder 584a07aba5dSTimm Baeder /// Index of the scope in the chain. 585a07aba5dSTimm Baeder std::optional<unsigned> Idx; 586a07aba5dSTimm Baeder }; 587a07aba5dSTimm Baeder 588a07aba5dSTimm Baeder /// Scope for storage declared in a compound statement. 589a07aba5dSTimm Baeder template <class Emitter> class BlockScope final : public LocalScope<Emitter> { 590a07aba5dSTimm Baeder public: 591a07aba5dSTimm Baeder BlockScope(Compiler<Emitter> *Ctx) : LocalScope<Emitter>(Ctx) {} 592a07aba5dSTimm Baeder 593a07aba5dSTimm Baeder void addExtended(const Scope::Local &Local) override { 594a07aba5dSTimm Baeder // If we to this point, just add the variable as a normal local 595a07aba5dSTimm Baeder // variable. It will be destroyed at the end of the block just 596a07aba5dSTimm Baeder // like all others. 597a07aba5dSTimm Baeder this->addLocal(Local); 598a07aba5dSTimm Baeder } 599a07aba5dSTimm Baeder }; 600a07aba5dSTimm Baeder 601a07aba5dSTimm Baeder template <class Emitter> class ArrayIndexScope final { 602a07aba5dSTimm Baeder public: 603a07aba5dSTimm Baeder ArrayIndexScope(Compiler<Emitter> *Ctx, uint64_t Index) : Ctx(Ctx) { 604a07aba5dSTimm Baeder OldArrayIndex = Ctx->ArrayIndex; 605a07aba5dSTimm Baeder Ctx->ArrayIndex = Index; 606a07aba5dSTimm Baeder } 607a07aba5dSTimm Baeder 608a07aba5dSTimm Baeder ~ArrayIndexScope() { Ctx->ArrayIndex = OldArrayIndex; } 609a07aba5dSTimm Baeder 610a07aba5dSTimm Baeder private: 611a07aba5dSTimm Baeder Compiler<Emitter> *Ctx; 612a07aba5dSTimm Baeder std::optional<uint64_t> OldArrayIndex; 613a07aba5dSTimm Baeder }; 614a07aba5dSTimm Baeder 615a07aba5dSTimm Baeder template <class Emitter> class SourceLocScope final { 616a07aba5dSTimm Baeder public: 617a07aba5dSTimm Baeder SourceLocScope(Compiler<Emitter> *Ctx, const Expr *DefaultExpr) : Ctx(Ctx) { 618a07aba5dSTimm Baeder assert(DefaultExpr); 619a07aba5dSTimm Baeder // We only switch if the current SourceLocDefaultExpr is null. 620a07aba5dSTimm Baeder if (!Ctx->SourceLocDefaultExpr) { 621a07aba5dSTimm Baeder Enabled = true; 622a07aba5dSTimm Baeder Ctx->SourceLocDefaultExpr = DefaultExpr; 623a07aba5dSTimm Baeder } 624a07aba5dSTimm Baeder } 625a07aba5dSTimm Baeder 626a07aba5dSTimm Baeder ~SourceLocScope() { 627a07aba5dSTimm Baeder if (Enabled) 628a07aba5dSTimm Baeder Ctx->SourceLocDefaultExpr = nullptr; 629a07aba5dSTimm Baeder } 630a07aba5dSTimm Baeder 631a07aba5dSTimm Baeder private: 632a07aba5dSTimm Baeder Compiler<Emitter> *Ctx; 633a07aba5dSTimm Baeder bool Enabled = false; 634a07aba5dSTimm Baeder }; 635a07aba5dSTimm Baeder 636a07aba5dSTimm Baeder template <class Emitter> class InitLinkScope final { 637a07aba5dSTimm Baeder public: 638a07aba5dSTimm Baeder InitLinkScope(Compiler<Emitter> *Ctx, InitLink &&Link) : Ctx(Ctx) { 639a07aba5dSTimm Baeder Ctx->InitStack.push_back(std::move(Link)); 640a07aba5dSTimm Baeder } 641a07aba5dSTimm Baeder 642a07aba5dSTimm Baeder ~InitLinkScope() { this->Ctx->InitStack.pop_back(); } 643a07aba5dSTimm Baeder 644a07aba5dSTimm Baeder private: 645a07aba5dSTimm Baeder Compiler<Emitter> *Ctx; 646a07aba5dSTimm Baeder }; 647a07aba5dSTimm Baeder 648a07aba5dSTimm Baeder template <class Emitter> class InitStackScope final { 649a07aba5dSTimm Baeder public: 650a07aba5dSTimm Baeder InitStackScope(Compiler<Emitter> *Ctx, bool Active) 651a07aba5dSTimm Baeder : Ctx(Ctx), OldValue(Ctx->InitStackActive) { 652a07aba5dSTimm Baeder Ctx->InitStackActive = Active; 653a07aba5dSTimm Baeder } 654a07aba5dSTimm Baeder 655a07aba5dSTimm Baeder ~InitStackScope() { this->Ctx->InitStackActive = OldValue; } 656a07aba5dSTimm Baeder 657a07aba5dSTimm Baeder private: 658a07aba5dSTimm Baeder Compiler<Emitter> *Ctx; 659a07aba5dSTimm Baeder bool OldValue; 660a07aba5dSTimm Baeder }; 661a07aba5dSTimm Baeder 662a07aba5dSTimm Baeder } // namespace interp 663a07aba5dSTimm Baeder } // namespace clang 664a07aba5dSTimm Baeder 665a07aba5dSTimm Baeder #endif 666