Adding ssa type check and test for that one

This commit is contained in:
Djordje Mijovic 2020-02-19 17:34:08 +01:00 committed by chriseth
parent 2efda4129b
commit c891597204
6 changed files with 127 additions and 10 deletions

View File

@ -27,6 +27,8 @@
#include <libsolutil/CommonData.h> #include <libsolutil/CommonData.h>
#include <libyul/optimiser/TypeInfo.h>
using namespace std; using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
@ -42,8 +44,14 @@ namespace
class IntroduceSSA: public ASTModifier class IntroduceSSA: public ASTModifier
{ {
public: public:
explicit IntroduceSSA(NameDispenser& _nameDispenser, set<YulString> const& _variablesToReplace): explicit IntroduceSSA(
m_nameDispenser(_nameDispenser), m_variablesToReplace(_variablesToReplace) NameDispenser& _nameDispenser,
set<YulString> const& _variablesToReplace,
TypeInfo& _typeInfo
):
m_nameDispenser(_nameDispenser),
m_variablesToReplace(_variablesToReplace),
m_typeInfo(_typeInfo)
{ } { }
void operator()(Block& _block) override; void operator()(Block& _block) override;
@ -51,6 +59,7 @@ public:
private: private:
NameDispenser& m_nameDispenser; NameDispenser& m_nameDispenser;
set<YulString> const& m_variablesToReplace; set<YulString> const& m_variablesToReplace;
TypeInfo const& m_typeInfo;
}; };
@ -83,10 +92,10 @@ void IntroduceSSA::operator()(Block& _block)
{ {
YulString oldName = var.name; YulString oldName = var.name;
YulString newName = m_nameDispenser.newName(oldName); YulString newName = m_nameDispenser.newName(oldName);
newVariables.emplace_back(TypedName{loc, newName, {}}); newVariables.emplace_back(TypedName{loc, newName, var.type});
statements.emplace_back(VariableDeclaration{ statements.emplace_back(VariableDeclaration{
loc, loc,
{TypedName{loc, oldName, {}}}, {TypedName{loc, oldName, var.type}},
make_unique<Expression>(Identifier{loc, newName}) make_unique<Expression>(Identifier{loc, newName})
}); });
} }
@ -110,7 +119,11 @@ void IntroduceSSA::operator()(Block& _block)
{ {
YulString oldName = var.name; YulString oldName = var.name;
YulString newName = m_nameDispenser.newName(oldName); YulString newName = m_nameDispenser.newName(oldName);
newVariables.emplace_back(TypedName{loc, newName, {}}); newVariables.emplace_back(TypedName{
loc,
newName,
m_typeInfo.typeOfVariable(oldName)
});
statements.emplace_back(Assignment{ statements.emplace_back(Assignment{
loc, loc,
{Identifier{loc, oldName}}, {Identifier{loc, oldName}},
@ -136,9 +149,12 @@ class IntroduceControlFlowSSA: public ASTModifier
public: public:
explicit IntroduceControlFlowSSA( explicit IntroduceControlFlowSSA(
NameDispenser& _nameDispenser, NameDispenser& _nameDispenser,
set<YulString> const& _variablesToReplace set<YulString> const& _variablesToReplace,
TypeInfo const& _typeInfo
): ):
m_nameDispenser(_nameDispenser), m_variablesToReplace(_variablesToReplace) m_nameDispenser(_nameDispenser),
m_variablesToReplace(_variablesToReplace),
m_typeInfo(_typeInfo)
{ } { }
void operator()(FunctionDefinition& _function) override; void operator()(FunctionDefinition& _function) override;
@ -153,6 +169,7 @@ private:
set<YulString> m_variablesInScope; set<YulString> m_variablesInScope;
/// Set of variables that do not have a specific value. /// Set of variables that do not have a specific value.
set<YulString> m_variablesToReassign; set<YulString> m_variablesToReassign;
TypeInfo const& m_typeInfo;
}; };
void IntroduceControlFlowSSA::operator()(FunctionDefinition& _function) void IntroduceControlFlowSSA::operator()(FunctionDefinition& _function)
@ -221,7 +238,7 @@ void IntroduceControlFlowSSA::operator()(Block& _block)
YulString newName = m_nameDispenser.newName(toReassign); YulString newName = m_nameDispenser.newName(toReassign);
toPrepend.emplace_back(VariableDeclaration{ toPrepend.emplace_back(VariableDeclaration{
locationOf(_s), locationOf(_s),
{TypedName{locationOf(_s), newName, {}}}, {TypedName{locationOf(_s), newName, m_typeInfo.typeOfVariable(toReassign)}},
make_unique<Expression>(Identifier{locationOf(_s), toReassign}) make_unique<Expression>(Identifier{locationOf(_s), toReassign})
}); });
assignedVariables.insert(toReassign); assignedVariables.insert(toReassign);
@ -375,10 +392,11 @@ void PropagateValues::operator()(Block& _block)
void SSATransform::run(OptimiserStepContext& _context, Block& _ast) void SSATransform::run(OptimiserStepContext& _context, Block& _ast)
{ {
TypeInfo typeInfo(_context.dialect, _ast);
Assignments assignments; Assignments assignments;
assignments(_ast); assignments(_ast);
IntroduceSSA{_context.dispenser, assignments.names()}(_ast); IntroduceSSA{_context.dispenser, assignments.names(), typeInfo}(_ast);
IntroduceControlFlowSSA{_context.dispenser, assignments.names()}(_ast); IntroduceControlFlowSSA{_context.dispenser, assignments.names(), typeInfo}(_ast);
PropagateValues{assignments.names()}(_ast); PropagateValues{assignments.names()}(_ast);
} }

View File

@ -96,3 +96,8 @@ YulString TypeInfo::typeOf(Expression const& _expression) const
} }
}, _expression); }, _expression);
} }
YulString TypeInfo::typeOfVariable(YulString _name) const
{
return m_variableTypes.at(_name);
}

View File

@ -44,6 +44,9 @@ public:
/// @returns the type of an expression that is assumed to return exactly one value. /// @returns the type of an expression that is assumed to return exactly one value.
YulString typeOf(Expression const& _expression) const; YulString typeOf(Expression const& _expression) const;
/// \returns the type of variable
YulString typeOfVariable(YulString _name) const;
private: private:
class TypeCollector; class TypeCollector;

View File

@ -0,0 +1,41 @@
{
let b:bool := true
let c:bool := false
c := b
b := false
let a:u256 := 1
a := add(a, 1)
if c {
a := add(a, 1)
}
a := add(a, 1)
mstore(a, 1)
}
// ====
// dialect: evmTyped
// step: ssaTransform
// ----
// {
// let b_1:bool := true
// let b:bool := b_1
// let c_2:bool := false
// let c:bool := c_2
// let c_3:bool := b_1
// c := c_3
// let b_4:bool := false
// b := b_4
// let a_5 := 1
// let a := a_5
// let a_6 := add(a_5, 1)
// a := a_6
// if c_3
// {
// let a_7 := add(a_6, 1)
// a := a_7
// }
// let a_9 := a
// let a_8 := add(a_9, 1)
// a := a_8
// mstore(a_8, 1)
// }

View File

@ -0,0 +1,25 @@
{
let b:bool := true
let c:bool := false
for {} b {} {
c := true
}
let d: bool := c
}
// ====
// dialect: evmTyped
// step: ssaTransform
// ----
// {
// let b:bool := true
// let c_1:bool := false
// let c:bool := c_1
// for { } b { }
// {
// let c_3:bool := c
// let c_2:bool := true
// c := c_2
// }
// let c_4:bool := c
// let d:bool := c_4
// }

View File

@ -0,0 +1,25 @@
{
let b:bool := true
let c:bool := false
switch b
case true { c := true}
case false { }
let d: bool := c
}
// ====
// dialect: evmTyped
// step: ssaTransform
// ----
// {
// let b:bool := true
// let c_1:bool := false
// let c:bool := c_1
// switch b
// case true {
// let c_2:bool := true
// c := c_2
// }
// case false { }
// let c_3:bool := c
// let d:bool := c_3
// }