Split Instruction and FunctionalInstruction in Julia

This commit is contained in:
Alex Beregszaszi 2017-12-05 13:44:20 +00:00
parent a08d853bbb
commit 745eefa36f
7 changed files with 27 additions and 19 deletions

View File

@ -125,11 +125,11 @@ void CodeTransform::operator()(FunctionCall const& _call)
void CodeTransform::operator()(FunctionalInstruction const& _instruction) void CodeTransform::operator()(FunctionalInstruction const& _instruction)
{ {
if (m_evm15 && ( if (m_evm15 && (
_instruction.instruction.instruction == solidity::Instruction::JUMP || _instruction.instruction == solidity::Instruction::JUMP ||
_instruction.instruction.instruction == solidity::Instruction::JUMPI _instruction.instruction == solidity::Instruction::JUMPI
)) ))
{ {
bool const isJumpI = _instruction.instruction.instruction == solidity::Instruction::JUMPI; bool const isJumpI = _instruction.instruction == solidity::Instruction::JUMPI;
if (isJumpI) if (isJumpI)
{ {
solAssert(_instruction.arguments.size() == 2, ""); solAssert(_instruction.arguments.size() == 2, "");
@ -150,7 +150,8 @@ void CodeTransform::operator()(FunctionalInstruction const& _instruction)
{ {
for (auto const& arg: _instruction.arguments | boost::adaptors::reversed) for (auto const& arg: _instruction.arguments | boost::adaptors::reversed)
visitExpression(arg); visitExpression(arg);
(*this)(_instruction.instruction); m_assembly.setSourceLocation(_instruction.location);
m_assembly.appendInstruction(_instruction.instruction);
} }
checkStackHeight(&_instruction); checkStackHeight(&_instruction);
} }

View File

@ -31,9 +31,10 @@ using namespace dev;
using namespace dev::julia; using namespace dev::julia;
Statement ASTCopier::operator()(Instruction const& _instruction) Statement ASTCopier::operator()(Instruction const&)
{ {
return _instruction; solAssert(false, "Invalid operation.");
return {};
} }
Statement ASTCopier::operator()(VariableDeclaration const& _varDecl) Statement ASTCopier::operator()(VariableDeclaration const& _varDecl)

View File

@ -40,16 +40,13 @@ public:
void operator()(assembly::Label const&) { } void operator()(assembly::Label const&) { }
void operator()(assembly::Instruction const& _instruction) void operator()(assembly::Instruction const& _instruction)
{ {
if (eth::SemanticInformation::invalidInViewFunctions(_instruction.instruction)) checkInstruction(_instruction.location, _instruction.instruction);
m_reportMutability(StateMutability::NonPayable, _instruction.location);
else if (eth::SemanticInformation::invalidInPureFunctions(_instruction.instruction))
m_reportMutability(StateMutability::View, _instruction.location);
} }
void operator()(assembly::Literal const&) {} void operator()(assembly::Literal const&) {}
void operator()(assembly::Identifier const&) {} void operator()(assembly::Identifier const&) {}
void operator()(assembly::FunctionalInstruction const& _instr) void operator()(assembly::FunctionalInstruction const& _instr)
{ {
(*this)(_instr.instruction); checkInstruction(_instr.location, _instr.instruction);
for (auto const& arg: _instr.arguments) for (auto const& arg: _instr.arguments)
boost::apply_visitor(*this, arg); boost::apply_visitor(*this, arg);
} }
@ -102,6 +99,13 @@ public:
private: private:
std::function<void(StateMutability, SourceLocation const&)> m_reportMutability; std::function<void(StateMutability, SourceLocation const&)> m_reportMutability;
void checkInstruction(SourceLocation _location, solidity::Instruction _instruction)
{
if (eth::SemanticInformation::invalidInViewFunctions(_instruction))
m_reportMutability(StateMutability::NonPayable, _location);
else if (eth::SemanticInformation::invalidInPureFunctions(_instruction))
m_reportMutability(StateMutability::View, _location);
}
}; };
} }

View File

@ -146,10 +146,11 @@ bool AsmAnalyzer::operator()(FunctionalInstruction const& _instr)
if (!expectExpression(arg)) if (!expectExpression(arg))
success = false; success = false;
// Parser already checks that the number of arguments is correct. // Parser already checks that the number of arguments is correct.
solAssert(instructionInfo(_instr.instruction.instruction).args == int(_instr.arguments.size()), ""); auto const& info = instructionInfo(_instr.instruction);
if (!(*this)(_instr.instruction)) solAssert(info.args == int(_instr.arguments.size()), "");
success = false; m_stackHeight += info.ret - info.args;
m_info.stackHeightInfo[&_instr] = m_stackHeight; m_info.stackHeightInfo[&_instr] = m_stackHeight;
warnOnInstructions(_instr.instruction, _instr.location);
return success; return success;
} }

View File

@ -60,7 +60,7 @@ struct StackAssignment { SourceLocation location; Identifier variableName; };
/// the same amount of items as the number of variables. /// the same amount of items as the number of variables.
struct Assignment { SourceLocation location; std::vector<Identifier> variableNames; std::shared_ptr<Statement> value; }; struct Assignment { SourceLocation location; std::vector<Identifier> variableNames; std::shared_ptr<Statement> value; };
/// Functional instruction, e.g. "mul(mload(20:u256), add(2:u256, x))" /// Functional instruction, e.g. "mul(mload(20:u256), add(2:u256, x))"
struct FunctionalInstruction { SourceLocation location; Instruction instruction; std::vector<Statement> arguments; }; struct FunctionalInstruction { SourceLocation location; solidity::Instruction instruction; std::vector<Statement> arguments; };
struct FunctionCall { SourceLocation location; Identifier functionName; std::vector<Statement> arguments; }; struct FunctionCall { SourceLocation location; Identifier functionName; std::vector<Statement> arguments; };
/// Block-scope variable declaration ("let x:u256 := mload(20:u256)"), non-hoisted /// Block-scope variable declaration ("let x:u256 := mload(20:u256)"), non-hoisted
struct VariableDeclaration { SourceLocation location; TypedNameList variables; std::shared_ptr<Statement> value; }; struct VariableDeclaration { SourceLocation location; TypedNameList variables; std::shared_ptr<Statement> value; };

View File

@ -448,10 +448,11 @@ assembly::Statement Parser::parseCall(assembly::Statement&& _instruction)
if (_instruction.type() == typeid(Instruction)) if (_instruction.type() == typeid(Instruction))
{ {
solAssert(!m_julia, "Instructions are invalid in JULIA"); solAssert(!m_julia, "Instructions are invalid in JULIA");
Instruction const& instruction = std::move(boost::get<Instruction>(_instruction));
FunctionalInstruction ret; FunctionalInstruction ret;
ret.instruction = std::move(boost::get<Instruction>(_instruction)); ret.instruction = instruction.instruction;
ret.location = ret.instruction.location; ret.location = std::move(instruction.location);
solidity::Instruction instr = ret.instruction.instruction; solidity::Instruction instr = ret.instruction;
InstructionInfo instrInfo = instructionInfo(instr); InstructionInfo instrInfo = instructionInfo(instr);
if (solidity::isDupInstruction(instr)) if (solidity::isDupInstruction(instr))
fatalParserError("DUPi instructions not allowed for functional notation"); fatalParserError("DUPi instructions not allowed for functional notation");

View File

@ -94,7 +94,7 @@ string AsmPrinter::operator()(assembly::FunctionalInstruction const& _functional
{ {
solAssert(!m_julia, ""); solAssert(!m_julia, "");
return return
(*this)(_functionalInstruction.instruction) + boost::to_lower_copy(instructionInfo(_functionalInstruction.instruction).name) +
"(" + "(" +
boost::algorithm::join( boost::algorithm::join(
_functionalInstruction.arguments | boost::adaptors::transformed(boost::apply_visitor(*this)), _functionalInstruction.arguments | boost::adaptors::transformed(boost::apply_visitor(*this)),