mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Use vector of slots.
This commit is contained in:
parent
3212cb6caa
commit
f38cf85482
@ -169,24 +169,24 @@ string IRGenerator::generateFunction(FunctionDefinition const& _function)
|
|||||||
string functionName = m_context.functionName(_function);
|
string functionName = m_context.functionName(_function);
|
||||||
return m_context.functionCollector().createFunction(functionName, [&]() {
|
return m_context.functionCollector().createFunction(functionName, [&]() {
|
||||||
Whiskers t(R"(
|
Whiskers t(R"(
|
||||||
function <functionName>(<params>) <returns> {
|
function <functionName>(<params>)<?+retParams> -> <retParams></+retParams> {
|
||||||
<initReturnVariables>
|
<initReturnVariables>
|
||||||
<body>
|
<body>
|
||||||
}
|
}
|
||||||
)");
|
)");
|
||||||
t("functionName", functionName);
|
t("functionName", functionName);
|
||||||
string params;
|
vector<string> params;
|
||||||
for (auto const& varDecl: _function.parameters())
|
for (auto const& varDecl: _function.parameters())
|
||||||
params += (params.empty() ? "" : ", ") + m_context.addLocalVariable(*varDecl).commaSeparatedList();
|
params += m_context.addLocalVariable(*varDecl).stackSlots();
|
||||||
t("params", params);
|
t("params", joinHumanReadable(params));
|
||||||
string retParams;
|
vector<string> retParams;
|
||||||
string retInit;
|
string retInit;
|
||||||
for (auto const& varDecl: _function.returnParameters())
|
for (auto const& varDecl: _function.returnParameters())
|
||||||
{
|
{
|
||||||
retParams += (retParams.empty() ? "" : ", ") + m_context.addLocalVariable(*varDecl).commaSeparatedList();
|
retParams += m_context.addLocalVariable(*varDecl).stackSlots();
|
||||||
retInit += generateInitialAssignment(*varDecl);
|
retInit += generateInitialAssignment(*varDecl);
|
||||||
}
|
}
|
||||||
t("returns", retParams.empty() ? "" : " -> " + retParams);
|
t("retParams", joinHumanReadable(retParams));
|
||||||
t("initReturnVariables", retInit);
|
t("initReturnVariables", retInit);
|
||||||
t("body", generate(_function.body()));
|
t("body", generate(_function.body()));
|
||||||
return t.render();
|
return t.render();
|
||||||
@ -300,11 +300,11 @@ string IRGenerator::generateInitialAssignment(VariableDeclaration const& _varDec
|
|||||||
return generator.code();
|
return generator.code();
|
||||||
}
|
}
|
||||||
|
|
||||||
pair<string, map<ContractDefinition const*, string>> IRGenerator::evaluateConstructorArguments(
|
pair<string, map<ContractDefinition const*, vector<string>>> IRGenerator::evaluateConstructorArguments(
|
||||||
ContractDefinition const& _contract
|
ContractDefinition const& _contract
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
map<ContractDefinition const*, string> constructorParams;
|
map<ContractDefinition const*, vector<string>> constructorParams;
|
||||||
vector<pair<ContractDefinition const*, std::vector<ASTPointer<Expression>>const *>> baseConstructorArguments;
|
vector<pair<ContractDefinition const*, std::vector<ASTPointer<Expression>>const *>> baseConstructorArguments;
|
||||||
|
|
||||||
for (ASTPointer<InheritanceSpecifier> const& base: _contract.baseContracts())
|
for (ASTPointer<InheritanceSpecifier> const& base: _contract.baseContracts())
|
||||||
@ -338,11 +338,11 @@ pair<string, map<ContractDefinition const*, string>> IRGenerator::evaluateConstr
|
|||||||
{
|
{
|
||||||
vector<string> params;
|
vector<string> params;
|
||||||
for (size_t i = 0; i < arguments->size(); ++i)
|
for (size_t i = 0; i < arguments->size(); ++i)
|
||||||
params.emplace_back(generator.evaluateExpression(
|
params += generator.evaluateExpression(
|
||||||
*(arguments->at(i)),
|
*(arguments->at(i)),
|
||||||
*(baseContract->constructor()->parameters()[i]->type())
|
*(baseContract->constructor()->parameters()[i]->type())
|
||||||
).commaSeparatedList());
|
).stackSlots();
|
||||||
constructorParams[baseContract] = joinHumanReadable(params);
|
constructorParams[baseContract] = std::move(params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -363,16 +363,16 @@ string IRGenerator::initStateVariables(ContractDefinition const& _contract)
|
|||||||
void IRGenerator::generateImplicitConstructors(ContractDefinition const& _contract)
|
void IRGenerator::generateImplicitConstructors(ContractDefinition const& _contract)
|
||||||
{
|
{
|
||||||
auto listAllParams = [&](
|
auto listAllParams = [&](
|
||||||
map<ContractDefinition const*, string> const& baseParams) -> string
|
map<ContractDefinition const*, vector<string>> const& baseParams) -> vector<string>
|
||||||
{
|
{
|
||||||
vector<string> params;
|
vector<string> params;
|
||||||
for (ContractDefinition const* contract: _contract.annotation().linearizedBaseContracts)
|
for (ContractDefinition const* contract: _contract.annotation().linearizedBaseContracts)
|
||||||
if (baseParams.count(contract))
|
if (baseParams.count(contract))
|
||||||
params.emplace_back(baseParams.at(contract));
|
params += baseParams.at(contract);
|
||||||
return joinHumanReadable(params);
|
return params;
|
||||||
};
|
};
|
||||||
|
|
||||||
map<ContractDefinition const*, string> baseConstructorParams;
|
map<ContractDefinition const*, vector<string>> baseConstructorParams;
|
||||||
for (size_t i = 0; i < _contract.annotation().linearizedBaseContracts.size(); ++i)
|
for (size_t i = 0; i < _contract.annotation().linearizedBaseContracts.size(); ++i)
|
||||||
{
|
{
|
||||||
ContractDefinition const* contract = _contract.annotation().linearizedBaseContracts[i];
|
ContractDefinition const* contract = _contract.annotation().linearizedBaseContracts[i];
|
||||||
@ -387,16 +387,16 @@ void IRGenerator::generateImplicitConstructors(ContractDefinition const& _contra
|
|||||||
<userDefinedConstructorBody>
|
<userDefinedConstructorBody>
|
||||||
}
|
}
|
||||||
)");
|
)");
|
||||||
string params;
|
vector<string> params;
|
||||||
if (contract->constructor())
|
if (contract->constructor())
|
||||||
for (ASTPointer<VariableDeclaration> const& varDecl: contract->constructor()->parameters())
|
for (ASTPointer<VariableDeclaration> const& varDecl: contract->constructor()->parameters())
|
||||||
params += (params.empty() ? "" : ", ") + m_context.addLocalVariable(*varDecl).commaSeparatedList();
|
params += m_context.addLocalVariable(*varDecl).stackSlots();
|
||||||
t("params", params);
|
t("params", joinHumanReadable(params));
|
||||||
string baseParamsString = listAllParams(baseConstructorParams);
|
vector<string> baseParams = listAllParams(baseConstructorParams);
|
||||||
t("baseParams", baseParamsString);
|
t("baseParams", joinHumanReadable(baseParams));
|
||||||
t("comma", !params.empty() && !baseParamsString.empty() ? ", " : "");
|
t("comma", !params.empty() && !baseParams.empty() ? ", " : "");
|
||||||
t("functionName", implicitConstructorName(*contract));
|
t("functionName", implicitConstructorName(*contract));
|
||||||
pair<string, map<ContractDefinition const*, string>> evaluatedArgs = evaluateConstructorArguments(*contract);
|
pair<string, map<ContractDefinition const*, vector<string>>> evaluatedArgs = evaluateConstructorArguments(*contract);
|
||||||
baseConstructorParams.insert(evaluatedArgs.second.begin(), evaluatedArgs.second.end());
|
baseConstructorParams.insert(evaluatedArgs.second.begin(), evaluatedArgs.second.end());
|
||||||
t("evalBaseArguments", evaluatedArgs.first);
|
t("evalBaseArguments", evaluatedArgs.first);
|
||||||
if (i < _contract.annotation().linearizedBaseContracts.size() - 1)
|
if (i < _contract.annotation().linearizedBaseContracts.size() - 1)
|
||||||
@ -404,7 +404,7 @@ void IRGenerator::generateImplicitConstructors(ContractDefinition const& _contra
|
|||||||
t("hasNextConstructor", true);
|
t("hasNextConstructor", true);
|
||||||
ContractDefinition const* nextContract = _contract.annotation().linearizedBaseContracts[i + 1];
|
ContractDefinition const* nextContract = _contract.annotation().linearizedBaseContracts[i + 1];
|
||||||
t("nextConstructor", implicitConstructorName(*nextContract));
|
t("nextConstructor", implicitConstructorName(*nextContract));
|
||||||
t("nextParams", listAllParams(baseConstructorParams));
|
t("nextParams", joinHumanReadable(listAllParams(baseConstructorParams)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
t("hasNextConstructor", false);
|
t("hasNextConstructor", false);
|
||||||
|
@ -81,9 +81,8 @@ private:
|
|||||||
/// Evaluates constructor's arguments for all base contracts (listed in inheritance specifiers) of
|
/// Evaluates constructor's arguments for all base contracts (listed in inheritance specifiers) of
|
||||||
/// @a _contract
|
/// @a _contract
|
||||||
/// @returns Pair of expressions needed to evaluate params and list of parameters in a map contract -> params
|
/// @returns Pair of expressions needed to evaluate params and list of parameters in a map contract -> params
|
||||||
std::pair<std::string, std::map<ContractDefinition const*, std::string>> evaluateConstructorArguments(
|
std::pair<std::string, std::map<ContractDefinition const*, std::vector<std::string>>>
|
||||||
ContractDefinition const& _contract
|
evaluateConstructorArguments(ContractDefinition const& _contract);
|
||||||
);
|
|
||||||
|
|
||||||
/// Initializes state variables of
|
/// Initializes state variables of
|
||||||
/// @a _contract
|
/// @a _contract
|
||||||
|
@ -637,13 +637,6 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
|||||||
break;
|
break;
|
||||||
case FunctionType::Kind::Internal:
|
case FunctionType::Kind::Internal:
|
||||||
{
|
{
|
||||||
vector<string> args;
|
|
||||||
for (size_t i = 0; i < arguments.size(); ++i)
|
|
||||||
if (functionType->takesArbitraryParameters())
|
|
||||||
args.emplace_back(IRVariable(*arguments[i]).commaSeparatedList());
|
|
||||||
else
|
|
||||||
args.emplace_back(convert(*arguments[i], *parameterTypes[i]).commaSeparatedList());
|
|
||||||
|
|
||||||
optional<FunctionDefinition const*> functionDef;
|
optional<FunctionDefinition const*> functionDef;
|
||||||
if (auto memberAccess = dynamic_cast<MemberAccess const*>(&_functionCall.expression()))
|
if (auto memberAccess = dynamic_cast<MemberAccess const*>(&_functionCall.expression()))
|
||||||
{
|
{
|
||||||
@ -681,6 +674,13 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
|||||||
solAssert(functionDef.has_value(), "");
|
solAssert(functionDef.has_value(), "");
|
||||||
solAssert(functionDef.value() == nullptr || functionDef.value()->isImplemented(), "");
|
solAssert(functionDef.value() == nullptr || functionDef.value()->isImplemented(), "");
|
||||||
|
|
||||||
|
vector<string> args;
|
||||||
|
for (size_t i = 0; i < arguments.size(); ++i)
|
||||||
|
if (functionType->takesArbitraryParameters())
|
||||||
|
args += IRVariable(*arguments[i]).stackSlots();
|
||||||
|
else
|
||||||
|
args += convert(*arguments[i], *parameterTypes[i]).stackSlots();
|
||||||
|
|
||||||
if (functionDef.value() != nullptr)
|
if (functionDef.value() != nullptr)
|
||||||
define(_functionCall) <<
|
define(_functionCall) <<
|
||||||
m_context.enqueueFunctionForCodeGeneration(*functionDef.value()) <<
|
m_context.enqueueFunctionForCodeGeneration(*functionDef.value()) <<
|
||||||
@ -716,7 +716,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
|||||||
ABIFunctions abi(m_context.evmVersion(), m_context.revertStrings(), m_context.functionCollector());
|
ABIFunctions abi(m_context.evmVersion(), m_context.revertStrings(), m_context.functionCollector());
|
||||||
|
|
||||||
vector<IRVariable> indexedArgs;
|
vector<IRVariable> indexedArgs;
|
||||||
string nonIndexedArgs;
|
vector<string> nonIndexedArgs;
|
||||||
TypePointers nonIndexedArgTypes;
|
TypePointers nonIndexedArgTypes;
|
||||||
TypePointers nonIndexedParamTypes;
|
TypePointers nonIndexedParamTypes;
|
||||||
if (!event.isAnonymous())
|
if (!event.isAnonymous())
|
||||||
@ -739,9 +739,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
string vars = IRVariable(arg).commaSeparatedList();
|
nonIndexedArgs += IRVariable(arg).stackSlots();
|
||||||
if (!vars.empty())
|
|
||||||
nonIndexedArgs += ", " + move(vars);
|
|
||||||
nonIndexedArgTypes.push_back(arg.annotation().type);
|
nonIndexedArgTypes.push_back(arg.annotation().type);
|
||||||
nonIndexedParamTypes.push_back(paramTypes[i]);
|
nonIndexedParamTypes.push_back(paramTypes[i]);
|
||||||
}
|
}
|
||||||
@ -756,7 +754,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
|||||||
templ("end", m_context.newYulVariable());
|
templ("end", m_context.newYulVariable());
|
||||||
templ("freeMemory", freeMemory());
|
templ("freeMemory", freeMemory());
|
||||||
templ("encode", abi.tupleEncoder(nonIndexedArgTypes, nonIndexedParamTypes));
|
templ("encode", abi.tupleEncoder(nonIndexedArgTypes, nonIndexedParamTypes));
|
||||||
templ("nonIndexedArgs", nonIndexedArgs);
|
templ("nonIndexedArgs", joinHumanReadablePrefixed(nonIndexedArgs));
|
||||||
templ("log", "log" + to_string(indexedArgs.size()));
|
templ("log", "log" + to_string(indexedArgs.size()));
|
||||||
templ("indexedArgs", joinHumanReadablePrefixed(indexedArgs | boost::adaptors::transformed([&](auto const& _arg) {
|
templ("indexedArgs", joinHumanReadablePrefixed(indexedArgs | boost::adaptors::transformed([&](auto const& _arg) {
|
||||||
return _arg.commaSeparatedList();
|
return _arg.commaSeparatedList();
|
||||||
@ -813,8 +811,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
|||||||
templ("allocateTemporary", m_utils.allocationTemporaryMemoryFunction());
|
templ("allocateTemporary", m_utils.allocationTemporaryMemoryFunction());
|
||||||
templ(
|
templ(
|
||||||
"argumentVars",
|
"argumentVars",
|
||||||
(type(*arguments.front()).sizeOnStack() > 0 ? ", " : "") +
|
joinHumanReadablePrefixed(IRVariable{*arguments.front()}.stackSlots())
|
||||||
IRVariable{*arguments.front()}.commaSeparatedList()
|
|
||||||
);
|
);
|
||||||
templ("encode", m_context.abiFunctions().tupleEncoder(
|
templ("encode", m_context.abiFunctions().tupleEncoder(
|
||||||
{&type(*arguments.front())},
|
{&type(*arguments.front())},
|
||||||
@ -991,11 +988,11 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
|||||||
);
|
);
|
||||||
|
|
||||||
TypePointers argumentTypes;
|
TypePointers argumentTypes;
|
||||||
string constructorParams;
|
vector<string> constructorParams;
|
||||||
for (ASTPointer<Expression const> const& arg: arguments)
|
for (ASTPointer<Expression const> const& arg: arguments)
|
||||||
{
|
{
|
||||||
argumentTypes.push_back(arg->annotation().type);
|
argumentTypes.push_back(arg->annotation().type);
|
||||||
constructorParams += ", " + IRVariable{*arg}.commaSeparatedList();
|
constructorParams += IRVariable{*arg}.stackSlots();
|
||||||
}
|
}
|
||||||
|
|
||||||
ContractDefinition const* contract =
|
ContractDefinition const* contract =
|
||||||
@ -1023,7 +1020,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
|||||||
t("abiEncode",
|
t("abiEncode",
|
||||||
m_context.abiFunctions().tupleEncoder(argumentTypes, functionType->parameterTypes(), false)
|
m_context.abiFunctions().tupleEncoder(argumentTypes, functionType->parameterTypes(), false)
|
||||||
);
|
);
|
||||||
t("constructorParams", constructorParams);
|
t("constructorParams", joinHumanReadablePrefixed(constructorParams));
|
||||||
t("value", functionType->valueSet() ? IRVariable(_functionCall.expression()).part("value").name() : "0");
|
t("value", functionType->valueSet() ? IRVariable(_functionCall.expression()).part("value").name() : "0");
|
||||||
t("saltSet", functionType->saltSet());
|
t("saltSet", functionType->saltSet());
|
||||||
if (functionType->saltSet())
|
if (functionType->saltSet())
|
||||||
@ -1398,14 +1395,11 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess)
|
|||||||
solAssert(keyType.sizeOnStack() <= 1, "");
|
solAssert(keyType.sizeOnStack() <= 1, "");
|
||||||
|
|
||||||
string slot = m_context.newYulVariable();
|
string slot = m_context.newYulVariable();
|
||||||
Whiskers templ("let <slot> := <indexAccess>(<base> <key>)\n");
|
Whiskers templ("let <slot> := <indexAccess>(<base><?+key>,<key></+key>)\n");
|
||||||
templ("slot", slot);
|
templ("slot", slot);
|
||||||
templ("indexAccess", m_utils.mappingIndexAccessFunction(mappingType, keyType));
|
templ("indexAccess", m_utils.mappingIndexAccessFunction(mappingType, keyType));
|
||||||
templ("base", IRVariable(_indexAccess.baseExpression()).commaSeparatedList());
|
templ("base", IRVariable(_indexAccess.baseExpression()).commaSeparatedList());
|
||||||
if (keyType.sizeOnStack() == 0)
|
templ("key", IRVariable(*_indexAccess.indexExpression()).commaSeparatedList());
|
||||||
templ("key", "");
|
|
||||||
else
|
|
||||||
templ("key", ", " + IRVariable(*_indexAccess.indexExpression()).commaSeparatedList());
|
|
||||||
m_code << templ.render();
|
m_code << templ.render();
|
||||||
setLValue(_indexAccess, IRLValue{
|
setLValue(_indexAccess, IRLValue{
|
||||||
*_indexAccess.annotation().type,
|
*_indexAccess.annotation().type,
|
||||||
@ -1678,10 +1672,8 @@ void IRGeneratorForStatements::appendExternalFunctionCall(
|
|||||||
for (auto const& arg: _arguments)
|
for (auto const& arg: _arguments)
|
||||||
{
|
{
|
||||||
argumentTypes.emplace_back(&type(*arg));
|
argumentTypes.emplace_back(&type(*arg));
|
||||||
if (IRVariable(*arg).type().sizeOnStack() > 0)
|
argumentStrings += IRVariable(*arg).stackSlots();
|
||||||
argumentStrings.emplace_back(IRVariable(*arg).commaSeparatedList());
|
|
||||||
}
|
}
|
||||||
string argumentString = argumentStrings.empty() ? ""s : (", " + joinHumanReadable(argumentStrings));
|
|
||||||
|
|
||||||
solUnimplementedAssert(funKind != FunctionType::Kind::ECRecover, "");
|
solUnimplementedAssert(funKind != FunctionType::Kind::ECRecover, "");
|
||||||
|
|
||||||
@ -1796,7 +1788,7 @@ void IRGeneratorForStatements::appendExternalFunctionCall(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
templ("encodeArgs", abi.tupleEncoder(argumentTypes, funType.parameterTypes(), encodeForLibraryCall));
|
templ("encodeArgs", abi.tupleEncoder(argumentTypes, funType.parameterTypes(), encodeForLibraryCall));
|
||||||
templ("argumentString", argumentString);
|
templ("argumentString", joinHumanReadablePrefixed(argumentStrings));
|
||||||
|
|
||||||
// Output data will replace input data, unless we have ECRecover (then, output
|
// Output data will replace input data, unless we have ECRecover (then, output
|
||||||
// area will be 32 bytes just before input area).
|
// area will be 32 bytes just before input area).
|
||||||
|
@ -69,10 +69,11 @@ public:
|
|||||||
/// The returned IRVariable is itself typed with the type of the stack slot as defined
|
/// The returned IRVariable is itself typed with the type of the stack slot as defined
|
||||||
/// in ``m_type.stackItems()`` and may again occupy multiple stack slots.
|
/// in ``m_type.stackItems()`` and may again occupy multiple stack slots.
|
||||||
IRVariable part(std::string const& _slot) const;
|
IRVariable part(std::string const& _slot) const;
|
||||||
private:
|
|
||||||
/// @returns a vector containing the names of the stack slots of the variable.
|
/// @returns a vector containing the names of the stack slots of the variable.
|
||||||
std::vector<std::string> stackSlots() const;
|
std::vector<std::string> stackSlots() const;
|
||||||
|
|
||||||
|
private:
|
||||||
/// @returns a name consisting of the base name appended with an underscore and @æ _suffix,
|
/// @returns a name consisting of the base name appended with an underscore and @æ _suffix,
|
||||||
/// unless @a _suffix is empty, in which case the base name itself is returned.
|
/// unless @a _suffix is empty, in which case the base name itself is returned.
|
||||||
std::string suffixedName(std::string const& _suffix) const;
|
std::string suffixedName(std::string const& _suffix) const;
|
||||||
|
@ -33,6 +33,8 @@ contract Main {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
// ----
|
// ----
|
||||||
// getFlag() -> true
|
// getFlag() -> true
|
||||||
// getName() -> "abc"
|
// getName() -> "abc"
|
||||||
|
Loading…
Reference in New Issue
Block a user