| 778 | } |
| 779 | |
| 780 | std::string YulUtilFunctions::overflowCheckedIntMulFunction(IntegerType const& _type) |
| 781 | { |
| 782 | std::string functionName = "checked_mul_" + _type.identifier(); |
| 783 | return m_functionCollector.createFunction(functionName, [&]() { |
| 784 | return |
| 785 | // Multiplication by zero could be treated separately and directly return zero. |
| 786 | Whiskers(R"( |
| 787 | function <functionName>(x, y) -> product { |
| 788 | x := <cleanupFunction>(x) |
| 789 | y := <cleanupFunction>(y) |
| 790 | let product_raw := mul(x, y) |
| 791 | product := <cleanupFunction>(product_raw) |
| 792 | <?signed> |
| 793 | <?gt128bit> |
| 794 | <?256bit> |
| 795 | // special case |
| 796 | if and(slt(x, 0), eq(y, <minValue>)) { <panic>() } |
| 797 | </256bit> |
| 798 | // overflow, if x != 0 and y != product/x |
| 799 | if iszero( |
| 800 | or( |
| 801 | iszero(x), |
| 802 | eq(y, sdiv(product, x)) |
| 803 | ) |
| 804 | ) { <panic>() } |
| 805 | <!gt128bit> |
| 806 | if iszero(eq(product, product_raw)) { <panic>() } |
| 807 | </gt128bit> |
| 808 | <!signed> |
| 809 | <?gt128bit> |
| 810 | // overflow, if x != 0 and y != product/x |
| 811 | if iszero( |
| 812 | or( |
| 813 | iszero(x), |
| 814 | eq(y, div(product, x)) |
| 815 | ) |
| 816 | ) { <panic>() } |
| 817 | <!gt128bit> |
| 818 | if iszero(eq(product, product_raw)) { <panic>() } |
| 819 | </gt128bit> |
| 820 | </signed> |
| 821 | } |
| 822 | )") |
| 823 | ("functionName", functionName) |
| 824 | ("signed", _type.isSigned()) |
| 825 | ("cleanupFunction", cleanupFunction(_type)) |
| 826 | ("panic", panicFunction(PanicCode::UnderOverflow)) |
| 827 | ("minValue", toCompactHexWithPrefix(u256(_type.minValue()))) |
| 828 | ("256bit", _type.numBits() == 256) |
| 829 | ("gt128bit", _type.numBits() > 128) |
| 830 | .render(); |
| 831 | }); |
| 832 | } |
| 833 | |
| 834 | std::string YulUtilFunctions::wrappingIntMulFunction(IntegerType const& _type) |
| 835 | { |
no test coverage detected