aboutsummaryrefslogtreecommitdiffstats
path: root/Compiler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Compiler.cpp')
-rw-r--r--Compiler.cpp88
1 files changed, 68 insertions, 20 deletions
diff --git a/Compiler.cpp b/Compiler.cpp
index 6ed6480f..eadfc204 100644
--- a/Compiler.cpp
+++ b/Compiler.cpp
@@ -25,6 +25,7 @@
#include <boost/range/adaptor/reversed.hpp>
#include <libevmcore/Instruction.h>
#include <libevmasm/Assembly.h>
+#include <libevmcore/Params.h>
#include <libsolidity/AST.h>
#include <libsolidity/ExpressionCompiler.h>
#include <libsolidity/CompilerUtils.h>
@@ -53,31 +54,45 @@ void Compiler::compileContract(ContractDefinition const& _contract,
m_context = CompilerContext(); // clear it just in case
{
CompilerContext::LocationSetter locationSetterRunTime(m_context, _contract);
- CompilerUtils(m_context).initialiseFreeMemoryPointer();
initializeContext(_contract, _contracts);
appendFunctionSelector(_contract);
- set<Declaration const*> functions = m_context.getFunctionsWithoutCode();
- while (!functions.empty())
- {
- for (Declaration const* function: functions)
- {
- m_context.setStackOffset(0);
- function->accept(*this);
- }
- functions = m_context.getFunctionsWithoutCode();
- }
+ appendFunctionsWithoutCode();
}
// Swap the runtime context with the creation-time context
swap(m_context, m_runtimeContext);
CompilerContext::LocationSetter locationSetterCreationTime(m_context, _contract);
- CompilerUtils(m_context).initialiseFreeMemoryPointer();
initializeContext(_contract, _contracts);
packIntoContractCreator(_contract, m_runtimeContext);
if (m_optimize)
m_context.optimise(m_optimizeRuns);
}
+void Compiler::compileClone(
+ ContractDefinition const& _contract,
+ map<ContractDefinition const*, bytes const*> const& _contracts
+)
+{
+ m_context = CompilerContext(); // clear it just in case
+ initializeContext(_contract, _contracts);
+
+ appendInitAndConstructorCode(_contract);
+
+ //@todo determine largest return size of all runtime functions
+ eth::AssemblyItem runtimeSub = m_context.addSubroutine(getCloneRuntime());
+ solAssert(runtimeSub.data() < numeric_limits<size_t>::max(), "");
+ m_runtimeSub = size_t(runtimeSub.data());
+
+ // stack contains sub size
+ m_context << eth::Instruction::DUP1 << runtimeSub << u256(0) << eth::Instruction::CODECOPY;
+ m_context << u256(0) << eth::Instruction::RETURN;
+
+ appendFunctionsWithoutCode();
+
+ if (m_optimize)
+ m_context.optimise(m_optimizeRuns);
+}
+
eth::AssemblyItem Compiler::getFunctionEntryLabel(FunctionDefinition const& _function) const
{
return m_runtimeContext.getFunctionEntryLabelIfExists(_function);
@@ -86,13 +101,14 @@ eth::AssemblyItem Compiler::getFunctionEntryLabel(FunctionDefinition const& _fun
void Compiler::initializeContext(ContractDefinition const& _contract,
map<ContractDefinition const*, bytes const*> const& _contracts)
{
+ CompilerUtils(m_context).initialiseFreeMemoryPointer();
m_context.setCompiledContracts(_contracts);
m_context.setInheritanceHierarchy(_contract.getLinearizedBaseContracts());
registerStateVariables(_contract);
m_context.resetVisitedNodes(&_contract);
}
-void Compiler::packIntoContractCreator(ContractDefinition const& _contract, CompilerContext const& _runtimeContext)
+void Compiler::appendInitAndConstructorCode(ContractDefinition const& _contract)
{
// Determine the arguments that are used for the base constructors.
std::vector<ContractDefinition const*> const& bases = _contract.getLinearizedBaseContracts();
@@ -126,22 +142,22 @@ void Compiler::packIntoContractCreator(ContractDefinition const& _contract, Comp
appendConstructor(*constructor);
else if (auto c = m_context.getNextConstructor(_contract))
appendBaseConstructor(*c);
+}
+
+void Compiler::packIntoContractCreator(ContractDefinition const& _contract, CompilerContext const& _runtimeContext)
+{
+ appendInitAndConstructorCode(_contract);
eth::AssemblyItem runtimeSub = m_context.addSubroutine(_runtimeContext.getAssembly());
solAssert(runtimeSub.data() < numeric_limits<size_t>::max(), "");
m_runtimeSub = size_t(runtimeSub.data());
+
// stack contains sub size
m_context << eth::Instruction::DUP1 << runtimeSub << u256(0) << eth::Instruction::CODECOPY;
m_context << u256(0) << eth::Instruction::RETURN;
// note that we have to include the functions again because of absolute jump labels
- set<Declaration const*> functions = m_context.getFunctionsWithoutCode();
- while (!functions.empty())
- {
- for (Declaration const* function: functions)
- function->accept(*this);
- functions = m_context.getFunctionsWithoutCode();
- }
+ appendFunctionsWithoutCode();
}
void Compiler::appendBaseConstructor(FunctionDefinition const& _constructor)
@@ -618,6 +634,20 @@ bool Compiler::visit(PlaceholderStatement const& _placeholderStatement)
return true;
}
+void Compiler::appendFunctionsWithoutCode()
+{
+ set<Declaration const*> functions = m_context.getFunctionsWithoutCode();
+ while (!functions.empty())
+ {
+ for (Declaration const* function: functions)
+ {
+ m_context.setStackOffset(0);
+ function->accept(*this);
+ }
+ functions = m_context.getFunctionsWithoutCode();
+ }
+}
+
void Compiler::appendModifierOrFunctionCode()
{
solAssert(m_currentFunction, "");
@@ -674,3 +704,21 @@ void Compiler::compileExpression(Expression const& _expression, TypePointer cons
if (_targetType)
CompilerUtils(m_context).convertType(*_expression.getType(), *_targetType);
}
+
+eth::Assembly Compiler::getCloneRuntime()
+{
+ eth::Assembly a;
+ a << eth::Instruction::CALLDATASIZE;
+ a << u256(0) << eth::Instruction::DUP1 << eth::Instruction::CALLDATACOPY;
+ //@todo adjust for larger return values, make this dynamic.
+ a << u256(0x20) << u256(0) << eth::Instruction::CALLDATASIZE;
+ a << u256(0) << eth::Instruction::DUP1;
+ // this is the address which has to be substituted by the linker.
+ //@todo implement as special "marker" AssemblyItem.
+ a << u256("0xcafecafecafecafecafecafecafecafecafecafe");
+ a << u256(eth::c_callGas + 10) << eth::Instruction::GAS << eth::Instruction::SUB;
+ a << eth::Instruction::CALLCODE;
+ //@todo adjust for larger return values, make this dynamic.
+ a << u256(0x20) << u256(0) << eth::Instruction::RETURN;
+ return a;
+}