diff --git a/libsolidity/codegen/ABIFunctions.cpp b/libsolidity/codegen/ABIFunctions.cpp index f6aa714d7..6c4ddc023 100644 --- a/libsolidity/codegen/ABIFunctions.cpp +++ b/libsolidity/codegen/ABIFunctions.cpp @@ -1439,17 +1439,18 @@ string ABIFunctions::shiftRightFunction(size_t _numBits, bool _signed) solAssert(_numBits < 256, ""); string functionName = "shift_right_" + to_string(_numBits) + (_signed ? "_signed" : "_unsigned"); - if (m_evmVersion.hasBitwiseShifting()) + + // NOTE: SAR rounds differently than SDIV + if (m_evmVersion.hasBitwiseShifting() && !_signed) { return createFunction(functionName, [&]() { return Whiskers(R"( function (value) -> newValue { - newValue := (, value) + newValue := shr(, value) } )") ("functionName", functionName) - ("shiftOp", _signed ? "sar" : "shr") ("numBits", to_string(_numBits)) .render(); }); diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index 46e81d49b..45ad1f471 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -1274,8 +1274,9 @@ void CompilerUtils::leftShiftNumberOnStack(unsigned _bits) void CompilerUtils::rightShiftNumberOnStack(unsigned _bits, bool _isSigned) { solAssert(_bits < 256, ""); - if (m_context.evmVersion().hasBitwiseShifting()) - m_context << _bits << (_isSigned ? Instruction::SAR : Instruction::SHR); + // NOTE: SAR rounds differently than SDIV + if (m_context.evmVersion().hasBitwiseShifting() && !_isSigned) + m_context << _bits << Instruction::SHR; else m_context << (u256(1) << _bits) << Instruction::SWAP1 << (_isSigned ? Instruction::SDIV : Instruction::DIV); } diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 1a33fe7cc..019867c55 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -1718,8 +1718,9 @@ void ExpressionCompiler::appendShiftOperatorCode(Token::Value _operator, Type co m_context << u256(2) << Instruction::EXP << Instruction::MUL; break; case Token::SAR: - if (m_context.evmVersion().hasBitwiseShifting()) - m_context << (c_valueSigned ? Instruction::SAR : Instruction::SHR); + // NOTE: SAR rounds differently than SDIV + if (m_context.evmVersion().hasBitwiseShifting() && !c_valueSigned) + m_context << Instruction::SHR; else m_context << u256(2) << Instruction::EXP << Instruction::SWAP1 << (c_valueSigned ? Instruction::SDIV : Instruction::DIV); break;