mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Fixed problem with alloc.
This commit is contained in:
parent
e65c3ff17d
commit
3174a5e0c6
@ -176,6 +176,11 @@ AssemblyItem const& Assembly::append(AssemblyItem const& _i)
|
|||||||
return back();
|
return back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Assembly::injectStart(AssemblyItem const& _i)
|
||||||
|
{
|
||||||
|
m_items.insert(m_items.begin(), _i);
|
||||||
|
}
|
||||||
|
|
||||||
inline bool matches(AssemblyItemsConstRef _a, AssemblyItemsConstRef _b)
|
inline bool matches(AssemblyItemsConstRef _a, AssemblyItemsConstRef _b)
|
||||||
{
|
{
|
||||||
if (_a.size() != _b.size())
|
if (_a.size() != _b.size())
|
||||||
|
@ -98,6 +98,8 @@ public:
|
|||||||
|
|
||||||
void popTo(int _deposit) { while (m_deposit > _deposit) append(Instruction::POP); }
|
void popTo(int _deposit) { while (m_deposit > _deposit) append(Instruction::POP); }
|
||||||
|
|
||||||
|
void injectStart(AssemblyItem const& _i);
|
||||||
|
|
||||||
std::string out() const { std::stringstream ret; streamOut(ret); return ret.str(); }
|
std::string out() const { std::stringstream ret; streamOut(ret); return ret.str(); }
|
||||||
int deposit() const { return m_deposit; }
|
int deposit() const { return m_deposit; }
|
||||||
bytes assemble() const;
|
bytes assemble() const;
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
* @date 2014
|
* @date 2014
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Parser.h"
|
|
||||||
#include "CodeFragment.h"
|
#include "CodeFragment.h"
|
||||||
|
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
@ -27,12 +26,30 @@
|
|||||||
#include <libethential/Log.h>
|
#include <libethential/Log.h>
|
||||||
#include <libevmface/Instruction.h>
|
#include <libevmface/Instruction.h>
|
||||||
#include "CompilerState.h"
|
#include "CompilerState.h"
|
||||||
|
#include "Parser.h"
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace eth;
|
using namespace eth;
|
||||||
namespace qi = boost::spirit::qi;
|
namespace qi = boost::spirit::qi;
|
||||||
namespace px = boost::phoenix;
|
namespace px = boost::phoenix;
|
||||||
namespace sp = boost::spirit;
|
namespace sp = boost::spirit;
|
||||||
|
|
||||||
|
void CodeFragment::finalise(CompilerState const& _cs)
|
||||||
|
{
|
||||||
|
if (_cs.usedAlloc && _cs.vars.size() && !m_finalised)
|
||||||
|
{
|
||||||
|
m_finalised = true;
|
||||||
|
m_asm.injectStart(Instruction::MSTORE8);
|
||||||
|
m_asm.injectStart((u256)((_cs.vars.size() + 2) * 32) - 1);
|
||||||
|
m_asm.injectStart((u256)1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes CodeFragment::code(CompilerState const& _cs)
|
||||||
|
{
|
||||||
|
finalise(_cs);
|
||||||
|
return m_asm.assemble();
|
||||||
|
}
|
||||||
|
|
||||||
CodeFragment::CodeFragment(sp::utree const& _t, CompilerState& _s, bool _allowASM)
|
CodeFragment::CodeFragment(sp::utree const& _t, CompilerState& _s, bool _allowASM)
|
||||||
{
|
{
|
||||||
/* cdebug << "CodeFragment. Locals:";
|
/* cdebug << "CodeFragment. Locals:";
|
||||||
@ -317,6 +334,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
|
|||||||
vector<CodeFragment> code;
|
vector<CodeFragment> code;
|
||||||
CompilerState ns = _s;
|
CompilerState ns = _s;
|
||||||
ns.vars.clear();
|
ns.vars.clear();
|
||||||
|
ns.usedAlloc = false;
|
||||||
int c = _t.tag() ? 1 : 0;
|
int c = _t.tag() ? 1 : 0;
|
||||||
for (auto const& i: _t)
|
for (auto const& i: _t)
|
||||||
if (c++)
|
if (c++)
|
||||||
@ -456,13 +474,30 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
|
|||||||
m_asm.appendJump(begin);
|
m_asm.appendJump(begin);
|
||||||
m_asm << end.tag();
|
m_asm << end.tag();
|
||||||
}
|
}
|
||||||
|
else if (us == "ALLOC")
|
||||||
|
{
|
||||||
|
requireSize(1);
|
||||||
|
requireDeposit(0, 1);
|
||||||
|
|
||||||
|
m_asm.append(Instruction::MEMSIZE);
|
||||||
|
m_asm.append(u256(0));
|
||||||
|
m_asm.append(u256(1));
|
||||||
|
m_asm.append(code[0].m_asm, 1);
|
||||||
|
m_asm.append(Instruction::MEMSIZE);
|
||||||
|
m_asm.append(Instruction::ADD);
|
||||||
|
m_asm.append(Instruction::SUB);
|
||||||
|
m_asm.append(Instruction::MSTORE8);
|
||||||
|
|
||||||
|
_s.usedAlloc = true;
|
||||||
|
}
|
||||||
else if (us == "LLL")
|
else if (us == "LLL")
|
||||||
{
|
{
|
||||||
requireMinSize(2);
|
requireMinSize(2);
|
||||||
requireMaxSize(3);
|
requireMaxSize(3);
|
||||||
requireDeposit(1, 1);
|
requireDeposit(1, 1);
|
||||||
|
|
||||||
bytes const& subcode = code[0].code();
|
code[0].optimise();
|
||||||
|
bytes subcode = code[0].code(ns);
|
||||||
|
|
||||||
m_asm.append((u256)subcode.size());
|
m_asm.append((u256)subcode.size());
|
||||||
m_asm.append(Instruction::DUP);
|
m_asm.append(Instruction::DUP);
|
||||||
|
@ -43,18 +43,21 @@ public:
|
|||||||
static CodeFragment compile(std::string const& _src, CompilerState& _s);
|
static CodeFragment compile(std::string const& _src, CompilerState& _s);
|
||||||
|
|
||||||
/// Consolidates data and compiles code.
|
/// Consolidates data and compiles code.
|
||||||
bytes code() const { return m_asm.assemble(); }
|
bytes code(CompilerState const& _cs);
|
||||||
|
|
||||||
/// Consolidates data and compiles code.
|
/// Consolidates data and compiles code.
|
||||||
std::string assembly() const { return m_asm.out(); }
|
std::string assembly(CompilerState const& _cs) { finalise(_cs); return m_asm.out(); }
|
||||||
|
|
||||||
/// Optimise the code. Best do this just before calling code() or assembly().
|
/// Optimise the code. Best do this just before calling code() or assembly().
|
||||||
void optimise() { m_asm.optimise(); }
|
void optimise() { m_asm.optimise(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void finalise(CompilerState const& _cs);
|
||||||
|
|
||||||
template <class T> void error() const { throw T(); }
|
template <class T> void error() const { throw T(); }
|
||||||
void constructOperation(sp::utree const& _t, CompilerState& _s);
|
void constructOperation(sp::utree const& _t, CompilerState& _s);
|
||||||
|
|
||||||
|
bool m_finalised = false;
|
||||||
Assembly m_asm;
|
Assembly m_asm;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ bytes eth::compileLLL(string const& _src, bool _opt, vector<string>* _errors)
|
|||||||
auto f = CodeFragment::compile(_src, cs);
|
auto f = CodeFragment::compile(_src, cs);
|
||||||
if (_opt)
|
if (_opt)
|
||||||
f.optimise();
|
f.optimise();
|
||||||
bytes ret = f.code();
|
bytes ret = f.code(cs);
|
||||||
for (auto i: cs.treesToKill)
|
for (auto i: cs.treesToKill)
|
||||||
killBigints(i);
|
killBigints(i);
|
||||||
return ret;
|
return ret;
|
||||||
@ -63,7 +63,7 @@ std::string eth::compileLLLToAsm(std::string const& _src, bool _opt, std::vector
|
|||||||
auto f = CodeFragment::compile(_src, cs);
|
auto f = CodeFragment::compile(_src, cs);
|
||||||
if (_opt)
|
if (_opt)
|
||||||
f.optimise();
|
f.optimise();
|
||||||
string ret = f.assembly();
|
string ret = f.assembly(cs);
|
||||||
for (auto i: cs.treesToKill)
|
for (auto i: cs.treesToKill)
|
||||||
killBigints(i);
|
killBigints(i);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -52,8 +52,7 @@ void CompilerState::populateStandard()
|
|||||||
"(def 'regname (name) { [0]:name (call (- (gas) 21) namereg 0 0 32 0 0) })"
|
"(def 'regname (name) { [0]:name (call (- (gas) 21) namereg 0 0 32 0 0) })"
|
||||||
"(def 'send (to value) (call (- (gas) 21) to value 0 0 0 0))"
|
"(def 'send (to value) (call (- (gas) 21) to value 0 0 0 0))"
|
||||||
"(def 'send (gaslimit to value) (call gaslimit to value 0 0 0 0))"
|
"(def 'send (gaslimit to value) (call gaslimit to value 0 0 0 0))"
|
||||||
"(def 'alloc (len) (asm msize 0 1 len msize add sub mstore8))"
|
"(def 'msg (gaslimit to value data datasize outsize) { (set x outsize) (set y (alloc @32)) (call gaslimit to value data datasize @0 @32) @0 })"
|
||||||
"(def 'msg (gaslimit to value data datasize outsize) { [32]:outsize [0]:(alloc @32) (call gaslimit to value data datasize @0 @32) @0 })"
|
|
||||||
"(def 'msg (gaslimit to value data datasize) { (call gaslimit to value data datasize 0 32) @0 })"
|
"(def 'msg (gaslimit to value data datasize) { (call gaslimit to value data datasize 0 32) @0 })"
|
||||||
"(def 'msg (gaslimit to value data) { [0]:data (msg gaslimit to value 0 32) })"
|
"(def 'msg (gaslimit to value data) { [0]:data (msg gaslimit to value 0 32) })"
|
||||||
"(def 'msg (to value data) { [0]:data (msg 0 to value 0 32) })"
|
"(def 'msg (to value data) { [0]:data (msg 0 to value 0 32) })"
|
||||||
|
@ -48,6 +48,7 @@ struct CompilerState
|
|||||||
std::map<std::string, CodeFragment> outers;
|
std::map<std::string, CodeFragment> outers;
|
||||||
std::map<std::pair<std::string, unsigned>, Macro> macros;
|
std::map<std::pair<std::string, unsigned>, Macro> macros;
|
||||||
std::vector<boost::spirit::utree> treesToKill;
|
std::vector<boost::spirit::utree> treesToKill;
|
||||||
|
bool usedAlloc = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user