MCPcopy Create free account
hub / github.com/argotorg/solidity / operator()

Method operator()

libyul/optimiser/StackToMemoryMover.cpp:117–196  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

115}
116
117void StackToMemoryMover::operator()(FunctionDefinition& _functionDefinition)
118{
119 // It is important to first visit the function body, so that it doesn't replace the memory inits for
120 // variable arguments we might generate below.
121 ASTModifier::operator()(_functionDefinition);
122
123 std::vector<Statement> memoryVariableInits;
124
125 // All function parameters with a memory slot are moved at the beginning of the function body.
126 for (NameWithDebugData const& param: _functionDefinition.parameters)
127 if (auto slot = m_memoryOffsetTracker(param.name))
128 memoryVariableInits += generateMemoryStore(
129 m_context.dialect,
130 param.debugData,
131 *slot,
132 Identifier{param.debugData, param.name}
133 );
134
135 // All memory return variables have to be initialized to zero in memory.
136 for (NameWithDebugData const& returnVariable: _functionDefinition.returnVariables)
137 if (auto slot = m_memoryOffsetTracker(returnVariable.name))
138 memoryVariableInits += generateMemoryStore(
139 m_context.dialect,
140 returnVariable.debugData,
141 *slot,
142 Literal{returnVariable.debugData, LiteralKind::Number, LiteralValue(u256{0})}
143 );
144
145 // Special case of a function with a single return argument that needs to move to memory.
146 if (_functionDefinition.returnVariables.size() == 1 && m_memoryOffsetTracker(_functionDefinition.returnVariables.front().name))
147 {
148 NameWithDebugDataList stackParameters = _functionDefinition.parameters | ranges::views::filter(
149 std::not_fn(m_memoryOffsetTracker)
150 ) | ranges::to<NameWithDebugDataList>;
151 // Generate new function without return variable and with only the non-moved parameters.
152 YulName newFunctionName = m_context.dispenser.newName(_functionDefinition.name);
153 m_newFunctionDefinitions.emplace_back(FunctionDefinition{
154 _functionDefinition.debugData,
155 newFunctionName,
156 stackParameters,
157 {},
158 std::move(_functionDefinition.body)
159 });
160 // Generate new names for the arguments to maintain disambiguation.
161 std::map<YulName, YulName> newArgumentNames;
162 for (NameWithDebugData const& _var: stackParameters)
163 newArgumentNames[_var.name] = m_context.dispenser.newName(_var.name);
164 for (auto& parameter: _functionDefinition.parameters)
165 parameter.name = util::valueOrDefault(newArgumentNames, parameter.name, parameter.name);
166 // Replace original function by a call to the new function and an assignment to the return variable from memory.
167 _functionDefinition.body = Block{_functionDefinition.debugData, std::move(memoryVariableInits)};
168 _functionDefinition.body.statements.emplace_back(ExpressionStatement{
169 _functionDefinition.debugData,
170 FunctionCall{
171 _functionDefinition.debugData,
172 Identifier{_functionDefinition.debugData, newFunctionName},
173 stackParameters | ranges::views::transform([&](NameWithDebugData const& _arg) {
174 return Expression{Identifier{_arg.debugData, newArgumentNames.at(_arg.name)}};

Callers

nothing calls this directly

Calls 15

generateMemoryStoreFunction · 0.85
filterFunction · 0.85
valueOrDefaultFunction · 0.85
generateMemoryLoadFunction · 0.85
isBuiltinFunctionCallFunction · 0.85
contains_ifFunction · 0.85
iterateReplacingFunction · 0.85
toCompactHexWithPrefixFunction · 0.85
newNameMethod · 0.80
atMethod · 0.80
LiteralValueClass · 0.50
sizeMethod · 0.45

Tested by

no test coverage detected