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

View File

@ -96,3 +96,8 @@ YulString TypeInfo::typeOf(Expression const& _expression) const
}
}, _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.
YulString typeOf(Expression const& _expression) const;
/// \returns the type of variable
YulString typeOfVariable(YulString _name) const;
private:
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
// }