mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Adding ssa type check and test for that one
This commit is contained in:
parent
2efda4129b
commit
c891597204
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,3 +96,8 @@ YulString TypeInfo::typeOf(Expression const& _expression) const
|
|||||||
}
|
}
|
||||||
}, _expression);
|
}, _expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
YulString TypeInfo::typeOfVariable(YulString _name) const
|
||||||
|
{
|
||||||
|
return m_variableTypes.at(_name);
|
||||||
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
41
test/libyul/yulOptimizerTests/ssaTransform/typed.yul
Normal file
41
test/libyul/yulOptimizerTests/ssaTransform/typed.yul
Normal 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)
|
||||||
|
// }
|
25
test/libyul/yulOptimizerTests/ssaTransform/typed_for.yul
Normal file
25
test/libyul/yulOptimizerTests/ssaTransform/typed_for.yul
Normal 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
|
||||||
|
// }
|
25
test/libyul/yulOptimizerTests/ssaTransform/typed_switch.yul
Normal file
25
test/libyul/yulOptimizerTests/ssaTransform/typed_switch.yul
Normal 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
|
||||||
|
// }
|
Loading…
Reference in New Issue
Block a user