diff options
Diffstat (limited to 'clang/lib/AST/Interp/ByteCodeExprGen.h')
-rw-r--r-- | clang/lib/AST/Interp/ByteCodeExprGen.h | 171 |
1 files changed, 102 insertions, 69 deletions
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h index 82aa413dabbc..c7fcc59e5a60 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.h +++ b/clang/lib/AST/Interp/ByteCodeExprGen.h @@ -22,7 +22,6 @@ #include "clang/AST/Expr.h" #include "clang/AST/StmtVisitor.h" #include "clang/Basic/TargetInfo.h" -#include "llvm/ADT/Optional.h" namespace clang { class QualType; @@ -34,25 +33,17 @@ template <class Emitter> class RecordScope; template <class Emitter> class VariableScope; template <class Emitter> class DeclScope; template <class Emitter> class OptionScope; +template <class Emitter> class ArrayIndexScope; /// Compilation context for expressions. template <class Emitter> class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>, public Emitter { protected: - // Emitters for opcodes of various arities. - using NullaryFn = bool (ByteCodeExprGen::*)(const SourceInfo &); - using UnaryFn = bool (ByteCodeExprGen::*)(PrimType, const SourceInfo &); - using BinaryFn = bool (ByteCodeExprGen::*)(PrimType, PrimType, - const SourceInfo &); - // Aliases for types defined in the emitter. using LabelTy = typename Emitter::LabelTy; using AddrTy = typename Emitter::AddrTy; - // Reference to a function generating the pointer of an initialized object.s - using InitFnRef = std::function<bool()>; - /// Current compilation context. Context &Ctx; /// Program to link to. @@ -64,11 +55,34 @@ public: ByteCodeExprGen(Context &Ctx, Program &P, Tys &&... Args) : Emitter(Ctx, P, Args...), Ctx(Ctx), P(P) {} - // Expression visitors - result returned on stack. + // Expression visitors - result returned on interp stack. bool VisitCastExpr(const CastExpr *E); bool VisitIntegerLiteral(const IntegerLiteral *E); bool VisitParenExpr(const ParenExpr *E); bool VisitBinaryOperator(const BinaryOperator *E); + bool VisitPointerArithBinOp(const BinaryOperator *E); + bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E); + bool VisitCallExpr(const CallExpr *E); + bool VisitCXXMemberCallExpr(const CXXMemberCallExpr *E); + bool VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E); + bool VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E); + bool VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E); + bool VisitCXXThisExpr(const CXXThisExpr *E); + bool VisitUnaryOperator(const UnaryOperator *E); + bool VisitDeclRefExpr(const DeclRefExpr *E); + bool VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E); + bool VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E); + bool VisitArraySubscriptExpr(const ArraySubscriptExpr *E); + bool VisitInitListExpr(const InitListExpr *E); + bool VisitConstantExpr(const ConstantExpr *E); + bool VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *E); + bool VisitMemberExpr(const MemberExpr *E); + bool VisitArrayInitIndexExpr(const ArrayInitIndexExpr *E); + bool VisitOpaqueValueExpr(const OpaqueValueExpr *E); + bool VisitAbstractConditionalOperator(const AbstractConditionalOperator *E); + bool VisitStringLiteral(const StringLiteral *E); + bool VisitCharacterLiteral(const CharacterLiteral *E); + bool VisitCompoundAssignOperator(const CompoundAssignOperator *E); protected: bool visitExpr(const Expr *E) override; @@ -85,31 +99,18 @@ protected: Record *getRecord(QualType Ty); Record *getRecord(const RecordDecl *RD); - /// Returns the size int bits of an integer. - unsigned getIntWidth(QualType Ty) { - auto &ASTContext = Ctx.getASTContext(); - return ASTContext.getIntWidth(Ty); - } - - /// Returns the value of CHAR_BIT. - unsigned getCharBit() const { - auto &ASTContext = Ctx.getASTContext(); - return ASTContext.getTargetInfo().getCharWidth(); - } + // Returns a function for the given FunctionDecl. + // If the function does not exist yet, it is compiled. + const Function *getFunction(const FunctionDecl *FD); /// Classifies a type. - llvm::Optional<PrimType> classify(const Expr *E) const { + std::optional<PrimType> classify(const Expr *E) const { return E->isGLValue() ? PT_Ptr : classify(E->getType()); } - llvm::Optional<PrimType> classify(QualType Ty) const { + std::optional<PrimType> classify(QualType Ty) const { return Ctx.classify(Ty); } - /// Checks if a pointer needs adjustment. - bool needsAdjust(QualType Ty) const { - return true; - } - /// Classifies a known primitive type PrimType classifyPrim(QualType Ty) const { if (auto T = classify(Ty)) { @@ -122,29 +123,49 @@ protected: bool discard(const Expr *E); /// Evaluates an expression and places result on stack. bool visit(const Expr *E); - /// Compiles an initializer for a local. - bool visitInitializer(const Expr *E, InitFnRef GenPtr); + /// Compiles an initializer. + bool visitInitializer(const Expr *E); + /// Compiles an array initializer. + bool visitArrayInitializer(const Expr *Initializer); + /// Compiles a record initializer. + bool visitRecordInitializer(const Expr *Initializer); + /// Creates and initializes a variable from the given decl. + bool visitVarDecl(const VarDecl *VD); /// Visits an expression and converts it to a boolean. bool visitBool(const Expr *E); /// Visits an initializer for a local. bool visitLocalInitializer(const Expr *Init, unsigned I) { - return visitInitializer(Init, [this, I, Init] { - return this->emitGetPtrLocal(I, Init); - }); + if (!this->emitGetPtrLocal(I, Init)) + return false; + + if (!visitInitializer(Init)) + return false; + + return this->emitPopPtr(Init); } /// Visits an initializer for a global. bool visitGlobalInitializer(const Expr *Init, unsigned I) { - return visitInitializer(Init, [this, I, Init] { - return this->emitGetPtrGlobal(I, Init); - }); + if (!this->emitGetPtrGlobal(I, Init)) + return false; + + if (!visitInitializer(Init)) + return false; + + return this->emitPopPtr(Init); } /// Visits a delegated initializer. bool visitThisInitializer(const Expr *I) { - return visitInitializer(I, [this, I] { return this->emitThis(I); }); + if (!this->emitThis(I)) + return false; + + if (!visitInitializer(I)) + return false; + + return this->emitPopPtr(I); } /// Creates a local primitive value. @@ -152,8 +173,7 @@ protected: bool IsExtended = false); /// Allocates a space storing a local given its type. - llvm::Optional<unsigned> allocateLocal(DeclTy &&Decl, - bool IsExtended = false); + std::optional<unsigned> allocateLocal(DeclTy &&Decl, bool IsExtended = false); private: friend class VariableScope<Emitter>; @@ -161,6 +181,7 @@ private: friend class RecordScope<Emitter>; friend class DeclScope<Emitter>; friend class OptionScope<Emitter>; + friend class ArrayIndexScope<Emitter>; /// Emits a zero initializer. bool visitZeroInitializer(PrimType T, const Expr *E); @@ -188,28 +209,28 @@ private: DerefKind AK, llvm::function_ref<bool(PrimType)> Direct, llvm::function_ref<bool(PrimType)> Indirect); - /// Emits an APInt constant. - bool emitConst(PrimType T, unsigned NumBits, const llvm::APInt &Value, - const Expr *E); + /// Emits an APSInt constant. + bool emitConst(const APSInt &Value, const Expr *E); + bool emitConst(const APInt &Value, const Expr *E) { + return emitConst(static_cast<APSInt>(Value), E); + } /// Emits an integer constant. - template <typename T> bool emitConst(const Expr *E, T Value) { - QualType Ty = E->getType(); - unsigned NumBits = getIntWidth(Ty); - APInt WrappedValue(NumBits, Value, std::is_signed<T>::value); - return emitConst(*Ctx.classify(Ty), NumBits, WrappedValue, E); + template <typename T> bool emitConst(T Value, const Expr *E); + + /// Returns the CXXRecordDecl for the type of the given expression, + /// or nullptr if no such decl exists. + const CXXRecordDecl *getRecordDecl(const Expr *E) const { + QualType T = E->getType(); + if (const auto *RD = T->getPointeeCXXRecordDecl()) + return RD; + return T->getAsCXXRecordDecl(); } - /// Returns a pointer to a variable declaration. - bool getPtrVarDecl(const VarDecl *VD, const Expr *E); - - /// Returns the index of a global. - llvm::Optional<unsigned> getGlobalIdx(const VarDecl *VD); - - /// Emits the initialized pointer. - bool emitInitFn() { - assert(InitFn && "missing initializer"); - return (*InitFn)(); + /// Returns whether we should create a global variable for the + /// given VarDecl. + bool shouldBeGloballyIndexed(const VarDecl *VD) const { + return VD->hasGlobalStorage() || VD->isConstexpr(); } protected: @@ -222,14 +243,11 @@ protected: /// Current scope. VariableScope<Emitter> *VarScope = nullptr; - /// Current argument index. - llvm::Optional<uint64_t> ArrayIndex; + /// Current argument index. Needed to emit ArrayInitIndexExpr. + std::optional<uint64_t> ArrayIndex; /// Flag indicating if return value is to be discarded. bool DiscardResult = false; - - /// Expression being initialized. - llvm::Optional<InitFnRef> InitFn = {}; }; extern template class ByteCodeExprGen<ByteCodeEmitter>; @@ -238,6 +256,11 @@ extern template class ByteCodeExprGen<EvalEmitter>; /// Scope chain managing the variable lifetimes. template <class Emitter> class VariableScope { public: + VariableScope(ByteCodeExprGen<Emitter> *Ctx) + : Ctx(Ctx), Parent(Ctx->VarScope) { + Ctx->VarScope = this; + } + virtual ~VariableScope() { Ctx->VarScope = this->Parent; } void add(const Scope::Local &Local, bool IsExtended) { @@ -262,11 +285,6 @@ public: VariableScope *getParent() { return Parent; } protected: - VariableScope(ByteCodeExprGen<Emitter> *Ctx) - : Ctx(Ctx), Parent(Ctx->VarScope) { - Ctx->VarScope = this; - } - /// ByteCodeExprGen instance. ByteCodeExprGen<Emitter> *Ctx; /// Link to the parent scope. @@ -300,7 +318,7 @@ public: protected: /// Index of the scope in the chain. - Optional<unsigned> Idx; + std::optional<unsigned> Idx; }; /// Scope for storage declared in a compound statement. @@ -320,10 +338,25 @@ public: ExprScope(ByteCodeExprGen<Emitter> *Ctx) : LocalScope<Emitter>(Ctx) {} void addExtended(const Scope::Local &Local) override { + assert(this->Parent); this->Parent->addLocal(Local); } }; +template <class Emitter> class ArrayIndexScope final { +public: + ArrayIndexScope(ByteCodeExprGen<Emitter> *Ctx, uint64_t Index) : Ctx(Ctx) { + OldArrayIndex = Ctx->ArrayIndex; + Ctx->ArrayIndex = Index; + } + + ~ArrayIndexScope() { Ctx->ArrayIndex = OldArrayIndex; } + +private: + ByteCodeExprGen<Emitter> *Ctx; + std::optional<uint64_t> OldArrayIndex; +}; + } // namespace interp } // namespace clang |