1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2014 Ericsson Telecom AB
3 // All rights reserved. This program and the accompanying materials
4 // are made available under the terms of the Eclipse Public License v1.0
5 // which accompanies this distribution, and is available at
6 // http://www.eclipse.org/legal/epl-v10.html
7 ///////////////////////////////////////////////////////////////////////////////
12 // =================================
14 // =================================
18 for(size_t i
=0; i
<branches
.size(); i
++)
23 ILT_branch
* ILT::get_as_branch()
25 FATAL_ERROR("ILT::get_as_branch()");
29 void ILT::add_branch(ILT_branch
*p_branch
)
31 if(!p_branch
) FATAL_ERROR("ILT::add_branch()");
32 branches
.add(p_branch
);
33 ILT_root
*my_root
= get_my_root();
34 p_branch
->set_my_root(my_root
);
35 p_branch
->set_branch_i(my_root
->get_new_branch_num());
39 // =================================
41 // =================================
43 ILT_root::ILT_root(Statement
*p_il
)
44 : il(p_il
), tmpnum(0), c_l(0), c_b(0)
46 if(!p_il
|| p_il
->get_statementtype()!=Statement::S_INTERLEAVE
)
47 FATAL_ERROR("ILT_root::ILT_root()");
48 mytmpid
=p_il
->get_my_sb()->get_scope_mod_gen()->get_temporary_id();
50 out_statevars
=memptystr();
52 out_branches
=memptystr();
57 for(size_t i
=0; i
<state_var_vals
.size(); i
++)
58 delete state_var_vals
[i
];
59 state_var_vals
.clear();
66 ILT_root
*ILT_root::clone() const
68 FATAL_ERROR("ILT_root::clone()");
71 ILT_root
*ILT_root::get_my_root()
76 bool ILT_root::is_toplevel()
81 char*& ILT_root::get_out_def()
86 char*& ILT_root::get_out_code()
91 char*& ILT_root::get_out_branches()
96 const string
& ILT_root::get_my_tmpid()
101 size_t ILT_root::get_new_tmpnum()
106 size_t ILT_root::get_new_state_var(bool toplevel
)
108 state_var_vals
.add(new size_t(1));
109 size_t newvar
=state_var_vals
.size()-1;
110 out_statevars
=mputprintf(out_statevars
, "%s_state[%lu]=%s;\n",
111 mytmpid
.c_str(), (unsigned long) newvar
, toplevel
?"2":"0");
115 size_t ILT_root::get_new_state_var_val(size_t p_state_var
)
117 if(p_state_var
>=state_var_vals
.size())
118 FATAL_ERROR("ILT_root::get_new_state_var_val()");
119 return ++*state_var_vals
[p_state_var
];
122 size_t ILT_root::get_new_label_num()
127 char* ILT_root::generate_code(char *str
)
129 // everything starts here: the top-level interleave statement
130 il
->ilt_generate_code(this);
131 // generating code for the branches
132 for(size_t i
=0; i
<branches
.size(); i
++)
133 branches
[i
]->ilt_generate_code(this);
134 str
=mputstr(str
, "{\n"); // (1)
135 // the state vars: definition
136 str
=mputprintf(str
, "size_t %s_state[%lu];\n",
137 mytmpid
.c_str(), (unsigned long) state_var_vals
.size());
138 // the state vars: initialization
139 str
=mputstr(str
, out_statevars
);
140 // the alt status flags: definition
141 str
=mputprintf(str
, "alt_status %s_alt_flag[%lu];\n",
142 mytmpid
.c_str(), (unsigned long) (c_b
+1));
144 str
=mputstr(str
, out_def
);
145 // the core of the interleave
146 str
=mputprintf(str
, "%s:\n"
147 "for(size_t tmp_i=0; tmp_i<%lu; tmp_i++)"
148 " %s_alt_flag[tmp_i]=ALT_UNCHECKED;\n"
149 "%s_alt_flag[%lu]=ALT_MAYBE;\n"
150 "TTCN_Snapshot::take_new(FALSE);\n"
151 "for( ; ; ) {\n" // (2)
152 "if(", mytmpid
.c_str(),
153 (unsigned long) c_b
, mytmpid
.c_str(),
154 mytmpid
.c_str(), (unsigned long) c_b
);
155 // checking for final condition
156 for(size_t i
=0; i
<branches
.size(); i
++) {
157 ILT_branch
*b
=branches
[i
];
158 str
=mputprintf(str
, "%s%s_state[%lu]==1",
159 i
?" && ":"", mytmpid
.c_str(), (unsigned long) b
->get_my_state_var());
161 str
=mputstr(str
, ") break;\n");
163 str
=mputstr(str
, out_code
);
165 str
=mputprintf(str
, "if(%s_alt_flag[%lu]==ALT_MAYBE) {\n"
166 "%s_alt_flag[%lu]=TTCN_Default::try_altsteps();\n"
167 "if(%s_alt_flag[%lu]==ALT_YES || %s_alt_flag[%lu]==ALT_BREAK)"
169 "else if(%s_alt_flag[%lu]==ALT_REPEAT) goto %s;\n"
171 mytmpid
.c_str(), (unsigned long) c_b
,
172 mytmpid
.c_str(), (unsigned long) c_b
,
173 mytmpid
.c_str(), (unsigned long) c_b
,
174 mytmpid
.c_str(), (unsigned long) c_b
,
175 mytmpid
.c_str(), (unsigned long) c_b
,
177 str
=il
->update_location_object(str
);
179 str
=mputprintf(str
, "for(size_t tmp_i=0; tmp_i<%lu; tmp_i++)"
180 " if(%s_alt_flag[tmp_i]!=ALT_NO) goto %s_newsnapshot;\n",
181 (unsigned long) (c_b
+1), mytmpid
.c_str(), mytmpid
.c_str());
182 str
= mputstr(str
, "TTCN_error(\"None of the branches can be chosen in the "
183 "interleave statement in file ");
184 str
= Code::translate_string(str
, il
->get_filename());
185 int first_line
= il
->get_first_line(), last_line
= il
->get_last_line();
186 if (first_line
< last_line
) str
= mputprintf(str
,
187 " between lines %d and %d", first_line
, last_line
);
188 else str
= mputprintf(str
, ", line %d", first_line
);
189 str
= mputprintf(str
, ".\");\n"
191 "TTCN_Snapshot::take_new(TRUE);\n"
192 "continue;\n", mytmpid
.c_str());
193 // the code of branches
194 str
=mputstr(str
, out_branches
);
195 str
=mputstr(str
, "}\n" // (2)
200 // =================================
202 // =================================
204 ILT_branch::ILT_branch(branchtype_t p_bt
, AltGuard
*p_ag
,
205 string p_state_cond
, size_t p_state_var
,
206 size_t p_state_var_val
, size_t p_goto_label_num
)
207 : branchtype(p_bt
), root(0), branch_i((size_t)-1),
208 state_cond(p_state_cond
), state_var(p_state_var
),
209 state_var_val(p_state_var_val
), goto_label_num(p_goto_label_num
)
214 if(!p_ag
) FATAL_ERROR("ILT_branch::ILT_branch()");
216 // the checker should check this but one never knows :)
217 if(ag
->get_type()!=AltGuard::AG_OP
)
218 FATAL_ERROR("ILT_branch::ILT_branch()");
221 FATAL_ERROR("ILT_branch::ILT_branch()");
225 ILT_branch::ILT_branch(branchtype_t p_bt
, Statement
*p_stmt
,
226 string p_state_cond
, size_t p_state_var
,
227 size_t p_state_var_val
, size_t p_goto_label_num
)
228 : branchtype(p_bt
), root(0), branch_i((size_t)-1),
229 state_cond(p_state_cond
), state_var(p_state_var
),
230 state_var_val(p_state_var_val
), goto_label_num(p_goto_label_num
)
234 if(!p_stmt
) FATAL_ERROR("ILT_branch::ILT_branch()");
238 FATAL_ERROR("ILT_branch::ILT_branch()");
242 ILT_branch::~ILT_branch()
247 ILT_branch
*ILT_branch::clone() const
249 FATAL_ERROR("ILT_branch::clone()");
252 void ILT_branch::set_my_root(ILT_root
*p_root
)
254 if(!p_root
) FATAL_ERROR("ILT_branch::set_my_root()");
258 ILT_root
* ILT_branch::get_my_root()
260 if (!root
) FATAL_ERROR("ILT_branch::get_my_root()");
264 ILT_branch
*ILT_branch::get_as_branch()
269 bool ILT_branch::is_toplevel()
274 char*& ILT_branch::get_out_def()
276 return root
->get_out_def();
279 char*& ILT_branch::get_out_code()
281 return root
->get_out_code();
284 char*& ILT_branch::get_out_branches()
286 return root
->get_out_branches();
289 const string
& ILT_branch::get_my_tmpid()
291 return root
->get_my_tmpid();
294 size_t ILT_branch::get_new_tmpnum()
296 return root
->get_new_tmpnum();
299 size_t ILT_branch::get_new_state_var(bool toplevel
)
301 return root
->get_new_state_var(toplevel
);
304 size_t ILT_branch::get_new_state_var_val(size_t p_state_var
)
306 return root
->get_new_state_var_val(p_state_var
);
309 size_t ILT_branch::get_new_label_num()
311 return root
->get_new_label_num();
314 void ILT_branch::ilt_generate_code(ILT
*ilt
)
316 const string
& mytmpid
=get_my_tmpid();
317 char*& out_code
=get_out_code();
319 =branchtype
==BT_RECV
?stmt
:ag
->get_guard_stmt();
320 out_code
=recv_stmt
->update_location_object(out_code
);
321 // ALT_UNCHECKED -> ALT_MAYBE or ALT_NO (state vars & guard expr)
323 out_code
=mputprintf(out_code
,
324 "if(%s_alt_flag[%lu]==ALT_UNCHECKED) {\n" // (1)
326 mytmpid
.c_str(), (unsigned long) branch_i
);
327 if(!state_cond
.empty())
328 out_code
=mputprintf(out_code
, "%s && ", state_cond
.c_str());
329 out_code
=mputprintf(out_code
, "%s_state[%lu]==%lu) {\n", // (2)
330 mytmpid
.c_str(), (unsigned long) state_var
,
331 (unsigned long) state_var_val
);
332 // only alt branch can have guard expression
333 Value
*guard_expr
=branchtype
==BT_ALT
?ag
->get_guard_expr():0;
335 out_code
=guard_expr
->update_location_object(out_code
);
336 expression_struct expr
;
337 Code::init_expr(&expr
);
338 guard_expr
->generate_code_expr(&expr
);
339 out_code
=mputstr(out_code
, expr
.preamble
);
340 out_code
=mputprintf(out_code
,
341 "%s_alt_flag[%lu]=(%s)?ALT_MAYBE:ALT_NO;\n",
342 mytmpid
.c_str(), (unsigned long) branch_i
,
344 out_code
=mputstr(out_code
, expr
.postamble
);
345 Code::free_expr(&expr
);
347 else out_code
=mputprintf(out_code
,
348 "%s_alt_flag[%lu]=ALT_MAYBE;\n",
349 mytmpid
.c_str(), (unsigned long) branch_i
);
350 out_code
=mputprintf(out_code
,
352 "else %s_alt_flag[%lu]=ALT_NO;\n"
354 mytmpid
.c_str(), (unsigned long) branch_i
);
356 // ALT_MAYBE -> ALT_YES or ALT_REPEAT or ALT_NO (guard stmt)
358 out_code
=mputprintf(out_code
,
359 "if(%s_alt_flag[%lu]==ALT_MAYBE) {\n", // (1)
360 mytmpid
.c_str(), (unsigned long) branch_i
);
361 expression_struct expr
;
362 Code::init_expr(&expr
);
363 recv_stmt
->generate_code_expr(&expr
);
364 // indicates whether the guard operation might return ALT_REPEAT
365 bool can_repeat
=recv_stmt
->can_repeat();
366 if(expr
.preamble
|| expr
.postamble
) {
367 out_code
=mputstr(out_code
, "{\n");
368 out_code
=mputstr(out_code
, expr
.preamble
);
370 out_code
=mputprintf(out_code
, "%s_alt_flag[%lu]=%s;\n",
371 mytmpid
.c_str(), (unsigned long) branch_i
, expr
.expr
);
372 if(expr
.preamble
|| expr
.postamble
) {
373 out_code
=mputstr(out_code
, expr
.postamble
);
374 out_code
=mputstr(out_code
, "}\n");
376 Code::free_expr(&expr
);
378 out_code
=mputprintf(out_code
,
379 "if(%s_alt_flag[%lu]==ALT_REPEAT) goto %s;\n",
380 mytmpid
.c_str(), (unsigned long) branch_i
,
383 if(branchtype
==BT_RECV
)
384 out_code
=mputprintf(out_code
,
385 "if(%s_alt_flag[%lu]==ALT_YES) goto %s_l%lu;\n",
386 mytmpid
.c_str(), (unsigned long) branch_i
,
387 mytmpid
.c_str(), (unsigned long) goto_label_num
);
389 out_code
=mputprintf(out_code
,
390 "if(%s_alt_flag[%lu]==ALT_YES) ",
391 mytmpid
.c_str(), (unsigned long) branch_i
);
392 // statement block code generation;
393 StatementBlock
*block
=ag
->get_block();
394 bool has_recv
=block
->has_receiving_stmt();
395 char*& out_stmt
=has_recv
?get_out_branches():out_code
;
397 out_code
=mputprintf(out_code
,
398 "goto %s_branch%lu;\n",
399 mytmpid
.c_str(), (unsigned long) branch_i
);
400 out_stmt
=mputprintf(out_stmt
, "%s_branch%lu:\n",
401 mytmpid
.c_str(), (unsigned long) branch_i
);
402 block
->ilt_generate_code(this);
405 out_stmt
=mputstr(out_stmt
, "{\n"); // (2)
406 out_stmt
=block
->generate_code(out_stmt
);
408 if(branchtype
==BT_IL
) {
409 out_stmt
=mputprintf(out_stmt
, "%s_state[%lu]=1;\n",
410 mytmpid
.c_str(), (unsigned long) state_var
);
411 if(!ilt
->is_toplevel()) {
412 vector
<ILT_branch
>& ilt_branches
= ilt
->get_as_branch()->branches
;
413 bool use_loop
=ilt_branches
.size() > 8;
414 size_t bmin
=0, bmax
=0;
416 size_t st_var
=ilt_branches
[0]->get_my_state_var();
417 bmin
=st_var
; bmax
=st_var
;
418 for (size_t i
=1; i
<ilt_branches
.size(); i
++) {
419 st_var
=ilt_branches
[i
]->get_my_state_var();
420 if (st_var
<bmin
) bmin
=st_var
;
421 if (st_var
>bmax
) bmax
=st_var
;
423 use_loop
=(bmax
-bmin
+1) == ilt_branches
.size();
426 out_stmt
=mputprintf(out_stmt
,
427 "for(size_t tmp_i=%lu; tmp_i<%lu; tmp_i++)"
428 " if (%s_state[tmp_i]!=1) goto %s;\n",
429 (unsigned long) bmin
, (unsigned long) bmax
+1,
430 mytmpid
.c_str(), mytmpid
.c_str());
431 } else if (ilt_branches
.size() > 1) {
432 // Check if any branches of non top level interleave need to be exe.
433 for(size_t i
=0, j
=0; i
<ilt_branches
.size(); i
++) {
434 ILT_branch
*b
=ilt_branches
[i
];
436 out_stmt
=mputprintf(out_stmt
, "%s%s_state[%lu]!=1",
437 j
++?" || ":"if (", mytmpid
.c_str(),
438 (unsigned long) b
->get_my_state_var());
440 out_stmt
=mputprintf(out_stmt
, ") goto %s;\n", mytmpid
.c_str());
442 // non top level interleave: Handle finish case
443 out_stmt
=mputprintf(out_stmt
, "goto %s_l%lu;\n",
444 mytmpid
.c_str(), (unsigned long) goto_label_num
);
445 } else // top level: finish condition is checked at the beginning
446 out_stmt
=mputprintf(out_stmt
, "goto %s;\n", mytmpid
.c_str());
447 } else // not interleave: finish after one branch execution
448 out_stmt
=mputprintf(out_stmt
, "goto %s_l%lu;\n",
449 mytmpid
.c_str(), (unsigned long) goto_label_num
);
451 out_stmt
=mputstr(out_stmt
, "}\n"); // (2)
453 out_code
=mputstr(out_code
, "}\n"); // (1)
454 // the nested branches
455 for(size_t i
=0; i
<branches
.size(); i
++)
456 branches
[i
]->ilt_generate_code(this);
This page took 0.041517 seconds and 5 git commands to generate.