mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
yul proto mutator: Add control flow to block statements.
This commit is contained in:
parent
6fd5ea01d1
commit
758d159d87
@ -46,6 +46,34 @@ static LPMPostProcessor<Block> addStoreToZero(
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
template <typename T>
|
||||
struct addControlFlow
|
||||
{
|
||||
addControlFlow()
|
||||
{
|
||||
function = [](T* _message, unsigned)
|
||||
{
|
||||
MutationInfo m{_message, "Added control flow."};
|
||||
YPM::addControlFlow(_message);
|
||||
};
|
||||
/// Unused variable registers callback.
|
||||
LPMPostProcessor<T> callback(function);
|
||||
}
|
||||
function<void(T*, unsigned)> function;
|
||||
};
|
||||
}
|
||||
|
||||
static addControlFlow<ForStmt> c1;
|
||||
static addControlFlow<BoundedForStmt> c2;
|
||||
static addControlFlow<IfStmt> c3;
|
||||
static addControlFlow<SwitchStmt> c4;
|
||||
static addControlFlow<FunctionDef> c5;
|
||||
static addControlFlow<CaseStmt> c6;
|
||||
static addControlFlow<Code> c7;
|
||||
|
||||
Literal* YPM::intLiteral(unsigned _value)
|
||||
{
|
||||
auto lit = new Literal();
|
||||
@ -145,3 +173,100 @@ unsigned YPM::EnumTypeConverter<T>::enumMin()
|
||||
else
|
||||
static_assert(AlwaysFalse<T>::value, "Yul proto mutator: non-exhaustive visitor.");
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void YPM::addControlFlow(T* _msg)
|
||||
{
|
||||
enum class ControlFlowStmt: unsigned
|
||||
{
|
||||
For = 0,
|
||||
BoundedFor,
|
||||
If,
|
||||
Switch,
|
||||
FunctionCall,
|
||||
Break,
|
||||
Continue,
|
||||
Leave,
|
||||
Termination
|
||||
};
|
||||
uniform_int_distribution<unsigned> d(
|
||||
static_cast<unsigned>(ControlFlowStmt::For),
|
||||
static_cast<unsigned>(ControlFlowStmt::Termination)
|
||||
);
|
||||
auto random = static_cast<ControlFlowStmt>(d(s_rand.m_random));
|
||||
Statement* s = basicBlock(_msg)->add_statements();
|
||||
switch (random)
|
||||
{
|
||||
case ControlFlowStmt::For:
|
||||
s->set_allocated_forstmt(new ForStmt());
|
||||
break;
|
||||
case ControlFlowStmt::BoundedFor:
|
||||
s->set_allocated_boundedforstmt(new BoundedForStmt());
|
||||
break;
|
||||
case ControlFlowStmt::If:
|
||||
s->set_allocated_ifstmt(new IfStmt());
|
||||
break;
|
||||
case ControlFlowStmt::Switch:
|
||||
s->set_allocated_switchstmt(new SwitchStmt());
|
||||
break;
|
||||
case ControlFlowStmt::FunctionCall:
|
||||
s->set_allocated_functioncall(new FunctionCall());
|
||||
break;
|
||||
case ControlFlowStmt::Break:
|
||||
s->set_allocated_breakstmt(new BreakStmt());
|
||||
break;
|
||||
case ControlFlowStmt::Continue:
|
||||
s->set_allocated_contstmt(new ContinueStmt());
|
||||
break;
|
||||
case ControlFlowStmt::Leave:
|
||||
s->set_allocated_leave(new LeaveStmt());
|
||||
break;
|
||||
case ControlFlowStmt::Termination:
|
||||
s->set_allocated_terminatestmt(new TerminatingStmt());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Block* YPM::randomBlock(ForStmt* _stmt)
|
||||
{
|
||||
enum class ForBlocks: unsigned
|
||||
{
|
||||
Init = 0,
|
||||
Post = 1,
|
||||
Body = 2
|
||||
};
|
||||
uniform_int_distribution<unsigned> d(
|
||||
static_cast<unsigned>(ForBlocks::Init),
|
||||
static_cast<unsigned>(ForBlocks::Body)
|
||||
);
|
||||
switch (static_cast<ForBlocks>(d(s_rand.m_random)))
|
||||
{
|
||||
case ForBlocks::Init:
|
||||
return _stmt->mutable_for_init();
|
||||
case ForBlocks::Post:
|
||||
return _stmt->mutable_for_post();
|
||||
case ForBlocks::Body:
|
||||
return _stmt->mutable_for_body();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Block* YPM::basicBlock(T* _msg)
|
||||
{
|
||||
if constexpr (std::is_same_v<T, ForStmt>)
|
||||
return randomBlock(_msg);
|
||||
else if constexpr (std::is_same_v<T, BoundedForStmt>)
|
||||
return _msg->mutable_for_body();
|
||||
else if constexpr (std::is_same_v<T, SwitchStmt>)
|
||||
return _msg->mutable_default_block();
|
||||
else if constexpr (std::is_same_v<T, FunctionDef>)
|
||||
return _msg->mutable_block();
|
||||
else if constexpr (std::is_same_v<T, IfStmt>)
|
||||
return _msg->mutable_if_body();
|
||||
else if constexpr (std::is_same_v<T, CaseStmt>)
|
||||
return _msg->mutable_case_block();
|
||||
else if constexpr (std::is_same_v<T, Code>)
|
||||
return _msg->mutable_block();
|
||||
else
|
||||
static_assert(AlwaysFalse<T>::value, "Yul proto mutator: non-exhaustive visitor.");
|
||||
}
|
||||
|
@ -94,5 +94,14 @@ struct YulProtoMutator
|
||||
static constexpr unsigned s_mediumIP = 29;
|
||||
/// Modulo for mutations that should occur often
|
||||
static constexpr unsigned s_highIP = 23;
|
||||
/// Add control-flow statement to basic block.
|
||||
template <typename T>
|
||||
static void addControlFlow(T* _msg);
|
||||
/// Obtain basic block for statement type.
|
||||
template <typename T>
|
||||
static Block* basicBlock(T* _msg);
|
||||
/// Obtain a basic block in a for stmt uniformly
|
||||
/// at random
|
||||
static Block* randomBlock(ForStmt* _msg);
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user