39 #include <llvm/ADT/Twine.h>
50 bool Init,
bool Cleanup) {
51 OwningPtr<Transition> T(
new NullTransition(From, To, Init, Cleanup));
52 Register(T, From, To, Transitions);
60 Automaton.argument_size());
62 OwningPtr<Transition> T(
new NowTransition(From, To, Ev, Refs, Init, Cleanup));
63 Register(T, From, To, Transitions);
70 OwningPtr<Transition> T(
71 new FnTransition(From, To, Ev, Init, Cleanup, OutOfScope));
73 Register(T, From, To, Transitions);
80 OwningPtr<Transition> T(
83 Register(T, From, To, Transitions);
86 void Transition::CreateSubAutomaton(
State& From,
State& To,
91 Register(T, From, To, Transitions);
97 OwningPtr<Transition> New;
102 assert(!Init || !OutOfScope);
111 auto O = cast<NowTransition>(Other);
112 New.reset(
new NowTransition(From, To, O->Ev, O->Refs, Init, Cleanup));
117 New.reset(
new FnTransition(From, To, cast<FnTransition>(Other)->Ev,
118 Init, Cleanup, OutOfScope));
123 From, To, cast<FieldAssignTransition>(Other)->Assign,
124 Init, Cleanup, OutOfScope));
130 cast<SubAutomatonTransition>(Other)->ID));
135 Register(New, From, To, Transitions);
138 void Transition::Register(OwningPtr<Transition>& T,
State& From,
State& To,
141 Transitions.push_back(T.get());
142 debugs(
"tesla.automata.transitions") <<
"registered " << T->String() <<
"\n";
145 assert(To.
ID() != 0);
156 auto& Out =
debugs(
"tesla.automata.transitions.equivalence");
157 Out <<
"grouping transitions:\n";
159 for (
auto *T : Ungrouped) {
160 Out <<
" " << T->String() <<
"\n";
162 bool FoundEquivalent =
false;
163 for (
auto& Set : EquivalenceClasses) {
164 auto *Head = *Set.begin();
165 if (T->EquivalentTo(*Head)) {
166 assert(Head->EquivalentTo(*T));
167 FoundEquivalent =
true;
173 if (!FoundEquivalent) {
174 SmallPtrSet<const Transition*, 4> New;
176 EquivalenceClasses.push_back(New);
180 Out <<
"equivalence classes:\n";
181 for (
auto& EquivClass : EquivalenceClasses) {
184 Out << (Head ?
" " :
" == ") << T->String() <<
"\n";
191 void Transition::ReferencesThusFar(OwningArrayPtr<const Argument*>& Args,
195 SmallVector<const Argument*, 4> MyRefs;
196 for (
auto Arg : this->Arguments())
197 if (Arg && Arg->type() == Argument::Variable) {
198 size_t i = Arg->index();
200 if (MyRefs.size() <= i)
201 MyRefs.resize(i + 1);
206 auto& FromRefs = From.References();
207 const size_t Size = FromRefs.size();
209 auto Arguments =
new const Argument*[Size];
210 for (
size_t i = 0; i < Size; i++) {
211 if ((MyRefs.size() > i) && MyRefs[i])
212 Arguments[i] = MyRefs[i];
214 else if ((FromRefs.size() > i) && FromRefs[i])
215 Arguments[i] = FromRefs[i];
221 Args.reset(Arguments);
226 SmallVector<const Argument*,4> Transition::NewArguments()
const {
227 auto OldArgs(From.References());
228 auto TransArgs(Arguments());
230 SmallVector<const Argument*,4> NewArgs(TransArgs.size());
231 for (
size_t i = 0; i < NewArgs.size(); i++)
232 if ((OldArgs.size() <= i) || (OldArgs[i] == NULL))
233 NewArgs[i] = TransArgs[i];
239 int Transition::NewArgMask()
const {
240 auto NewArgs(NewArguments());
243 for (
int i = 0; i < NewArgs.size(); i++)
244 if ((NewArgs[i] != NULL) && (NewArgs[i]->type() == Argument::Variable))
251 string Transition::String()
const {
253 for (
auto A : NewArguments())
254 if ((A != NULL) && (A->type() == Argument::Variable))
258 string(RequiresInit() ?
"<<init>>" :
"")
259 + (RequiresCleanup() ?
"<<cleanup>>" :
"")
265 + (NewArgs.empty() ?
"" :
":" + NewArgs)
266 + (Special.empty() ?
"" :
" " + Special)
275 const Argument*
const *Args = Ev.argument().data();
276 size_t Len = Ev.argument_size();
281 string FnTransition::ShortLabel()
const {
282 std::stringstream ss;
283 ss << Ev.function().name() <<
"(";
285 for (
int i = 0; i < Ev.argument_size(); i++)
288 << ((i < Ev.argument_size() - 1) ?
"," :
"");
292 if (Ev.has_expectedreturnvalue()) {
293 assert(Ev.direction() == FunctionEvent::Exit);
294 ss <<
" == " <<
ShortName(&Ev.expectedreturnvalue());
296 ss <<
": " << FunctionEvent::Direction_Name(Ev.direction());
301 string FnTransition::DotLabel()
const {
302 std::stringstream ss;
303 ss << Ev.function().name() <<
"(";
305 for (
int i = 0; i < Ev.argument_size(); i++)
308 << ((i < Ev.argument_size() - 1) ?
"," :
"");
312 if (Ev.has_expectedreturnvalue()) {
313 assert(Ev.direction() == FunctionEvent::Exit);
314 ss <<
" == " <<
DotName(&Ev.expectedreturnvalue());
317 << FunctionEvent::Direction_Name(Ev.direction())
325 FieldAssignTransition::FieldAssignTransition(
const State& From,
const State& To,
327 bool Init,
bool Cleanup,
329 :
Transition(From, To, Init, Cleanup, OutOfScope), Assign(A),
330 ReferencedVariables(new const
Argument*[2]),
331 Refs(ReferencedVariables.get(), 2)
333 ReferencedVariables[0] = &Assign.field().base();
334 ReferencedVariables[1] = &Assign.value();
351 +
"struct " + Assign.
field().
type() +
":\\l"
365 case FieldAssignment::PlusEqual:
return "+=";