| 920 | } |
| 921 | |
| 922 | std::string YulUtilFunctions::overflowCheckedIntSubFunction(IntegerType const& _type) |
| 923 | { |
| 924 | std::string functionName = "checked_sub_" + _type.identifier(); |
| 925 | return m_functionCollector.createFunction(functionName, [&] { |
| 926 | return |
| 927 | Whiskers(R"( |
| 928 | function <functionName>(x, y) -> diff { |
| 929 | x := <cleanupFunction>(x) |
| 930 | y := <cleanupFunction>(y) |
| 931 | diff := sub(x, y) |
| 932 | <?signed> |
| 933 | <?256bit> |
| 934 | // underflow, if y >= 0 and diff > x |
| 935 | // overflow, if y < 0 and diff < x |
| 936 | if or( |
| 937 | and(iszero(slt(y, 0)), sgt(diff, x)), |
| 938 | and(slt(y, 0), slt(diff, x)) |
| 939 | ) { <panic>() } |
| 940 | <!256bit> |
| 941 | if or( |
| 942 | slt(diff, <minValue>), |
| 943 | sgt(diff, <maxValue>) |
| 944 | ) { <panic>() } |
| 945 | </256bit> |
| 946 | <!signed> |
| 947 | <?256bit> |
| 948 | if gt(diff, x) { <panic>() } |
| 949 | <!256bit> |
| 950 | if gt(diff, <maxValue>) { <panic>() } |
| 951 | </256bit> |
| 952 | </signed> |
| 953 | } |
| 954 | )") |
| 955 | ("functionName", functionName) |
| 956 | ("signed", _type.isSigned()) |
| 957 | ("maxValue", toCompactHexWithPrefix(u256(_type.maxValue()))) |
| 958 | ("minValue", toCompactHexWithPrefix(u256(_type.minValue()))) |
| 959 | ("cleanupFunction", cleanupFunction(_type)) |
| 960 | ("panic", panicFunction(PanicCode::UnderOverflow)) |
| 961 | ("256bit", _type.numBits() == 256) |
| 962 | .render(); |
| 963 | }); |
| 964 | } |
| 965 | |
| 966 | std::string YulUtilFunctions::wrappingIntSubFunction(IntegerType const& _type) |
| 967 | { |
no test coverage detected