/* This file is part of cpp-ethereum. cpp-ethereum is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. cpp-ethereum is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ /** * @author Christian * @date 2014 * Solidity AST to EVM bytecode compiler for expressions. */ #include #include namespace dev { namespace eth { class AssemblyItem; // forward } namespace solidity { class CompilerContext; // forward class Type; // forward class IntegerType; // forward /** * Compiler for expressions, i.e. converts an AST tree whose root is an Expression into a stream * of EVM instructions. It needs a compiler context that is the same for the whole compilation * unit. */ class ExpressionCompiler: private ASTVisitor { public: /// Compile the given @a _expression into the @a _context. static void compileExpression(CompilerContext& _context, Expression& _expression); /// Appends code to remove dirty higher order bits in case of an implicit promotion to a wider type. static void appendTypeConversion(CompilerContext& _context, Type const& _typeOnStack, Type const& _targetType); private: ExpressionCompiler(CompilerContext& _compilerContext): m_context(_compilerContext) {} virtual bool visit(Assignment& _assignment) override; virtual void endVisit(UnaryOperation& _unaryOperation) override; virtual bool visit(BinaryOperation& _binaryOperation) override; virtual bool visit(FunctionCall& _functionCall) override; virtual void endVisit(MemberAccess& _memberAccess) override; virtual void endVisit(IndexAccess& _indexAccess) override; virtual void endVisit(Identifier& _identifier) override; virtual void endVisit(Literal& _literal) override; ///@{ ///@name Append code for various operator types void appendAndOrOperatorCode(BinaryOperation& _binaryOperation); void appendCompareOperatorCode(Token::Value _operator, Type const& _type); void appendOrdinaryBinaryOperatorCode(Token::Value _operator, Type const& _type); void appendArithmeticOperatorCode(Token::Value _operator, Type const& _type); void appendBitOperatorCode(Token::Value _operator); void appendShiftOperatorCode(Token::Value _operator); /// @} /// Appends an implicit or explicit type conversion. For now this comprises only erasing /// higher-order bits (@see appendHighBitCleanup) when widening integer types. /// If @a _cleanupNeeded, high order bits cleanup is also done if no type conversion would be /// necessary. void appendTypeConversion(Type const& _typeOnStack, Type const& _targetType, bool _cleanupNeeded = false); //// Appends code that cleans higher-order bits for integer types. void appendHighBitsCleanup(IntegerType const& _typeOnStack); /// Copies the value of the current lvalue to the top of the stack. void retrieveLValueValue(Expression const& _expression); /// Stores the value on top of the stack in the current lvalue. Removes it from the stack if /// @a _move is true. void storeInLValue(Expression const& _expression, bool _move = false); /** * Location of an lvalue, either in code (for a function) on the stack, in the storage or memory. */ struct LValueLocation { enum LocationType { INVALID, CODE, STACK, MEMORY, STORAGE }; LValueLocation() { reset(); } LValueLocation(LocationType _type, u256 const& _location): locationType(_type), location(_location) {} void reset() { locationType = INVALID; location = 0; } bool isValid() const { return locationType != INVALID; } bool isInCode() const { return locationType == CODE; } bool isInOnStack() const { return locationType == STACK; } bool isInMemory() const { return locationType == MEMORY; } bool isInStorage() const { return locationType == STORAGE; } LocationType locationType; /// Depending on the type, this is the id of a tag (code), the base offset of a stack /// variable (@see CompilerContext::getBaseStackOffsetOfVariable) or the offset in /// storage or memory. u256 location; }; LValueLocation m_currentLValue; CompilerContext& m_context; }; } }