1 /******************************************************************************
2 * Copyright (c) 2000-2016 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
13 * Szabo, Janos Zoltan – initial implementation
15 ******************************************************************************/
20 // =================================
22 // =================================
26 for(size_t i
=0; i
<branches
.size(); i
++)
31 ILT_branch
* ILT::get_as_branch()
33 FATAL_ERROR("ILT::get_as_branch()");
37 void ILT::add_branch(ILT_branch
*p_branch
)
39 if(!p_branch
) FATAL_ERROR("ILT::add_branch()");
40 branches
.add(p_branch
);
41 ILT_root
*my_root
= get_my_root();
42 p_branch
->set_my_root(my_root
);
43 p_branch
->set_branch_i(my_root
->get_new_branch_num());
47 // =================================
49 // =================================
51 ILT_root::ILT_root(Statement
*p_il
)
52 : il(p_il
), tmpnum(0), c_l(0), c_b(0)
54 if(!p_il
|| p_il
->get_statementtype()!=Statement::S_INTERLEAVE
)
55 FATAL_ERROR("ILT_root::ILT_root()");
56 mytmpid
=p_il
->get_my_sb()->get_scope_mod_gen()->get_temporary_id();
58 out_statevars
=memptystr();
60 out_branches
=memptystr();
65 for(size_t i
=0; i
<state_var_vals
.size(); i
++)
66 delete state_var_vals
[i
];
67 state_var_vals
.clear();
74 ILT_root
*ILT_root::clone() const
76 FATAL_ERROR("ILT_root::clone()");
79 ILT_root
*ILT_root::get_my_root()
84 bool ILT_root::is_toplevel()
89 char*& ILT_root::get_out_def()
94 char*& ILT_root::get_out_code()
99 char*& ILT_root::get_out_branches()
104 const string
& ILT_root::get_my_tmpid()
109 size_t ILT_root::get_new_tmpnum()
114 size_t ILT_root::get_new_state_var(bool toplevel
)
116 state_var_vals
.add(new size_t(1));
117 size_t newvar
=state_var_vals
.size()-1;
118 out_statevars
=mputprintf(out_statevars
, "%s_state[%lu]=%s;\n",
119 mytmpid
.c_str(), (unsigned long) newvar
, toplevel
?"2":"0");
123 size_t ILT_root::get_new_state_var_val(size_t p_state_var
)
125 if(p_state_var
>=state_var_vals
.size())
126 FATAL_ERROR("ILT_root::get_new_state_var_val()");
127 return ++*state_var_vals
[p_state_var
];
130 size_t ILT_root::get_new_label_num()
135 char* ILT_root::generate_code(char *str
)
137 // everything starts here: the top-level interleave statement
138 il
->ilt_generate_code(this);
139 // generating code for the branches
140 for(size_t i
=0; i
<branches
.size(); i
++)
141 branches
[i
]->ilt_generate_code(this);
142 str
=mputstr(str
, "{\n"); // (1)
143 // the state vars: definition
144 str
=mputprintf(str
, "size_t %s_state[%lu];\n",
145 mytmpid
.c_str(), (unsigned long) state_var_vals
.size());
146 // the state vars: initialization
147 str
=mputstr(str
, out_statevars
);
148 // the alt status flags: definition
149 str
=mputprintf(str
, "alt_status %s_alt_flag[%lu];\n",
150 mytmpid
.c_str(), (unsigned long) (c_b
+1));
152 str
=mputstr(str
, out_def
);
153 // the core of the interleave
154 str
=mputprintf(str
, "%s:\n"
155 "for(size_t tmp_i=0; tmp_i<%lu; tmp_i++)"
156 " %s_alt_flag[tmp_i]=ALT_UNCHECKED;\n"
157 "%s_alt_flag[%lu]=ALT_MAYBE;\n"
158 "TTCN_Snapshot::take_new(FALSE);\n"
159 "for( ; ; ) {\n" // (2)
160 "if(", mytmpid
.c_str(),
161 (unsigned long) c_b
, mytmpid
.c_str(),
162 mytmpid
.c_str(), (unsigned long) c_b
);
163 // checking for final condition
164 for(size_t i
=0; i
<branches
.size(); i
++) {
165 ILT_branch
*b
=branches
[i
];
166 str
=mputprintf(str
, "%s%s_state[%lu]==1",
167 i
?" && ":"", mytmpid
.c_str(), (unsigned long) b
->get_my_state_var());
169 str
=mputstr(str
, ") break;\n");
171 str
=mputstr(str
, out_code
);
173 str
=mputprintf(str
, "if(%s_alt_flag[%lu]==ALT_MAYBE) {\n"
174 "%s_alt_flag[%lu]=TTCN_Default::try_altsteps();\n"
175 "if(%s_alt_flag[%lu]==ALT_YES || %s_alt_flag[%lu]==ALT_BREAK)"
177 "else if(%s_alt_flag[%lu]==ALT_REPEAT) goto %s;\n"
179 mytmpid
.c_str(), (unsigned long) c_b
,
180 mytmpid
.c_str(), (unsigned long) c_b
,
181 mytmpid
.c_str(), (unsigned long) c_b
,
182 mytmpid
.c_str(), (unsigned long) c_b
,
183 mytmpid
.c_str(), (unsigned long) c_b
,
185 str
=il
->update_location_object(str
);
187 str
=mputprintf(str
, "for(size_t tmp_i=0; tmp_i<%lu; tmp_i++)"
188 " if(%s_alt_flag[tmp_i]!=ALT_NO) goto %s_newsnapshot;\n",
189 (unsigned long) (c_b
+1), mytmpid
.c_str(), mytmpid
.c_str());
190 str
= mputstr(str
, "TTCN_error(\"None of the branches can be chosen in the "
191 "interleave statement in file ");
192 str
= Code::translate_string(str
, il
->get_filename());
193 int first_line
= il
->get_first_line(), last_line
= il
->get_last_line();
194 if (first_line
< last_line
) str
= mputprintf(str
,
195 " between lines %d and %d", first_line
, last_line
);
196 else str
= mputprintf(str
, ", line %d", first_line
);
197 str
= mputprintf(str
, ".\");\n"
199 "TTCN_Snapshot::take_new(TRUE);\n"
200 "continue;\n", mytmpid
.c_str());
201 // the code of branches
202 str
=mputstr(str
, out_branches
);
203 str
=mputstr(str
, "}\n" // (2)
208 // =================================
210 // =================================
212 ILT_branch::ILT_branch(branchtype_t p_bt
, AltGuard
*p_ag
,
213 string p_state_cond
, size_t p_state_var
,
214 size_t p_state_var_val
, size_t p_goto_label_num
)
215 : branchtype(p_bt
), root(0), branch_i((size_t)-1),
216 state_cond(p_state_cond
), state_var(p_state_var
),
217 state_var_val(p_state_var_val
), goto_label_num(p_goto_label_num
)
222 if(!p_ag
) FATAL_ERROR("ILT_branch::ILT_branch()");
224 // the checker should check this but one never knows :)
225 if(ag
->get_type()!=AltGuard::AG_OP
)
226 FATAL_ERROR("ILT_branch::ILT_branch()");
229 FATAL_ERROR("ILT_branch::ILT_branch()");
233 ILT_branch::ILT_branch(branchtype_t p_bt
, Statement
*p_stmt
,
234 string p_state_cond
, size_t p_state_var
,
235 size_t p_state_var_val
, size_t p_goto_label_num
)
236 : branchtype(p_bt
), root(0), branch_i((size_t)-1),
237 state_cond(p_state_cond
), state_var(p_state_var
),
238 state_var_val(p_state_var_val
), goto_label_num(p_goto_label_num
)
242 if(!p_stmt
) FATAL_ERROR("ILT_branch::ILT_branch()");
246 FATAL_ERROR("ILT_branch::ILT_branch()");
250 ILT_branch::~ILT_branch()
255 ILT_branch
*ILT_branch::clone() const
257 FATAL_ERROR("ILT_branch::clone()");
260 void ILT_branch::set_my_root(ILT_root
*p_root
)
262 if(!p_root
) FATAL_ERROR("ILT_branch::set_my_root()");
266 ILT_root
* ILT_branch::get_my_root()
268 if (!root
) FATAL_ERROR("ILT_branch::get_my_root()");
272 ILT_branch
*ILT_branch::get_as_branch()
277 bool ILT_branch::is_toplevel()
282 char*& ILT_branch::get_out_def()
284 return root
->get_out_def();
287 char*& ILT_branch::get_out_code()
289 return root
->get_out_code();
292 char*& ILT_branch::get_out_branches()
294 return root
->get_out_branches();
297 const string
& ILT_branch::get_my_tmpid()
299 return root
->get_my_tmpid();
302 size_t ILT_branch::get_new_tmpnum()
304 return root
->get_new_tmpnum();
307 size_t ILT_branch::get_new_state_var(bool toplevel
)
309 return root
->get_new_state_var(toplevel
);
312 size_t ILT_branch::get_new_state_var_val(size_t p_state_var
)
314 return root
->get_new_state_var_val(p_state_var
);
317 size_t ILT_branch::get_new_label_num()
319 return root
->get_new_label_num();
322 void ILT_branch::ilt_generate_code(ILT
*ilt
)
324 const string
& mytmpid
=get_my_tmpid();
325 char*& out_code
=get_out_code();
327 =branchtype
==BT_RECV
?stmt
:ag
->get_guard_stmt();
328 out_code
=recv_stmt
->update_location_object(out_code
);
329 // ALT_UNCHECKED -> ALT_MAYBE or ALT_NO (state vars & guard expr)
331 out_code
=mputprintf(out_code
,
332 "if(%s_alt_flag[%lu]==ALT_UNCHECKED) {\n" // (1)
334 mytmpid
.c_str(), (unsigned long) branch_i
);
335 if(!state_cond
.empty())
336 out_code
=mputprintf(out_code
, "%s && ", state_cond
.c_str());
337 out_code
=mputprintf(out_code
, "%s_state[%lu]==%lu) {\n", // (2)
338 mytmpid
.c_str(), (unsigned long) state_var
,
339 (unsigned long) state_var_val
);
340 // only alt branch can have guard expression
341 Value
*guard_expr
=branchtype
==BT_ALT
?ag
->get_guard_expr():0;
343 out_code
=guard_expr
->update_location_object(out_code
);
344 expression_struct expr
;
345 Code::init_expr(&expr
);
346 guard_expr
->generate_code_expr(&expr
);
347 out_code
=mputstr(out_code
, expr
.preamble
);
348 out_code
=mputprintf(out_code
,
349 "%s_alt_flag[%lu]=(%s)?ALT_MAYBE:ALT_NO;\n",
350 mytmpid
.c_str(), (unsigned long) branch_i
,
352 out_code
=mputstr(out_code
, expr
.postamble
);
353 Code::free_expr(&expr
);
355 else out_code
=mputprintf(out_code
,
356 "%s_alt_flag[%lu]=ALT_MAYBE;\n",
357 mytmpid
.c_str(), (unsigned long) branch_i
);
358 out_code
=mputprintf(out_code
,
360 "else %s_alt_flag[%lu]=ALT_NO;\n"
362 mytmpid
.c_str(), (unsigned long) branch_i
);
364 // ALT_MAYBE -> ALT_YES or ALT_REPEAT or ALT_NO (guard stmt)
366 out_code
=mputprintf(out_code
,
367 "if(%s_alt_flag[%lu]==ALT_MAYBE) {\n", // (1)
368 mytmpid
.c_str(), (unsigned long) branch_i
);
369 expression_struct expr
;
370 Code::init_expr(&expr
);
371 recv_stmt
->generate_code_expr(&expr
);
372 // indicates whether the guard operation might return ALT_REPEAT
373 bool can_repeat
=recv_stmt
->can_repeat();
374 if(expr
.preamble
|| expr
.postamble
) {
375 out_code
=mputstr(out_code
, "{\n");
376 out_code
=mputstr(out_code
, expr
.preamble
);
378 out_code
=mputprintf(out_code
, "%s_alt_flag[%lu]=%s;\n",
379 mytmpid
.c_str(), (unsigned long) branch_i
, expr
.expr
);
380 if(expr
.preamble
|| expr
.postamble
) {
381 out_code
=mputstr(out_code
, expr
.postamble
);
382 out_code
=mputstr(out_code
, "}\n");
384 Code::free_expr(&expr
);
386 out_code
=mputprintf(out_code
,
387 "if(%s_alt_flag[%lu]==ALT_REPEAT) goto %s;\n",
388 mytmpid
.c_str(), (unsigned long) branch_i
,
391 if(branchtype
==BT_RECV
)
392 out_code
=mputprintf(out_code
,
393 "if(%s_alt_flag[%lu]==ALT_YES) goto %s_l%lu;\n",
394 mytmpid
.c_str(), (unsigned long) branch_i
,
395 mytmpid
.c_str(), (unsigned long) goto_label_num
);
397 out_code
=mputprintf(out_code
,
398 "if(%s_alt_flag[%lu]==ALT_YES) ",
399 mytmpid
.c_str(), (unsigned long) branch_i
);
400 // statement block code generation;
401 StatementBlock
*block
=ag
->get_block();
402 bool has_recv
=block
->has_receiving_stmt();
403 char*& out_stmt
=has_recv
?get_out_branches():out_code
;
405 out_code
=mputprintf(out_code
,
406 "goto %s_branch%lu;\n",
407 mytmpid
.c_str(), (unsigned long) branch_i
);
408 out_stmt
=mputprintf(out_stmt
, "%s_branch%lu:\n",
409 mytmpid
.c_str(), (unsigned long) branch_i
);
410 block
->ilt_generate_code(this);
413 out_stmt
=mputstr(out_stmt
, "{\n"); // (2)
414 out_stmt
=block
->generate_code(out_stmt
);
416 if(branchtype
==BT_IL
) {
417 out_stmt
=mputprintf(out_stmt
, "%s_state[%lu]=1;\n",
418 mytmpid
.c_str(), (unsigned long) state_var
);
419 if(!ilt
->is_toplevel()) {
420 vector
<ILT_branch
>& ilt_branches
= ilt
->get_as_branch()->branches
;
421 bool use_loop
=ilt_branches
.size() > 8;
422 size_t bmin
=0, bmax
=0;
424 size_t st_var
=ilt_branches
[0]->get_my_state_var();
425 bmin
=st_var
; bmax
=st_var
;
426 for (size_t i
=1; i
<ilt_branches
.size(); i
++) {
427 st_var
=ilt_branches
[i
]->get_my_state_var();
428 if (st_var
<bmin
) bmin
=st_var
;
429 if (st_var
>bmax
) bmax
=st_var
;
431 use_loop
=(bmax
-bmin
+1) == ilt_branches
.size();
434 out_stmt
=mputprintf(out_stmt
,
435 "for(size_t tmp_i=%lu; tmp_i<%lu; tmp_i++)"
436 " if (%s_state[tmp_i]!=1) goto %s;\n",
437 (unsigned long) bmin
, (unsigned long) bmax
+1,
438 mytmpid
.c_str(), mytmpid
.c_str());
439 } else if (ilt_branches
.size() > 1) {
440 // Check if any branches of non top level interleave need to be exe.
441 for(size_t i
=0, j
=0; i
<ilt_branches
.size(); i
++) {
442 ILT_branch
*b
=ilt_branches
[i
];
444 out_stmt
=mputprintf(out_stmt
, "%s%s_state[%lu]!=1",
445 j
++?" || ":"if (", mytmpid
.c_str(),
446 (unsigned long) b
->get_my_state_var());
448 out_stmt
=mputprintf(out_stmt
, ") goto %s;\n", mytmpid
.c_str());
450 // non top level interleave: Handle finish case
451 out_stmt
=mputprintf(out_stmt
, "goto %s_l%lu;\n",
452 mytmpid
.c_str(), (unsigned long) goto_label_num
);
453 } else // top level: finish condition is checked at the beginning
454 out_stmt
=mputprintf(out_stmt
, "goto %s;\n", mytmpid
.c_str());
455 } else // not interleave: finish after one branch execution
456 out_stmt
=mputprintf(out_stmt
, "goto %s_l%lu;\n",
457 mytmpid
.c_str(), (unsigned long) goto_label_num
);
459 out_stmt
=mputstr(out_stmt
, "}\n"); // (2)
461 out_code
=mputstr(out_code
, "}\n"); // (1)
462 // the nested branches
463 for(size_t i
=0; i
<branches
.size(); i
++)
464 branches
[i
]->ilt_generate_code(this);
This page took 0.040188 seconds and 5 git commands to generate.