mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Cleanup allocation.
This commit is contained in:
@@ -1035,13 +1035,13 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
}
|
||||
solAssert(indexedArgs.size() <= 4, "Too many indexed arguments.");
|
||||
Whiskers templ(R"({
|
||||
let <pos> := <freeMemory>
|
||||
let <pos> := <allocateUnbounded>()
|
||||
let <end> := <encode>(<pos> <nonIndexedArgs>)
|
||||
<log>(<pos>, sub(<end>, <pos>) <indexedArgs>)
|
||||
})");
|
||||
templ("pos", m_context.newYulVariable());
|
||||
templ("end", m_context.newYulVariable());
|
||||
templ("freeMemory", freeMemory());
|
||||
templ("allocateUnbounded", m_utils.allocateUnboundedFunction());
|
||||
templ("encode", abi.tupleEncoder(nonIndexedArgTypes, nonIndexedParamTypes));
|
||||
templ("nonIndexedArgs", joinHumanReadablePrefixed(nonIndexedArgs));
|
||||
templ("log", "log" + to_string(indexedArgs.size()));
|
||||
@@ -1107,8 +1107,11 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
else
|
||||
{
|
||||
// Used to reset the free memory pointer later.
|
||||
// TODO This is an abuse of the `allocateUnbounded` function.
|
||||
// We might want to introduce a new set of memory handling functions here
|
||||
// a la "setMemoryCheckPoint" and "freeUntilCheckPoint".
|
||||
string freeMemoryPre = m_context.newYulVariable();
|
||||
m_code << "let " << freeMemoryPre << " := " << freeMemory() << "\n";
|
||||
m_code << "let " << freeMemoryPre << " := " << m_utils.allocateUnboundedFunction() << "()\n";
|
||||
IRVariable array = convert(*arguments[0], *TypeProvider::bytesMemory());
|
||||
IRVariable hashVariable(m_context.newYulVariable(), *TypeProvider::fixedBytes(32));
|
||||
|
||||
@@ -1125,26 +1128,26 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
IRVariable selectorVariable(m_context.newYulVariable(), *TypeProvider::fixedBytes(4));
|
||||
define(selectorVariable, hashVariable);
|
||||
selector = selectorVariable.name();
|
||||
m_code << "mstore(" << to_string(CompilerUtils::freeMemoryPointer) << ", " << freeMemoryPre << ")\n";
|
||||
m_code << m_utils.finalizeAllocationFunction() << "(" << freeMemoryPre << ", 0)\n";
|
||||
}
|
||||
}
|
||||
else if (functionType->kind() == FunctionType::Kind::ABIEncodeWithSelector)
|
||||
selector = convert(*arguments.front(), *TypeProvider::fixedBytes(4)).name();
|
||||
|
||||
Whiskers templ(R"(
|
||||
let <data> := <allocateTemporary>()
|
||||
let <mpos> := add(<data>, 0x20)
|
||||
let <data> := <allocateUnbounded>()
|
||||
let <memPtr> := add(<data>, 0x20)
|
||||
<?+selector>
|
||||
mstore(<mpos>, <selector>)
|
||||
<mpos> := add(<mpos>, 4)
|
||||
mstore(<memPtr>, <selector>)
|
||||
<memPtr> := add(<memPtr>, 4)
|
||||
</+selector>
|
||||
let <mend> := <encode>(<mpos><arguments>)
|
||||
let <mend> := <encode>(<memPtr><arguments>)
|
||||
mstore(<data>, sub(<mend>, add(<data>, 0x20)))
|
||||
mstore(<freeMemPtr>, <roundUp>(<mend>))
|
||||
<finalizeAllocation>(<data>, sub(<mend>, <data>))
|
||||
)");
|
||||
templ("data", IRVariable(_functionCall).part("mpos").name());
|
||||
templ("allocateTemporary", m_utils.allocationTemporaryMemoryFunction());
|
||||
templ("mpos", m_context.newYulVariable());
|
||||
templ("allocateUnbounded", m_utils.allocateUnboundedFunction());
|
||||
templ("memPtr", m_context.newYulVariable());
|
||||
templ("mend", m_context.newYulVariable());
|
||||
templ("selector", selector);
|
||||
templ("encode",
|
||||
@@ -1153,8 +1156,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
m_context.abiFunctions().tupleEncoder(argumentTypes, targetTypes, false)
|
||||
);
|
||||
templ("arguments", joinHumanReadablePrefixed(argumentVars));
|
||||
templ("freeMemPtr", to_string(CompilerUtils::freeMemoryPointer));
|
||||
templ("roundUp", m_utils.roundUpFunction());
|
||||
templ("finalizeAllocation", m_utils.finalizeAllocationFunction());
|
||||
|
||||
m_code << templ.render();
|
||||
break;
|
||||
@@ -1214,7 +1216,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
solAssert(type(*arguments.front()).isImplicitlyConvertibleTo(*TypeProvider::stringMemory()),"");
|
||||
|
||||
Whiskers templ(R"({
|
||||
let <pos> := <allocateTemporary>()
|
||||
let <pos> := <allocateUnbounded>()
|
||||
mstore(<pos>, <hash>)
|
||||
let <end> := <encode>(add(<pos>, 4) <argumentVars>)
|
||||
revert(<pos>, sub(<end>, <pos>))
|
||||
@@ -1222,7 +1224,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
templ("pos", m_context.newYulVariable());
|
||||
templ("end", m_context.newYulVariable());
|
||||
templ("hash", util::selectorFromSignature("Error(string)").str());
|
||||
templ("allocateTemporary", m_utils.allocationTemporaryMemoryFunction());
|
||||
templ("allocateUnbounded", m_utils.allocateUnboundedFunction());
|
||||
templ(
|
||||
"argumentVars",
|
||||
joinHumanReadablePrefixed(IRVariable{*arguments.front()}.stackSlots())
|
||||
@@ -1396,7 +1398,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
m_context.subObjectsCreated().insert(contract);
|
||||
|
||||
Whiskers t(R"(
|
||||
let <memPos> := <allocateTemporaryMemory>()
|
||||
let <memPos> := <allocateUnbounded>()
|
||||
let <memEnd> := add(<memPos>, datasize("<object>"))
|
||||
if or(gt(<memEnd>, 0xffffffffffffffff), lt(<memEnd>, <memPos>)) { <panic>() }
|
||||
datacopy(<memPos>, dataoffset("<object>"), datasize("<object>"))
|
||||
@@ -1411,12 +1413,10 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
<!isTryCall>
|
||||
if iszero(<address>) { <forwardingRevert>() }
|
||||
</isTryCall>
|
||||
<releaseTemporaryMemory>()
|
||||
)");
|
||||
t("memPos", m_context.newYulVariable());
|
||||
t("memEnd", m_context.newYulVariable());
|
||||
t("allocateTemporaryMemory", m_utils.allocationTemporaryMemoryFunction());
|
||||
t("releaseTemporaryMemory", m_utils.releaseTemporaryMemoryFunction());
|
||||
t("allocateUnbounded", m_utils.allocateUnboundedFunction());
|
||||
t("object", IRNames::creationObject(*contract));
|
||||
t("panic", m_utils.panicFunction(PanicCode::ResourceError));
|
||||
t("abiEncode",
|
||||
@@ -1489,7 +1489,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
argumentStrings += IRVariable(*arg).stackSlots();
|
||||
}
|
||||
Whiskers templ(R"(
|
||||
let <pos> := <allocateTemporary>()
|
||||
let <pos> := <allocateUnbounded>()
|
||||
let <end> := <encodeArgs>(<pos> <argumentString>)
|
||||
<?isECRecover>
|
||||
mstore(0, 0)
|
||||
@@ -1501,7 +1501,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
templ("call", m_context.evmVersion().hasStaticCall() ? "staticcall" : "call");
|
||||
templ("isCall", !m_context.evmVersion().hasStaticCall());
|
||||
templ("shl", m_utils.shiftLeftFunction(offset * 8));
|
||||
templ("allocateTemporary", m_utils.allocationTemporaryMemoryFunction());
|
||||
templ("allocateUnbounded", m_utils.allocateUnboundedFunction());
|
||||
templ("pos", m_context.newYulVariable());
|
||||
templ("end", m_context.newYulVariable());
|
||||
templ("isECRecover", FunctionType::Kind::ECRecover == functionType->kind());
|
||||
@@ -2363,14 +2363,14 @@ void IRGeneratorForStatements::appendExternalFunctionCall(
|
||||
// We could also just use MLOAD; POP right before the gas calculation, but the optimizer
|
||||
// would remove that, so we use MSTORE here.
|
||||
if (!funType.gasSet() && returnInfo.estimatedReturnSize > 0)
|
||||
m_code << "mstore(add(" << freeMemory() << ", " << to_string(returnInfo.estimatedReturnSize) << "), 0)\n";
|
||||
m_code << "mstore(add(" << m_utils.allocateUnboundedFunction() << "() , " << to_string(returnInfo.estimatedReturnSize) << "), 0)\n";
|
||||
}
|
||||
|
||||
Whiskers templ(R"(
|
||||
if iszero(extcodesize(<address>)) { <revertNoCode> }
|
||||
|
||||
// storage for arguments and returned data
|
||||
let <pos> := <freeMemory>
|
||||
let <pos> := <allocateUnbounded>()
|
||||
mstore(<pos>, <shl28>(<funSel>))
|
||||
let <end> := <encodeArgs>(add(<pos>, 4) <argumentString>)
|
||||
|
||||
@@ -2386,7 +2386,7 @@ void IRGeneratorForStatements::appendExternalFunctionCall(
|
||||
</dynamicReturnSize>
|
||||
|
||||
// update freeMemoryPointer according to dynamic return size
|
||||
mstore(<freeMemoryPointer>, add(<pos>, <roundUp>(<returnSize>)))
|
||||
<finalizeAllocation>(<pos>, <returnSize>)
|
||||
|
||||
// decode return parameters from external try-call into retVars
|
||||
<?+retVars> <retVars> := </+retVars> <abiDecode>(<pos>, add(<pos>, <returnSize>))
|
||||
@@ -2399,7 +2399,8 @@ void IRGeneratorForStatements::appendExternalFunctionCall(
|
||||
templ("success", IRNames::trySuccessConditionVariable(_functionCall));
|
||||
else
|
||||
templ("success", m_context.newYulVariable());
|
||||
templ("freeMemory", freeMemory());
|
||||
templ("allocateUnbounded", m_utils.allocateUnboundedFunction());
|
||||
templ("finalizeAllocation", m_utils.finalizeAllocationFunction());
|
||||
templ("shl28", m_utils.shiftLeftFunction(8 * (32 - 4)));
|
||||
|
||||
templ("funSel", IRVariable(_functionCall.expression()).part("functionSelector").name());
|
||||
@@ -2421,7 +2422,6 @@ void IRGeneratorForStatements::appendExternalFunctionCall(
|
||||
templ("roundUp", m_utils.roundUpFunction());
|
||||
templ("abiDecode", m_context.abiFunctions().tupleDecoder(returnInfo.returnTypes, true));
|
||||
templ("dynamicReturnSize", returnInfo.dynamicReturnSize);
|
||||
templ("freeMemoryPointer", to_string(CompilerUtils::freeMemoryPointer));
|
||||
|
||||
templ("noTryCall", !_functionCall.annotation().tryCall);
|
||||
|
||||
@@ -2489,7 +2489,7 @@ void IRGeneratorForStatements::appendBareCall(
|
||||
solAssert(!_functionCall.annotation().tryCall, "");
|
||||
Whiskers templ(R"(
|
||||
<?needsEncoding>
|
||||
let <pos> := mload(<freeMemoryPointer>)
|
||||
let <pos> := <allocateUnbounded>()
|
||||
let <length> := sub(<encode>(<pos> <?+arg>,</+arg> <arg>), <pos>)
|
||||
<!needsEncoding>
|
||||
let <pos> := add(<arg>, 0x20)
|
||||
@@ -2502,7 +2502,7 @@ void IRGeneratorForStatements::appendBareCall(
|
||||
</+returndataVar>
|
||||
)");
|
||||
|
||||
templ("freeMemoryPointer", to_string(CompilerUtils::freeMemoryPointer));
|
||||
templ("allocateUnbounded", m_utils.allocateUnboundedFunction());
|
||||
templ("pos", m_context.newYulVariable());
|
||||
templ("length", m_context.newYulVariable());
|
||||
|
||||
@@ -2562,11 +2562,6 @@ void IRGeneratorForStatements::appendBareCall(
|
||||
m_code << templ.render();
|
||||
}
|
||||
|
||||
string IRGeneratorForStatements::freeMemory()
|
||||
{
|
||||
return "mload(" + to_string(CompilerUtils::freeMemoryPointer) + ")";
|
||||
}
|
||||
|
||||
IRVariable IRGeneratorForStatements::convert(IRVariable const& _from, Type const& _to)
|
||||
{
|
||||
if (_from.type() == _to)
|
||||
|
||||
Reference in New Issue
Block a user