mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Zero initialize memory arrays
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
|
||||
#include <libsolidity/codegen/YulUtilFunctions.h>
|
||||
#include <libsolidity/ast/AST.h>
|
||||
#include <libsolidity/ast/TypeProvider.h>
|
||||
|
||||
#include <libsolutil/Whiskers.h>
|
||||
#include <libsolutil/StringUtils.h>
|
||||
@@ -112,9 +113,10 @@ string IRGenerationContext::internalDispatch(size_t _in, size_t _out)
|
||||
for (auto const& contract: mostDerivedContract().annotation().linearizedBaseContracts)
|
||||
for (FunctionDefinition const* function: contract->definedFunctions())
|
||||
if (
|
||||
FunctionType const* functionType = TypeProvider::function(*function)->asCallableFunction(false);
|
||||
!function->isConstructor() &&
|
||||
function->parameters().size() == _in &&
|
||||
function->returnParameters().size() == _out
|
||||
TupleType(functionType->parameterTypes()).sizeOnStack() == _in &&
|
||||
TupleType(functionType->returnParameterTypes()).sizeOnStack() == _out
|
||||
)
|
||||
{
|
||||
// 0 is reserved for uninitialized function pointers
|
||||
|
||||
@@ -133,6 +133,7 @@ string IRGenerator::generateFunction(FunctionDefinition const& _function)
|
||||
return m_context.functionCollector().createFunction(functionName, [&]() {
|
||||
Whiskers t(R"(
|
||||
function <functionName>(<params>) <returns> {
|
||||
<initReturnVariables>
|
||||
<body>
|
||||
}
|
||||
)");
|
||||
@@ -142,9 +143,14 @@ string IRGenerator::generateFunction(FunctionDefinition const& _function)
|
||||
params += (params.empty() ? "" : ", ") + m_context.addLocalVariable(*varDecl).commaSeparatedList();
|
||||
t("params", params);
|
||||
string retParams;
|
||||
string retInit;
|
||||
for (auto const& varDecl: _function.returnParameters())
|
||||
{
|
||||
retParams += (retParams.empty() ? "" : ", ") + m_context.addLocalVariable(*varDecl).commaSeparatedList();
|
||||
retInit += generateInitialAssignment(*varDecl);
|
||||
}
|
||||
t("returns", retParams.empty() ? "" : " -> " + retParams);
|
||||
t("initReturnVariables", retInit);
|
||||
t("body", generate(_function.body()));
|
||||
return t.render();
|
||||
});
|
||||
@@ -226,6 +232,13 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
||||
}
|
||||
}
|
||||
|
||||
string IRGenerator::generateInitialAssignment(VariableDeclaration const& _varDecl)
|
||||
{
|
||||
IRGeneratorForStatements generator(m_context, m_utils);
|
||||
generator.initializeLocalVar(_varDecl);
|
||||
return generator.code();
|
||||
}
|
||||
|
||||
string IRGenerator::constructorCode(ContractDefinition const& _contract)
|
||||
{
|
||||
// Initialization of state variables in base-to-derived order.
|
||||
|
||||
@@ -61,6 +61,9 @@ private:
|
||||
/// Generates a getter for the given declaration and returns its name
|
||||
std::string generateGetter(VariableDeclaration const& _varDecl);
|
||||
|
||||
/// Generates code that assigns the initial value of the respective type.
|
||||
std::string generateInitialAssignment(VariableDeclaration const& _varDecl);
|
||||
|
||||
std::string constructorCode(ContractDefinition const& _contract);
|
||||
std::string deployCode(ContractDefinition const& _contract);
|
||||
std::string callValueCheck();
|
||||
|
||||
@@ -154,6 +154,19 @@ void IRGeneratorForStatements::initializeStateVar(VariableDeclaration const& _va
|
||||
}
|
||||
}
|
||||
|
||||
void IRGeneratorForStatements::initializeLocalVar(VariableDeclaration const& _varDecl)
|
||||
{
|
||||
solAssert(m_context.isLocalVariable(_varDecl), "Must be a local variable.");
|
||||
|
||||
auto const* type = _varDecl.type();
|
||||
if (auto const* refType = dynamic_cast<ReferenceType const*>(type))
|
||||
if (refType->dataStoredIn(DataLocation::Storage) && refType->isPointer())
|
||||
return;
|
||||
|
||||
IRVariable zero = zeroValue(*type);
|
||||
assign(m_context.localVariable(_varDecl), zero);
|
||||
}
|
||||
|
||||
void IRGeneratorForStatements::endVisit(VariableDeclarationStatement const& _varDeclStatement)
|
||||
{
|
||||
if (Expression const* expression = _varDeclStatement.initialValue())
|
||||
@@ -179,7 +192,10 @@ void IRGeneratorForStatements::endVisit(VariableDeclarationStatement const& _var
|
||||
else
|
||||
for (auto const& decl: _varDeclStatement.declarations())
|
||||
if (decl)
|
||||
{
|
||||
declare(m_context.addLocalVariable(*decl));
|
||||
initializeLocalVar(*decl);
|
||||
}
|
||||
}
|
||||
|
||||
bool IRGeneratorForStatements::visit(Conditional const& _conditional)
|
||||
@@ -670,7 +686,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
|
||||
IRVariable value = convert(*arguments[0], *TypeProvider::uint256());
|
||||
define(_functionCall) <<
|
||||
m_utils.allocateMemoryArrayFunction(arrayType) <<
|
||||
m_utils.allocateAndInitializeMemoryArrayFunction(arrayType) <<
|
||||
"(" <<
|
||||
value.commaSeparatedList() <<
|
||||
")\n";
|
||||
@@ -1439,6 +1455,12 @@ std::ostream& IRGeneratorForStatements::define(IRVariable const& _var)
|
||||
return m_code;
|
||||
}
|
||||
|
||||
void IRGeneratorForStatements::declare(IRVariable const& _var)
|
||||
{
|
||||
if (_var.type().sizeOnStack() > 0)
|
||||
m_code << "let " << _var.commaSeparatedList() << "\n";
|
||||
}
|
||||
|
||||
void IRGeneratorForStatements::declareAssign(IRVariable const& _lhs, IRVariable const& _rhs, bool _declare)
|
||||
{
|
||||
string output;
|
||||
@@ -1458,10 +1480,15 @@ void IRGeneratorForStatements::declareAssign(IRVariable const& _lhs, IRVariable
|
||||
_rhs.commaSeparatedList() <<
|
||||
")\n";
|
||||
}
|
||||
void IRGeneratorForStatements::declare(IRVariable const& _var)
|
||||
|
||||
IRVariable IRGeneratorForStatements::zeroValue(Type const& _type, bool _splitFunctionTypes)
|
||||
{
|
||||
if (_var.type().sizeOnStack() > 0)
|
||||
m_code << "let " << _var.commaSeparatedList() << "\n";
|
||||
IRVariable irVar{
|
||||
"zero_value_for_type_" + _type.identifier() + m_context.newYulVariable(),
|
||||
_type
|
||||
};
|
||||
define(irVar) << m_utils.zeroValueFunction(_type, _splitFunctionTypes) << "()\n";
|
||||
return irVar;
|
||||
}
|
||||
|
||||
void IRGeneratorForStatements::appendSimpleUnaryOperation(UnaryOperation const& _operation, Expression const& _expr)
|
||||
|
||||
@@ -46,6 +46,8 @@ public:
|
||||
|
||||
/// Generates code to initialize the given state variable.
|
||||
void initializeStateVar(VariableDeclaration const& _varDecl);
|
||||
/// Generates code to initialize the given local variable.
|
||||
void initializeLocalVar(VariableDeclaration const& _varDecl);
|
||||
|
||||
void endVisit(VariableDeclarationStatement const& _variableDeclaration) override;
|
||||
bool visit(Conditional const& _conditional) override;
|
||||
@@ -100,6 +102,11 @@ private:
|
||||
|
||||
void declareAssign(IRVariable const& _var, IRVariable const& _value, bool _define);
|
||||
|
||||
/// @returns an IRVariable with the zero
|
||||
/// value of @a _type.
|
||||
/// @param _splitFunctionTypes if false, returns two zeroes
|
||||
IRVariable zeroValue(Type const& _type, bool _splitFunctionTypes = true);
|
||||
|
||||
void appendAndOrOperatorCode(BinaryOperation const& _binOp);
|
||||
void appendSimpleUnaryOperation(UnaryOperation const& _operation, Expression const& _expr);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user