mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Swap literals to the end if optimizing.
This commit is contained in:
parent
6fcdfdc353
commit
66d95abfd9
15
Compiler.cpp
15
Compiler.cpp
@ -246,7 +246,7 @@ bool Compiler::visit(FunctionDefinition const& _function)
|
||||
|
||||
bool Compiler::visit(IfStatement const& _ifStatement)
|
||||
{
|
||||
ExpressionCompiler::compileExpression(m_context, _ifStatement.getCondition());
|
||||
compileExpression(_ifStatement.getCondition());
|
||||
eth::AssemblyItem trueTag = m_context.appendConditionalJump();
|
||||
if (_ifStatement.getFalseStatement())
|
||||
_ifStatement.getFalseStatement()->accept(*this);
|
||||
@ -265,7 +265,7 @@ bool Compiler::visit(WhileStatement const& _whileStatement)
|
||||
m_breakTags.push_back(loopEnd);
|
||||
|
||||
m_context << loopStart;
|
||||
ExpressionCompiler::compileExpression(m_context, _whileStatement.getCondition());
|
||||
compileExpression(_whileStatement.getCondition());
|
||||
m_context << eth::Instruction::ISZERO;
|
||||
m_context.appendConditionalJumpTo(loopEnd);
|
||||
|
||||
@ -298,7 +298,7 @@ bool Compiler::visit(Return const& _return)
|
||||
//@todo modifications are needed to make this work with functions returning multiple values
|
||||
if (Expression const* expression = _return.getExpression())
|
||||
{
|
||||
ExpressionCompiler::compileExpression(m_context, *expression);
|
||||
compileExpression(*expression);
|
||||
VariableDeclaration const& firstVariable = *_return.getFunctionReturnParameters().getParameters().front();
|
||||
ExpressionCompiler::appendTypeConversion(m_context, *expression->getType(), *firstVariable.getType());
|
||||
|
||||
@ -312,7 +312,7 @@ bool Compiler::visit(VariableDefinition const& _variableDefinition)
|
||||
{
|
||||
if (Expression const* expression = _variableDefinition.getExpression())
|
||||
{
|
||||
ExpressionCompiler::compileExpression(m_context, *expression);
|
||||
compileExpression(*expression);
|
||||
ExpressionCompiler::appendTypeConversion(m_context,
|
||||
*expression->getType(),
|
||||
*_variableDefinition.getDeclaration().getType());
|
||||
@ -324,10 +324,15 @@ bool Compiler::visit(VariableDefinition const& _variableDefinition)
|
||||
bool Compiler::visit(ExpressionStatement const& _expressionStatement)
|
||||
{
|
||||
Expression const& expression = _expressionStatement.getExpression();
|
||||
ExpressionCompiler::compileExpression(m_context, expression);
|
||||
compileExpression(expression);
|
||||
CompilerUtils(m_context).popStackElement(*expression.getType());
|
||||
return false;
|
||||
}
|
||||
|
||||
void Compiler::compileExpression(Expression const& _expression)
|
||||
{
|
||||
ExpressionCompiler::compileExpression(m_context, _expression, m_optimize);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -30,10 +30,10 @@ namespace solidity {
|
||||
class Compiler: private ASTConstVisitor
|
||||
{
|
||||
public:
|
||||
Compiler(): m_returnTag(m_context.newTag()) {}
|
||||
explicit Compiler(bool _optimize = false): m_optimize(_optimize), m_returnTag(m_context.newTag()) {}
|
||||
|
||||
void compileContract(ContractDefinition const& _contract, std::vector<MagicVariableDeclaration const*> const& _magicGlobals);
|
||||
bytes getAssembledBytecode(bool _optimize = false) { return m_context.getAssembledBytecode(_optimize); }
|
||||
bytes getAssembledBytecode() { return m_context.getAssembledBytecode(m_optimize); }
|
||||
void streamAssembly(std::ostream& _stream) const { m_context.streamAssembly(_stream); }
|
||||
|
||||
private:
|
||||
@ -57,7 +57,9 @@ private:
|
||||
virtual bool visit(VariableDefinition const& _variableDefinition) override;
|
||||
virtual bool visit(ExpressionStatement const& _expressionStatement) override;
|
||||
|
||||
void compileExpression(Expression const& _expression);
|
||||
|
||||
bool const m_optimize;
|
||||
CompilerContext m_context;
|
||||
std::vector<eth::AssemblyItem> m_breakTags; ///< tag to jump to for a "break" statement
|
||||
std::vector<eth::AssemblyItem> m_continueTags; ///< tag to jump to for a "continue" statement
|
||||
|
@ -101,10 +101,10 @@ void CompilerStack::compile(bool _optimize)
|
||||
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
|
||||
{
|
||||
m_globalContext->setCurrentContract(*contract);
|
||||
shared_ptr<Compiler> compiler = make_shared<Compiler>();
|
||||
shared_ptr<Compiler> compiler = make_shared<Compiler>(_optimize);
|
||||
compiler->compileContract(*contract, m_globalContext->getMagicVariables());
|
||||
Contract& compiledContract = m_contracts[contract->getName()];
|
||||
compiledContract.bytecode = compiler->getAssembledBytecode(_optimize);
|
||||
compiledContract.bytecode = compiler->getAssembledBytecode();
|
||||
compiledContract.compiler = move(compiler);
|
||||
}
|
||||
}
|
||||
|
@ -33,9 +33,9 @@ using namespace std;
|
||||
namespace dev {
|
||||
namespace solidity {
|
||||
|
||||
void ExpressionCompiler::compileExpression(CompilerContext& _context, Expression const& _expression)
|
||||
void ExpressionCompiler::compileExpression(CompilerContext& _context, Expression const& _expression, bool _optimize)
|
||||
{
|
||||
ExpressionCompiler compiler(_context);
|
||||
ExpressionCompiler compiler(_context, _optimize);
|
||||
_expression.accept(compiler);
|
||||
}
|
||||
|
||||
@ -145,10 +145,24 @@ bool ExpressionCompiler::visit(BinaryOperation const& _binaryOperation)
|
||||
if (Token::isCompareOp(op) || op == Token::DIV || op == Token::MOD)
|
||||
cleanupNeeded = true;
|
||||
|
||||
rightExpression.accept(*this);
|
||||
appendTypeConversion(*rightExpression.getType(), commonType, cleanupNeeded);
|
||||
leftExpression.accept(*this);
|
||||
appendTypeConversion(*leftExpression.getType(), commonType, cleanupNeeded);
|
||||
// for commutative operators, push the literal as late as possible to allow improved optimization
|
||||
//@todo this has to be extended for literal expressions
|
||||
bool swap = (m_optimize && Token::isCommutativeOp(op) && dynamic_cast<Literal const*>(&rightExpression)
|
||||
&& !dynamic_cast<Literal const*>(&leftExpression));
|
||||
if (swap)
|
||||
{
|
||||
leftExpression.accept(*this);
|
||||
appendTypeConversion(*leftExpression.getType(), commonType, cleanupNeeded);
|
||||
rightExpression.accept(*this);
|
||||
appendTypeConversion(*rightExpression.getType(), commonType, cleanupNeeded);
|
||||
}
|
||||
else
|
||||
{
|
||||
rightExpression.accept(*this);
|
||||
appendTypeConversion(*rightExpression.getType(), commonType, cleanupNeeded);
|
||||
leftExpression.accept(*this);
|
||||
appendTypeConversion(*leftExpression.getType(), commonType, cleanupNeeded);
|
||||
}
|
||||
if (Token::isCompareOp(op))
|
||||
appendCompareOperatorCode(op, commonType);
|
||||
else
|
||||
|
@ -45,14 +45,14 @@ class ExpressionCompiler: private ASTConstVisitor
|
||||
{
|
||||
public:
|
||||
/// Compile the given @a _expression into the @a _context.
|
||||
static void compileExpression(CompilerContext& _context, Expression const& _expression);
|
||||
static void compileExpression(CompilerContext& _context, Expression const& _expression, bool _optimize = false);
|
||||
|
||||
/// Appends code to remove dirty higher order bits in case of an implicit promotion to a wider type.
|
||||
static void appendTypeConversion(CompilerContext& _context, Type const& _typeOnStack, Type const& _targetType);
|
||||
|
||||
private:
|
||||
ExpressionCompiler(CompilerContext& _compilerContext):
|
||||
m_context(_compilerContext), m_currentLValue(m_context) {}
|
||||
explicit ExpressionCompiler(CompilerContext& _compilerContext, bool _optimize = false):
|
||||
m_optimize(_optimize), m_context(_compilerContext), m_currentLValue(m_context) {}
|
||||
|
||||
virtual bool visit(Assignment const& _assignment) override;
|
||||
virtual void endVisit(UnaryOperation const& _unaryOperation) override;
|
||||
@ -132,6 +132,7 @@ private:
|
||||
unsigned m_stackSize;
|
||||
};
|
||||
|
||||
bool m_optimize;
|
||||
CompilerContext& m_context;
|
||||
LValue m_currentLValue;
|
||||
};
|
||||
|
2
Token.h
2
Token.h
@ -317,6 +317,8 @@ public:
|
||||
static bool isElementaryTypeName(Value tok) { return INT <= tok && tok < TYPES_END; }
|
||||
static bool isAssignmentOp(Value tok) { return ASSIGN <= tok && tok <= ASSIGN_MOD; }
|
||||
static bool isBinaryOp(Value op) { return COMMA <= op && op <= MOD; }
|
||||
static bool isCommutativeOp(Value op) { return op == BIT_OR || op == BIT_XOR || op == BIT_AND ||
|
||||
op == ADD || op == MUL || op == EQ || op == NE; }
|
||||
static bool isArithmeticOp(Value op) { return ADD <= op && op <= MOD; }
|
||||
static bool isCompareOp(Value op) { return EQ <= op && op <= IN; }
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user