MCPcopy Create free account
hub / github.com/argotorg/solidity / calculateMaxStackHeight

Function calculateMaxStackHeight

libevmasm/Assembly.cpp:1035–1120  ·  view source on GitHub ↗

Calculates maximum stack height for given code section. According to EIP5450 https://eips.ethereum.org/EIPS/eip-5450

Source from the content-addressed store, hash-verified

1033
1034// Calculates maximum stack height for given code section. According to EIP5450 https://eips.ethereum.org/EIPS/eip-5450
1035uint16_t calculateMaxStackHeight(Assembly::CodeSection const& _section)
1036{
1037 static auto constexpr UNVISITED = std::numeric_limits<size_t>::max();
1038
1039 AssemblyItems const& items = _section.items;
1040 solAssert(!items.empty());
1041 uint16_t overallMaxHeight = _section.inputs;
1042 std::stack<size_t> worklist;
1043 std::vector<size_t> maxStackHeights(items.size(), UNVISITED);
1044
1045 // Init first item stack height to number of inputs to the code section
1046 // maxStackHeights stores stack height for an item before the item execution
1047 maxStackHeights[0] = _section.inputs;
1048 // Push first item index to the worklist
1049 worklist.push(0u);
1050 while (!worklist.empty())
1051 {
1052 size_t idx = worklist.top();
1053 worklist.pop();
1054 AssemblyItem const& item = items[idx];
1055 size_t stackHeightChange = item.deposit();
1056 size_t currentMaxHeight = maxStackHeights[idx];
1057 solAssert(currentMaxHeight != UNVISITED);
1058
1059 std::vector<size_t> successors;
1060
1061 // Add next instruction to successors for non-control-flow-changing instructions
1062 if (
1063 !(item.hasInstruction() && SemanticInformation::terminatesControlFlow(item.instruction())) &&
1064 item.type() != RelativeJump &&
1065 item.type() != RetF &&
1066 item.type() != JumpF
1067 )
1068 {
1069 solAssert(idx < items.size() - 1, "No terminating instruction.");
1070 successors.emplace_back(idx + 1);
1071 }
1072
1073 // Add jumps destinations to successors
1074 // TODO: Remember to add RJUMPV when it is supported.
1075 if (item.type() == RelativeJump || item.type() == ConditionalRelativeJump)
1076 {
1077 auto const tagIt = std::find(items.begin(), items.end(), item.tag());
1078 solAssert(tagIt != items.end(), "Tag not found.");
1079 successors.emplace_back(static_cast<size_t>(std::distance(items.begin(), tagIt)));
1080 // TODO: This assert fails until the code is not topologically sorted. Uncomment when sorting introduced.
1081 // If backward jump the successor must be already visited.
1082 // solAssert(idx <= successors.back() || maxStackHeights[successors.back()] != UNVISITED);
1083 }
1084
1085 solRequire(
1086 currentMaxHeight + stackHeightChange <= std::numeric_limits<uint16_t>::max(),
1087 AssemblyException,
1088 "Stack overflow in EOF function."
1089 );
1090 overallMaxHeight = std::max(overallMaxHeight, static_cast<uint16_t>(currentMaxHeight + stackHeightChange));
1091 currentMaxHeight += stackHeightChange;
1092

Callers 1

createEOFHeaderMethod · 0.85

Calls 11

hasInstructionMethod · 0.80
tagMethod · 0.80
emptyMethod · 0.45
sizeMethod · 0.45
pushMethod · 0.45
popMethod · 0.45
depositMethod · 0.45
instructionMethod · 0.45
typeMethod · 0.45
beginMethod · 0.45
endMethod · 0.45

Tested by

no test coverage detected