This commit is contained in:
chriseth
2019-05-08 13:29:11 +02:00
parent 5fb85a6118
commit b4d6f847b4
6 changed files with 237 additions and 91 deletions
@@ -94,8 +94,11 @@ string IRGenerationContext::newYulVariable()
string IRGenerationContext::variable(Expression const& _expression)
{
unsigned size = _expression.annotation().type->sizeOnStack();
solUnimplementedAssert(size == 1, "");
return "expr_" + to_string(_expression.id());
string var = "expr_" + to_string(_expression.id());
if (size == 1)
return var;
else
return YulUtilFunctions::suffixedVariableNameList(move(var) + "_", 1, 1 + size);
}
string IRGenerationContext::internalDispatch(size_t _in, size_t _out)
@@ -24,6 +24,7 @@
#include <libsolidity/codegen/ir/IRGenerationContext.h>
#include <libsolidity/codegen/ir/IRLValue.h>
#include <libsolidity/codegen/YulUtilFunctions.h>
#include <libsolidity/codegen/ABIFunctions.h>
#include <libsolidity/codegen/CompilerUtils.h>
#include <libsolidity/ast/TypeProvider.h>
@@ -31,6 +32,7 @@
#include <libyul/AsmData.h>
#include <libyul/optimiser/ASTCopier.h>
#include <libdevcore/Whiskers.h>
#include <libdevcore/StringUtils.h>
#include <libdevcore/Whiskers.h>
#include <libdevcore/Keccak256.h>
@@ -370,6 +372,65 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
")\n";
break;
}
case FunctionType::Kind::Event:
{
auto const& event = dynamic_cast<EventDefinition const&>(functionType->declaration());
TypePointers paramTypes = functionType->parameterTypes();
ABIFunctions abi(m_context.evmVersion(), m_context.functionCollector());
vector<string> indexedArgs;
string nonIndexedArgs;
TypePointers nonIndexedArgTypes;
TypePointers nonIndexedParamTypes;
if (!event.isAnonymous())
{
indexedArgs.emplace_back(m_context.newYulVariable());
string signature = formatNumber(u256(h256::Arith(dev::keccak256(functionType->externalSignature()))));
m_code << "let " << indexedArgs.back() << " := " << signature << "\n";
}
for (size_t i = 0; i < event.parameters().size(); ++i)
{
Expression const& arg = *arguments[i];
if (event.parameters()[i]->isIndexed())
{
string value;
indexedArgs.emplace_back(m_context.newYulVariable());
if (auto const& referenceType = dynamic_cast<ReferenceType const*>(paramTypes[i]))
value =
m_utils.packedHashFunction({arg.annotation().type}, {referenceType}) +
"(" +
m_context.variable(arg) +
")";
else
value = expressionAsType(arg, *paramTypes[i]);
m_code << "let " << indexedArgs.back() << " := " << value << "\n";
}
else
{
string vars = m_context.variable(arg);
if (!vars.empty())
// In reverse because abi_encode expects it like that.
nonIndexedArgs = ", " + move(vars) + nonIndexedArgs;
nonIndexedArgTypes.push_back(arg.annotation().type);
nonIndexedParamTypes.push_back(paramTypes[i]);
}
}
solAssert(indexedArgs.size() <= 4, "Too many indexed arguments.");
Whiskers templ(R"({
let <pos> := mload(<freeMemoryPointer>)
let <end> := <encode>(<pos> <nonIndexedArgs>)
<log>(<pos>, sub(<end>, <pos>) <indexedArgs>)
})");
templ("pos", m_context.newYulVariable());
templ("end", m_context.newYulVariable());
templ("freeMemoryPointer", to_string(CompilerUtils::freeMemoryPointer));
templ("encode", abi.tupleEncoder(nonIndexedArgTypes, nonIndexedParamTypes));
templ("nonIndexedArgs", nonIndexedArgs);
templ("log", "log" + to_string(indexedArgs.size()));
templ("indexedArgs", joinHumanReadablePrefixed(indexedArgs));
m_code << templ.render();
break;
}
case FunctionType::Kind::Assert:
case FunctionType::Kind::Require:
{
@@ -596,8 +657,26 @@ void IRGeneratorForStatements::endVisit(Identifier const& _identifier)
setLValue(_identifier, move(lvalue));
}
else if (auto contract = dynamic_cast<ContractDefinition const*>(declaration))
{
solUnimplementedAssert(!contract->isLibrary(), "Libraries not yet supported.");
}
else if (dynamic_cast<EventDefinition const*>(declaration))
{
// no-op
}
else if (dynamic_cast<EnumDefinition const*>(declaration))
{
// no-op
}
else if (dynamic_cast<StructDefinition const*>(declaration))
{
// no-op
}
else
solUnimplemented("Identifier of type " + declaration->type()->toString() + " not implemented.");
{
solAssert(false, "Identifier type not expected in expression context.");
}
}
bool IRGeneratorForStatements::visit(Literal const& _literal)