diff options
author | Christian <c@ethdev.com> | 2014-11-05 02:13:03 +0800 |
---|---|---|
committer | Christian <c@ethdev.com> | 2014-11-06 09:36:39 +0800 |
commit | 13baaf98b8a3ca2a97c96e5a25398a0cae26e5fb (patch) | |
tree | 79a400acba06f1d3c43885bda0c2f69c2e809ed5 /ExpressionCompiler.cpp | |
parent | 4b6c42231595cd8a53327656db4ac22db70960d5 (diff) | |
download | dexon-solidity-13baaf98b8a3ca2a97c96e5a25398a0cae26e5fb.tar.gz dexon-solidity-13baaf98b8a3ca2a97c96e5a25398a0cae26e5fb.tar.zst dexon-solidity-13baaf98b8a3ca2a97c96e5a25398a0cae26e5fb.zip |
Proper type promotion and conversion.
Diffstat (limited to 'ExpressionCompiler.cpp')
-rw-r--r-- | ExpressionCompiler.cpp | 81 |
1 files changed, 54 insertions, 27 deletions
diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp index a7d87221..0df74184 100644 --- a/ExpressionCompiler.cpp +++ b/ExpressionCompiler.cpp @@ -37,6 +37,13 @@ void ExpressionCompiler::compileExpression(CompilerContext& _context, Expression _expression.accept(compiler); } +void ExpressionCompiler::appendTypeConversion(CompilerContext& _context, + Type const& _typeOnStack, Type const& _targetType) +{ + ExpressionCompiler compiler(_context); + compiler.appendTypeConversion(_typeOnStack, _targetType); +} + bool ExpressionCompiler::visit(Assignment& _assignment) { m_currentLValue = nullptr; @@ -44,7 +51,7 @@ bool ExpressionCompiler::visit(Assignment& _assignment) Expression& rightHandSide = _assignment.getRightHandSide(); rightHandSide.accept(*this); Type const& resultType = *_assignment.getType(); - cleanHigherOrderBitsIfNeeded(*rightHandSide.getType(), resultType); + appendTypeConversion(*rightHandSide.getType(), resultType); _assignment.getLeftHandSide().accept(*this); Token::Value op = _assignment.getAssignmentOperator(); @@ -123,10 +130,21 @@ bool ExpressionCompiler::visit(BinaryOperation& _binaryOperation) } else { + bool cleanupNeeded = false; + if (commonType.getCategory() == Type::Category::INTEGER) + if (Token::isCompareOp(op) || op == Token::DIV || op == Token::MOD) + cleanupNeeded = true; + leftExpression.accept(*this); - cleanHigherOrderBitsIfNeeded(*leftExpression.getType(), commonType); + if (cleanupNeeded) + appendHighBitsCleanup(dynamic_cast<IntegerType const&>(*leftExpression.getType())); + else + appendTypeConversion(*leftExpression.getType(), commonType); rightExpression.accept(*this); - cleanHigherOrderBitsIfNeeded(*rightExpression.getType(), commonType); + if (cleanupNeeded) + appendHighBitsCleanup(dynamic_cast<IntegerType const&>(*leftExpression.getType())); + else + appendTypeConversion(*rightExpression.getType(), commonType); if (Token::isCompareOp(op)) appendCompareOperatorCode(op, commonType); else @@ -146,7 +164,7 @@ bool ExpressionCompiler::visit(FunctionCall& _functionCall) BOOST_THROW_EXCEPTION(InternalCompilerError()); Expression& firstArgument = *_functionCall.getArguments().front(); firstArgument.accept(*this); - cleanHigherOrderBitsIfNeeded(*firstArgument.getType(), *_functionCall.getType()); + appendTypeConversion(*firstArgument.getType(), *_functionCall.getType()); } else { @@ -163,7 +181,7 @@ bool ExpressionCompiler::visit(FunctionCall& _functionCall) for (unsigned i = 0; i < arguments.size(); ++i) { arguments[i]->accept(*this); - cleanHigherOrderBitsIfNeeded(*arguments[i]->getType(), + appendTypeConversion(*arguments[i]->getType(), *function.getParameters()[i]->getType()); } @@ -226,28 +244,6 @@ void ExpressionCompiler::endVisit(Literal& _literal) } } -void ExpressionCompiler::cleanHigherOrderBitsIfNeeded(Type const& _typeOnStack, Type const& _targetType) -{ - // If the type of one of the operands is extended, we need to remove all - // higher-order bits that we might have ignored in previous operations. - // @todo: store in the AST whether the operand might have "dirty" higher - // order bits - - if (_typeOnStack == _targetType) - return; - if (_typeOnStack.getCategory() == Type::Category::INTEGER && - _targetType.getCategory() == Type::Category::INTEGER) - { - //@todo - } - else - { - // If we get here, there is either an implementation missing to clean higher oder bits - // for non-integer types that are explicitly convertible or we got here in error. - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid type conversion requested.")); - } -} - void ExpressionCompiler::appendAndOrOperatorCode(BinaryOperation& _binaryOperation) { Token::Value const op = _binaryOperation.getOperator(); @@ -372,6 +368,37 @@ void ExpressionCompiler::appendShiftOperatorCode(Token::Value _operator) } } +void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type const& _targetType) +{ + // If the type of one of the operands is extended, we need to remove all + // higher-order bits that we might have ignored in previous operations. + // @todo: store in the AST whether the operand might have "dirty" higher + // order bits + + if (_typeOnStack == _targetType) + return; + if (_typeOnStack.getCategory() == Type::Category::INTEGER) + { + appendHighBitsCleanup(dynamic_cast<IntegerType const&>(_typeOnStack)); + } + else + { + // All other types should not be convertible to non-equal types. + assert(!_typeOnStack.isExplicitlyConvertibleTo(_targetType)); + assert(false); + } +} + +void ExpressionCompiler::appendHighBitsCleanup(IntegerType const& _typeOnStack) +{ + if (_typeOnStack.getNumBits() == 256) + return; + else if (_typeOnStack.isSigned()) + m_context << u256(_typeOnStack.getNumBits() / 8 - 1) << eth::Instruction::SIGNEXTEND; + else + m_context << ((u256(1) << _typeOnStack.getNumBits()) - 1) << eth::Instruction::AND; +} + void ExpressionCompiler::storeInLValue(Expression const& _expression) { moveToLValue(_expression); |