Zero initialize memory arrays

This commit is contained in:
Leonardo Alt
2020-04-02 15:55:18 +02:00
parent 8d28089abc
commit 39ff0deb05
22 changed files with 475 additions and 35 deletions
@@ -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
+13
View File
@@ -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.
+3
View File
@@ -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);