CBMC
Loading...
Searching...
No Matches
statement_list_typecheck.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: Statement List Language Type Checking
4
5Author: Matthias Weiss, matthias.weiss@diffblue.com
6
7\*******************************************************************/
8
11
13
14#include <util/cprover_prefix.h>
15#include <util/message.h>
16#include <util/namespace.h>
17#include <util/pointer_expr.h>
18#include <util/simplify_expr.h>
19#include <util/std_code.h>
21
23
25
27#define STATEMENT_LIST_PTR_WIDTH 64
28// TODO: Replace with more specific exception throws.
29#define TYPECHECK_ERROR 0
31#define DATA_BLOCK_PARAMETER_NAME "data_block"
33#define DATA_BLOCK_TYPE_POSTFIX "_db"
35#define CPROVER_ASSERT CPROVER_PREFIX "assert"
37#define CPROVER_ASSUME CPROVER_PREFIX "assume"
39#define CPROVER_TEMP_RLO CPROVER_PREFIX "temp_rlo"
40
55
63
81
83 const statement_list_parse_treet &parse_tree,
84 symbol_table_baset &symbol_table,
85 const std::string &module,
86 message_handlert &message_handler)
87{
89 parse_tree, symbol_table, module, message_handler);
90
91 return stl_typecheck.typecheck_main();
92}
93
95 exprt rlo_bit,
96 bool or_bit,
97 codet function_code)
98 : rlo_bit(rlo_bit), or_bit(or_bit), function_code(function_code)
99{
100}
101
103 size_t nesting_depth,
104 bool jumps_permitted,
105 bool fc_false_required)
106 : nesting_depth(nesting_depth),
107 jumps_permitted(jumps_permitted),
108 fc_false_required(fc_false_required)
109{
110}
112 size_t nesting_depth,
113 bool sets_fc_false)
114 : nesting_depth(nesting_depth), sets_fc_false(sets_fc_false)
115{
116}
117
129
131{
132 // First fill the symbol table with function, tag and parameter declarations
133 // to be able to properly resolve block calls later.
137 parse_tree.function_blocks)
140 // Temporary RLO symbol for certain operations.
141 add_temp_rlo();
142
143 // Iterate through all networks to generate the function bodies.
145 parse_tree.function_blocks)
146 {
149 }
151 {
154 }
155}
156
159{
160 // Create FB symbol.
162 function_block_sym.module = module;
163 function_block_sym.base_name = function_block_sym.name;
164 function_block_sym.pretty_name = function_block_sym.name;
165
166 // When calling function blocks, the passed parameters are value-copied to a
167 // corresponding instance data block. This block contains all input, inout,
168 // output and static variables. The function block reads and writes only
169 // those fields and does not modify the actual parameters. To simulate this
170 // behaviour, all function blocks are modeled as functions with a single
171 // parameter: An instance of their data block, whose members they modify.
172
173 // Create and add DB type symbol.
180 data_block.base_name = data_block.name;
182
183 // Create and add parameter symbol.
187 param_sym.module = module;
188 param_sym.type = param.type();
189 param_sym.name = param.get_identifier();
191 param_sym.pretty_name = param_sym.base_name;
194
195 // Setup FB symbol type and value.
197 params.push_back(param);
198 code_typet fb_type{params, empty_typet()};
202}
203
224
226{
227 for(const symbol_exprt &tag : parse_tree.tags)
228 {
229 symbolt tag_sym{tag.get_identifier(), tag.type(), ID_statement_list};
230 tag_sym.is_static_lifetime = true;
231 tag_sym.module = module;
232 tag_sym.base_name = tag_sym.name;
233 tag_sym.pretty_name = tag_sym.name;
235 }
236}
237
239{
241 temp_rlo.is_static_lifetime = true;
242 temp_rlo.module = module;
243 temp_rlo.base_name = temp_rlo.name;
244 temp_rlo.pretty_name = temp_rlo.name;
246}
247
263
267 const irep_idt &var_property)
268{
269 for(const statement_list_parse_treet::var_declarationt &declaration :
270 var_decls)
271 {
272 const irep_idt &var_name{declaration.variable.get_identifier()};
273 const typet &var_type{declaration.variable.type()};
276 components.push_back(component);
277 }
278}
279
283 const irep_idt &function_name,
284 const irep_idt &var_property)
285{
286 for(const statement_list_parse_treet::var_declarationt &declaration :
287 var_decls)
288 {
290 param_sym.module = module;
291 param_sym.type = declaration.variable.type();
292 param_sym.name = id2string(function_name) +
293 "::" + id2string(declaration.variable.get_identifier());
294 param_sym.base_name = declaration.variable.get_identifier();
295 param_sym.pretty_name = param_sym.base_name;
298
299 code_typet::parametert param{declaration.variable.type()};
300 param.set_identifier(param_sym.name);
301 param.set_base_name(declaration.variable.get_identifier());
303 params.push_back(param);
304 }
305}
306
310{
311 for(const statement_list_parse_treet::var_declarationt &declaration :
312 tia_module.var_temp)
313 {
315 id2string(tia_symbol.name) +
316 "::" + id2string(declaration.variable.get_identifier()),
317 declaration.variable.type(),
319 temp_sym.base_name = declaration.variable.get_identifier();
320 temp_sym.pretty_name = temp_sym.base_name;
321 temp_sym.module = module;
323
324 const code_declt code_decl{temp_sym.symbol_expr()};
325 tia_symbol.value.add_to_operands(code_decl);
326 }
327}
328
332{
333 // Leave value empty if there are no networks to iterate through.
334 if(tia_module.networks.empty())
335 return;
336 if(tia_symbol.value.is_nil())
337 tia_symbol.value = code_blockt{};
338
341
342 for(const auto &network : tia_module.networks)
343 {
345 for(const auto &instruction : network.instructions)
347 }
349}
350
352{
353 if(!label_references.empty())
354 {
355 error() << "Unable to find the labels:";
356 for(auto pair : label_references)
357 {
358 error() << "\n";
359 error() << id2string(pair.first);
360 }
361 error() << eom;
362 throw TYPECHECK_ERROR;
363 }
364}
365
373
375 const codet &instruction,
377{
378 const irep_idt statement{instruction.get_statement()};
379
380 if(ID_label == statement)
381 typecheck_label(instruction, tia_element);
382 else if(ID_statement_list_load == statement)
384 else if(ID_statement_list_transfer == statement)
386 else if(ID_statement_list_accu_int_add == statement)
388 else if(ID_statement_list_accu_int_sub == statement)
390 else if(ID_statement_list_accu_int_mul == statement)
392 else if(ID_statement_list_accu_int_div == statement)
394 else if(ID_statement_list_accu_int_eq == statement)
396 else if(ID_statement_list_accu_int_neq == statement)
398 else if(ID_statement_list_accu_int_lt == statement)
400 else if(ID_statement_list_accu_int_gt == statement)
402 else if(ID_statement_list_accu_int_lte == statement)
404 else if(ID_statement_list_accu_int_gte == statement)
406 else if(ID_statement_list_accu_dint_add == statement)
408 else if(ID_statement_list_accu_dint_sub == statement)
410 else if(ID_statement_list_accu_dint_mul == statement)
412 else if(ID_statement_list_accu_dint_div == statement)
414 else if(ID_statement_list_accu_dint_eq == statement)
416 else if(ID_statement_list_accu_dint_neq == statement)
418 else if(ID_statement_list_accu_dint_lt == statement)
420 else if(ID_statement_list_accu_dint_gt == statement)
422 else if(ID_statement_list_accu_dint_lte == statement)
424 else if(ID_statement_list_accu_dint_gte == statement)
426 else if(ID_statement_list_accu_real_add == statement)
428 else if(ID_statement_list_accu_real_sub == statement)
430 else if(ID_statement_list_accu_real_mul == statement)
432 else if(ID_statement_list_accu_real_div == statement)
434 else if(ID_statement_list_accu_real_eq == statement)
436 else if(ID_statement_list_accu_real_neq == statement)
438 else if(ID_statement_list_accu_real_lt == statement)
440 else if(ID_statement_list_accu_real_gt == statement)
442 else if(ID_statement_list_accu_real_lte == statement)
444 else if(ID_statement_list_accu_real_gte == statement)
446 else if(ID_statement_list_not == statement)
447 typecheck_statement_list_not(instruction);
448 else if(ID_statement_list_and == statement)
450 else if(ID_statement_list_and_not == statement)
452 else if(ID_statement_list_or == statement)
454 else if(ID_statement_list_or_not == statement)
456 else if(ID_statement_list_xor == statement)
458 else if(ID_statement_list_xor_not == statement)
460 else if(ID_statement_list_and_nested == statement)
462 else if(ID_statement_list_and_not_nested == statement)
464 else if(ID_statement_list_or_nested == statement)
466 else if(ID_statement_list_or_not_nested == statement)
468 else if(ID_statement_list_xor_nested == statement)
470 else if(ID_statement_list_xor_not_nested == statement)
472 else if(ID_statement_list_nesting_closed == statement)
474 else if(ID_statement_list_assign == statement)
476 else if(ID_statement_list_set_rlo == statement)
478 else if(ID_statement_list_clr_rlo == statement)
480 else if(ID_statement_list_set == statement)
482 else if(ID_statement_list_reset == statement)
484 else if(ID_statement_list_jump_unconditional == statement)
486 else if(ID_statement_list_jump_conditional == statement)
488 else if(ID_statement_list_jump_conditional_not == statement)
490 else if(ID_statement_list_nop == statement)
491 return;
492 else if(ID_statement_list_call == statement)
494 else
495 {
496 error() << "OP code of instruction not found: "
497 << instruction.get_statement() << eom;
498 throw TYPECHECK_ERROR;
499 }
500}
501
503 const codet &instruction,
505{
506 const code_labelt &label = to_code_label(instruction);
507
508 // Check if label is duplicate (not allowed in STL).
509 if(stl_labels.find(label.get_label()) != end(stl_labels))
510 {
511 error() << "Multiple definitions of label " << id2string(label.get_label())
512 << eom;
513 throw TYPECHECK_ERROR;
514 }
515
516 // Determine the properties of this location in the code.
518
519 // Store the implicit RLO in order to correctly separate the different
520 // blocks of logic.
521 if(location.jumps_permitted)
523
524 // Now check if there are any jumps that referenced that label before and
525 // validate these.
526 typecheck_jump_locations(label, location);
527
528 // Only add the label to the code if jumps are permitted. Proceed as normal
529 // if they are not. An added label will always point at an empty code
530 // location due to the way how the typecheck works.
531 if(location.jumps_permitted)
532 tia_element.value.add_to_operands(
533 code_labelt{label.get_label(), code_skipt{}});
534
535 // Recursive call to check the label target.
537}
538
541{
542 // Jumps to a label are only allowed if one of the following conditions
543 // applies:
544 //
545 // a) The /FC bit is false when encountering the instruction (pointing at the
546 // beginning of a logic sequence or no sequence at all).
547 // b) The /FC bit is set to false after processing the instruction (pointing
548 // at the termination of a logic sequence). This excludes nesting-open
549 // operations since although they terminate the current sequence, it will
550 // be resumed later.
551 //
552 // Labels at locations where this does not hold true compile, but actual
553 // jumps to them do not.
554 //
555 // Additionally, jumps to instructions that mark the beginning of a logic
556 // sequence are only allowed if the jump instruction itself sets the /FC bit
557 // to false.
558
559 bool jumps_permitted = false;
560 bool fc_false_required = false;
561 if(!fc_bit)
562 {
563 jumps_permitted = true;
564 // Check if label points to new logic sequence.
566 if(op_code == label.code().get_statement())
567 {
568 fc_false_required = true;
569 break;
570 }
571 }
572 else // Check if the label's instruction terminates the logic sequence.
573 {
575 if(op_code == label.code().get_statement())
576 {
577 jumps_permitted = true;
578 break;
579 }
580 }
581
582 // Add the label to map.
583 stl_label_locationt location{
584 nesting_stack.size(), jumps_permitted, fc_false_required};
585 stl_labels.emplace(label.get_label(), location);
586 return location;
587}
588
590 const code_labelt &label,
592{
593 // Now check if there are any jumps that referenced that label before and
594 // validate these.
595 auto reference_it = label_references.find(label.get_label());
597 {
598 if(!location.jumps_permitted)
599 {
600 error() << "Not allowed to jump to label " << id2string(label.get_label())
601 << eom;
602 throw TYPECHECK_ERROR;
603 }
604 for(auto jump_location_it = begin(reference_it->second);
605 jump_location_it != end(reference_it->second);
607 {
608 if(location.fc_false_required && !jump_location_it->sets_fc_false)
609 {
610 error() << "Jump to label " << id2string(label.get_label())
611 << " can not be unconditional" << eom;
612 throw TYPECHECK_ERROR;
613 }
614 if(nesting_stack.size() != jump_location_it->nesting_depth)
615 {
616 error() << "Jump to label " << id2string(label.get_label())
617 << " violates brace scope" << eom;
618 throw TYPECHECK_ERROR;
619 }
620 }
621 // Remove entry after validation.
622 label_references.erase(label.get_label());
623 }
624}
625
627 const codet &op_code,
628 const symbolt &tia_element)
629{
630 const symbol_exprt *const symbol =
632 if(symbol)
633 {
634 const irep_idt &identifier{symbol->get_identifier()};
635 const exprt val{typecheck_identifier(tia_element, identifier)};
636 accumulator.push_back(val);
637 }
639 accumulator.push_back(op_code.op0());
640 else
641 {
642 error() << "Instruction is not followed by symbol or constant" << eom;
643 throw TYPECHECK_ERROR;
644 }
645}
646
648 const codet &op_code,
650{
652 const exprt lhs{typecheck_identifier(tia_element, op.get_identifier())};
653 if(lhs.type() != accumulator.back().type())
654 {
655 error() << "Types of transfer assignment do not match" << eom;
656 throw TYPECHECK_ERROR;
657 }
658 const code_assignt assignment{lhs, accumulator.back()};
659 tia_element.value.add_to_operands(assignment);
660}
661
663 const codet &op_code)
664{
666
667 // Pop first operand, peek second.
668 const exprt accu1{accumulator.back()};
669 accumulator.pop_back();
670 const exprt &accu2{accumulator.back()};
671 const plus_exprt operation{accu2, accu1};
672 accumulator.push_back(operation);
673}
674
676 const codet &op_code)
677{
679
680 // Pop first operand, peek second.
681 const exprt accu1{accumulator.back()};
682 accumulator.pop_back();
683 const exprt &accu2{accumulator.back()};
684 const minus_exprt operation{accu2, accu1};
685 accumulator.push_back(operation);
686}
687
689 const codet &op_code)
690{
692
693 // Pop first operand, peek second.
694 const exprt accu1{accumulator.back()};
695 accumulator.pop_back();
696 const exprt &accu2{accumulator.back()};
697 const mult_exprt operation{accu2, accu1};
698 accumulator.push_back(operation);
699}
700
702 const codet &op_code)
703{
705
706 // Pop first operand, peek second.
707 const exprt accu1{accumulator.back()};
708 accumulator.pop_back();
709 const exprt &accu2{accumulator.back()};
710 const div_exprt operation{accu2, accu1};
711 accumulator.push_back(operation);
712}
713
720
727
734
741
748
755
757 const codet &op_code)
758{
760
761 // Pop first operand, peek second.
762 const exprt accu1{accumulator.back()};
763 accumulator.pop_back();
764 const exprt &accu2{accumulator.back()};
765 const plus_exprt operation{accu2, accu1};
766 accumulator.push_back(operation);
767}
768
770 const codet &op_code)
771{
773
774 // Pop first operand, peek second.
775 const exprt accu1{accumulator.back()};
776 accumulator.pop_back();
777 const exprt &accu2{accumulator.back()};
778 const minus_exprt operation{accu2, accu1};
779 accumulator.push_back(operation);
780}
781
783 const codet &op_code)
784{
786
787 // Pop first operand, peek second.
788 const exprt accu1{accumulator.back()};
789 accumulator.pop_back();
790 const exprt &accu2{accumulator.back()};
791 const mult_exprt operation{accu2, accu1};
792 accumulator.push_back(operation);
793}
794
796 const codet &op_code)
797{
799
800 // Pop first operand, peek second.
801 const exprt accu1{accumulator.back()};
802 accumulator.pop_back();
803 const exprt &accu2{accumulator.back()};
804 const div_exprt operation{accu2, accu1};
805 accumulator.push_back(operation);
806}
807
814
821
828
835
842
849
851 const codet &op_code)
852{
854
855 // Pop first operand, peek second.
856 const exprt accu1{accumulator.back()};
857 accumulator.pop_back();
858 const exprt &accu2{accumulator.back()};
859 const plus_exprt operation{accu2, accu1};
860 accumulator.push_back(operation);
861}
862
864 const codet &op_code)
865{
867
868 // Pop first operand, peek second.
869 const exprt accu1{accumulator.back()};
870 accumulator.pop_back();
871 const exprt &accu2{accumulator.back()};
872 const minus_exprt operation{accu2, accu1};
873 accumulator.push_back(operation);
874}
875
877 const codet &op_code)
878{
880
881 // Pop first operand, peek second.
882 const exprt accu1{accumulator.back()};
883 accumulator.pop_back();
884 const exprt &accu2{accumulator.back()};
885 const mult_exprt operation{accu2, accu1};
886 accumulator.push_back(operation);
887}
888
890 const codet &op_code)
891{
893
894 // Pop first operand, peek second.
895 const exprt accu1{accumulator.back()};
896 accumulator.pop_back();
897 const exprt &accu2{accumulator.back()};
898 const div_exprt operation{accu2, accu1};
899 accumulator.push_back(operation);
900}
901
908
915
922
929
936
943
951
953 const codet &op_code,
954 const symbolt &tia_element)
955{
956 exprt op{
958
959 // If inside of a bit string and if the OR bit is not set, create an 'and'
960 // expression with the operand and the current contents of the rlo bit. If
961 // the OR bit is set then this instruction is part of an 'and-before-or'
962 // block and needs to be added to the rlo in a special way.
963 if(fc_bit && or_bit)
965 else if(fc_bit)
966 {
967 const and_exprt unsimplified{rlo_bit, op};
969 }
970 else
972}
973
975 const codet &op_code,
976 const symbolt &tia_element)
977{
978 exprt op{
980
981 // If inside of a bit string and if the OR bit is not set, create an 'and'
982 // expression with the operand and the current contents of the rlo bit. If
983 // the OR bit is set then this instruction is part of an 'and-before-or'
984 // block and needs to be added to the rlo in a special way.
985 if(or_bit && fc_bit)
987 else if(fc_bit)
988 {
989 const and_exprt unsimplified{rlo_bit, op};
991 }
992 else
994}
995
997 const codet &op_code,
998 const symbolt &tia_element)
999{
1000 if(op_code.operands().empty())
1001 {
1003 return;
1004 }
1005 const symbol_exprt &sym{
1007 const exprt op{typecheck_identifier(tia_element, sym.get_identifier())};
1008
1009 // If inside of a bit string, create an 'or' expression with the operand and
1010 // the current contents of the rlo bit.
1011 if(fc_bit)
1012 {
1013 const or_exprt unsimplified{rlo_bit, op};
1015 or_bit = false;
1016 }
1017 else
1019}
1020
1022 const codet &op_code,
1023 const symbolt &tia_element)
1024{
1025 const symbol_exprt &sym{
1027 const exprt op{typecheck_identifier(tia_element, sym.get_identifier())};
1028 const not_exprt not_op{op};
1029
1030 // If inside of a bit string, create an 'or' expression with the operand and
1031 // the current contents of the rlo bit.
1032 if(fc_bit)
1033 {
1036 or_bit = false;
1037 }
1038 else
1040}
1041
1043 const codet &op_code,
1044 const symbolt &tia_element)
1045{
1046 const symbol_exprt &sym{
1048 const exprt op{typecheck_identifier(tia_element, sym.get_identifier())};
1049
1050 // If inside of a bit string, create an 'xor' expression with the operand and
1051 // the current contents of the rlo bit.
1052 if(fc_bit)
1053 {
1054 const xor_exprt unsimplified{rlo_bit, op};
1056 or_bit = false;
1057 }
1058 else
1060}
1061
1063 const codet &op_code,
1064 const symbolt &tia_element)
1065{
1066 const symbol_exprt &sym{
1068 const exprt op{typecheck_identifier(tia_element, sym.get_identifier())};
1069 const not_exprt not_op{op};
1070
1071 // If inside of a bit string, create an 'xor not' expression with the
1072 // operand and the current contents of the rlo bit.
1073 if(fc_bit)
1074 {
1077 or_bit = false;
1078 }
1079 else
1081}
1082
1084{
1085 if(fc_bit)
1086 {
1088 or_bit = true;
1089 }
1090 else
1091 return; // Instruction has no semantic influence.
1092}
1093
1095 const codet &op_code)
1096{
1097 // Set the rlo to true implicitly so that the value of the AND instruction
1098 // is being loaded in case of a new bit string.
1100}
1101
1103 const codet &op_code)
1104{
1105 // Set the rlo to true implicitly so that the value of the AND instruction
1106 // is being loaded in case of a new bit string.
1108}
1109
1111 const codet &op_code)
1112{
1113 // Set the rlo to false implicitly so that the value of the OR instruction
1114 // is being loaded in case of a new bit string.
1116}
1117
1119 const codet &op_code)
1120{
1121 // Set the rlo to false implicitly so that the value of the OR instruction
1122 // is being loaded in case of a new bit string.
1124}
1125
1127 const codet &op_code)
1128{
1129 // Set the rlo to false implicitly so that the value of the XOR instruction
1130 // is being loaded in case of a new bit string.
1132}
1133
1135 const codet &op_code)
1136{
1137 // Set the rlo to false implicitly so that the value of the XOR instruction
1138 // is being loaded in case of a new bit string.
1140}
1141
1143 const codet &op_code)
1144{
1146 if(nesting_stack.empty())
1147 {
1148 error() << "Wrong order of brackets (Right parenthesis is not preceded by "
1149 "nesting)"
1150 << eom;
1151 throw TYPECHECK_ERROR;
1152 }
1153 or_bit = nesting_stack.back().or_bit;
1154 fc_bit = true;
1155 const irep_idt &statement{nesting_stack.back().function_code.get_statement()};
1156 if(ID_statement_list_and_nested == statement)
1157 {
1158 if(or_bit)
1159 {
1160 const exprt op{rlo_bit};
1161 rlo_bit = nesting_stack.back().rlo_bit;
1163 }
1164 else
1165 rlo_bit = and_exprt{nesting_stack.back().rlo_bit, rlo_bit};
1166 }
1167 else if(ID_statement_list_and_not_nested == statement)
1168 {
1169 if(or_bit)
1170 {
1171 const not_exprt op{rlo_bit};
1172 rlo_bit = nesting_stack.back().rlo_bit;
1174 }
1175 else
1176 rlo_bit = and_exprt{nesting_stack.back().rlo_bit, not_exprt{rlo_bit}};
1177 }
1178 else if(ID_statement_list_or_nested == statement)
1179 {
1180 or_bit = false;
1181 rlo_bit = or_exprt{nesting_stack.back().rlo_bit, rlo_bit};
1182 }
1183 else if(ID_statement_list_or_not_nested == statement)
1184 {
1185 or_bit = false;
1186 rlo_bit = or_exprt{nesting_stack.back().rlo_bit, not_exprt{rlo_bit}};
1187 }
1188 else if(ID_statement_list_xor_nested == statement)
1189 {
1190 or_bit = false;
1191 rlo_bit = xor_exprt{nesting_stack.back().rlo_bit, rlo_bit};
1192 }
1193 else if(ID_statement_list_xor_not_nested == statement)
1194 {
1195 or_bit = false;
1196 rlo_bit = xor_exprt{nesting_stack.back().rlo_bit, not_exprt{rlo_bit}};
1197 }
1198 nesting_stack.pop_back();
1199}
1200
1202 const codet &op_code,
1204{
1206 const exprt lhs{typecheck_identifier(tia_element, op.get_identifier())};
1207
1208 if(lhs.type() != rlo_bit.type())
1209 {
1210 error() << "Types of assign do not match" << eom;
1211 throw TYPECHECK_ERROR;
1212 }
1213 const code_assignt assignment{lhs, rlo_bit};
1214 tia_element.value.add_to_operands(assignment);
1215 fc_bit = false;
1216 or_bit = false;
1217 // Set RLO to assigned operand in order to prevent false results if a symbol
1218 // that's implicitly part of the RLO was changed by the assignment.
1219 rlo_bit = lhs;
1220}
1221
1230
1239
1241 const codet &op_code,
1243{
1245 const irep_idt &identifier{op.get_identifier()};
1246
1248
1249 const exprt lhs{typecheck_identifier(tia_element, identifier)};
1250 const code_assignt assignment{lhs, true_exprt()};
1251 const code_ifthenelset ifthen{rlo_bit, assignment};
1252 tia_element.value.add_to_operands(ifthen);
1253 fc_bit = false;
1254 or_bit = false;
1255}
1256
1258 const codet &op_code,
1260{
1262 const irep_idt &identifier{op.get_identifier()};
1263
1265
1266 const exprt lhs{typecheck_identifier(tia_element, identifier)};
1267 const code_assignt assignment{lhs, false_exprt()};
1268 const code_ifthenelset ifthen{rlo_bit, assignment};
1269 tia_element.value.add_to_operands(ifthen);
1270 fc_bit = false;
1271 or_bit = false;
1272}
1273
1275 const codet &op_code,
1277{
1279 const irep_idt &identifier{op.get_identifier()};
1280 if(symbol_table.has_symbol(identifier))
1282 else if(identifier == CPROVER_ASSUME)
1284 else if(identifier == CPROVER_ASSERT)
1286 else
1287 {
1288 error() << "Called function could not be found" << eom;
1289 throw TYPECHECK_ERROR;
1290 }
1291 fc_bit = false;
1292 or_bit = false;
1293}
1294
1296 const codet &op_code,
1298{
1299 const symbol_exprt &label{
1301 typecheck_label_reference(label.get_identifier(), false);
1302
1304 code_gotot unconditional{label.get_identifier()};
1305 tia_element.value.add_to_operands(unconditional);
1306}
1307
1309 const codet &op_code,
1311{
1312 const symbol_exprt &label{
1314 typecheck_label_reference(label.get_identifier(), true);
1315
1317 code_gotot jump{label.get_identifier()};
1319 tia_element.value.add_to_operands(conditional);
1320
1321 fc_bit = false;
1322 or_bit = false;
1323 rlo_bit = true_exprt{};
1324}
1325
1327 const codet &op_code,
1329{
1330 const symbol_exprt &label{
1332 typecheck_label_reference(label.get_identifier(), true);
1333
1335 code_gotot jump{label.get_identifier()};
1337 tia_element.value.add_to_operands(not_conditional);
1338
1339 fc_bit = false;
1340 or_bit = false;
1341 rlo_bit = true_exprt{};
1342}
1343
1345 const codet &op_code)
1346{
1348 const exprt &accu1{accumulator.back()};
1349 const exprt &accu2{accumulator.at(accumulator.size() - 2)};
1350
1351 // Are both operands integers?
1352 const signedbv_typet *const accu_type1 =
1354 const signedbv_typet *const accu_type2 =
1356 if(
1357 !accu_type1 || !accu_type2 || accu_type1->get_width() != STL_INT_WIDTH ||
1358 accu_type2->get_width() != STL_INT_WIDTH)
1359 {
1360 error() << "Operands of integer addition are no integers" << eom;
1361 throw TYPECHECK_ERROR;
1362 }
1363}
1364
1366 const codet &op_code)
1367{
1369 const exprt &accu1{accumulator.back()};
1370 const exprt &accu2{accumulator.at(accumulator.size() - 2)};
1371
1372 // Are both operands double integers?
1373 const signedbv_typet *const accu_type1 =
1375 const signedbv_typet *const accu_type2 =
1377 if(
1378 !accu_type1 || !accu_type2 || accu_type1->get_width() != STL_DINT_WIDTH ||
1379 accu_type2->get_width() != STL_DINT_WIDTH)
1380 {
1381 error() << "Operands of double integer addition are no double integers"
1382 << eom;
1383 throw TYPECHECK_ERROR;
1384 }
1385}
1386
1388 const codet &op_code)
1389{
1391 const exprt &accu1{accumulator.back()};
1392 const exprt &accu2{accumulator.at(accumulator.size() - 2)};
1393
1394 // Are both operands real types?
1395 if(!(can_cast_type<floatbv_typet>(accu1.type()) &&
1397 {
1398 error() << "Operands of Real addition do not have the type Real" << eom;
1399 throw TYPECHECK_ERROR;
1400 }
1401}
1402
1404 const irep_idt &comparison)
1405{
1406 const exprt &accu1{accumulator.back()};
1407 const exprt &accu2{accumulator.at(accumulator.size() - 2)};
1408 // STL behaviour: ACCU2 is lhs, ACCU1 is rhs.
1409 const binary_relation_exprt operation{accu2, comparison, accu1};
1410 rlo_bit = operation;
1411}
1412
1414 const irep_idt &label,
1415 bool sets_fc_false)
1416{
1417 // If the label is already present in the list, check if it matches the
1418 // criteria.
1419 auto label_it = stl_labels.find(label);
1420 if(label_it != end(stl_labels))
1421 {
1422 if(!label_it->second.jumps_permitted)
1423 {
1424 error() << "Not allowed to jump to label " << id2string(label_it->first)
1425 << eom;
1426 throw TYPECHECK_ERROR;
1427 }
1428
1429 if(label_it->second.fc_false_required && !sets_fc_false)
1430 {
1431 error() << "Jump to label " << id2string(label_it->first)
1432 << " can not be unconditional" << eom;
1433 throw TYPECHECK_ERROR;
1434 }
1435
1436 if(label_it->second.nesting_depth != nesting_stack.size())
1437 {
1438 error() << "Jump to label " << id2string(label_it->first)
1439 << " violates brace scope" << eom;
1440 throw TYPECHECK_ERROR;
1441 }
1442 }
1443 else // If it was not encountered yet, create a new reference entry.
1444 {
1445 stl_jump_locationt location{nesting_stack.size(), sets_fc_false};
1446 auto reference_it = label_references.find(label);
1447 if(reference_it == end(label_references))
1448 {
1449 std::vector<stl_jump_locationt> locations;
1450 locations.push_back(location);
1451 label_references.emplace(label, locations);
1452 }
1453 else
1454 reference_it->second.push_back(location);
1455 }
1456}
1457
1458const symbol_exprt &
1460 const codet &op_code)
1461{
1462 const symbol_exprt *const symbol =
1464
1465 if(symbol)
1466 return *symbol;
1467
1468 error() << "Instruction is not followed by symbol" << eom;
1469 throw TYPECHECK_ERROR;
1470}
1471
1473 const codet &op_code)
1474{
1475 if(op_code.operands().size() > 0)
1476 {
1477 error() << "Instruction is followed by operand" << eom;
1478 throw TYPECHECK_ERROR;
1479 }
1480}
1481
1483 const codet &op_code)
1484{
1486 if(accumulator.size() < 2)
1487 {
1488 error() << "Not enough operands in the accumulator" << eom;
1489 throw TYPECHECK_ERROR;
1490 }
1491}
1492
1494 const codet &op_code,
1495 const exprt &rlo_value)
1496{
1498 // If inside of a bit string use the value of the rlo. If this is the first
1499 // expression of a bit string, load the value of the nested operation by
1500 // implicitly setting the rlo to the specified value.
1501 if(!fc_bit)
1504 nesting_stack.push_back(stack_entry);
1505 fc_bit = false;
1506 or_bit = false;
1507}
1508
1510 const codet &op_code,
1511 const symbolt &tia_element,
1512 bool negate)
1513{
1514 const symbol_exprt &sym{
1516 const exprt op{typecheck_identifier(tia_element, sym.get_identifier())};
1517 const not_exprt not_op{op};
1518 return negate ? not_op : op;
1519}
1520
1522 const symbolt &tia_element,
1523 const irep_idt &identifier)
1524{
1525 const code_typet &element_type{to_code_type(tia_element.type)};
1526
1527 // Check for temporary variables.
1529 id2string(tia_element.name) + "::" + id2string(identifier)))
1530 {
1532 id2string(tia_element.name) + "::" + id2string(identifier))};
1533 return sym.symbol_expr();
1534 }
1535
1536 // Check for global tags.
1537 if(symbol_table.has_symbol(identifier))
1538 return symbol_table.lookup_ref(identifier).symbol_expr();
1539
1540 if(
1541 element_type.get(ID_statement_list_type) ==
1543 {
1544 // Check for variables inside of the function block interface.
1547 const symbol_exprt db_expr = data_block.symbol_expr();
1549 to_type_with_subtype(db_expr.type()).subtype());
1550 if(!db_type)
1552 for(const struct_union_typet::componentt &member : db_type->components())
1553 {
1554 if(member.get_name() == identifier)
1555 {
1557 const member_exprt val{deref_db, member.get_name(), member.type()};
1558 return val;
1559 }
1560 }
1561 }
1562 else if(
1564 {
1565 // Check for variables inside of the function interface.
1566 for(const auto &member : element_type.parameters())
1567 {
1568 if(member.get_base_name() == identifier)
1569 {
1570 const symbolt &par{
1571 symbol_table.get_writeable_ref(member.get_identifier())};
1572 return par.symbol_expr();
1573 }
1574 }
1575 }
1576 else
1577 UNREACHABLE; // Variable declarations should only be checked for FCs or FBs
1578
1579 error() << "Identifier could not be found in project" << eom;
1580 throw TYPECHECK_ERROR;
1581}
1582
1584 const codet &op_code,
1586{
1587 if(
1588 const auto assignment =
1590 {
1591 const code_assertt assertion{
1593 tia_element.value.add_to_operands(assertion);
1594 }
1595 else
1596 {
1597 error() << "No assignment found for assertion" << eom;
1598 throw TYPECHECK_ERROR;
1599 }
1600}
1601
1603 const codet &op_code,
1605{
1606 if(
1607 const auto assignment =
1609 {
1610 const code_assumet assumption{
1612 tia_element.value.add_to_operands(assumption);
1613 }
1614 else
1615 {
1616 error() << "No assignment found for assumption" << eom;
1617 throw TYPECHECK_ERROR;
1618 }
1619}
1620
1622 const codet &op_code,
1624{
1626 const symbolt &called_function{
1627 symbol_table.lookup_ref(call_operand.get_identifier())};
1628 const code_typet &called_type{to_code_type(called_function.type)};
1629 // Is it a STL function or STL function block?
1630 if(
1635 else
1636 {
1637 error() << "Tried to call element that is no function or function block"
1638 << eom;
1639 throw TYPECHECK_ERROR;
1640 }
1641}
1642
1644 const codet &op_code,
1646{
1649 symbol_table.lookup_ref(call_operand.get_identifier())};
1652
1653 // Check if function name is followed by data block.
1655 {
1656 error() << "Function calls should not address instance data blocks" << eom;
1657 throw TYPECHECK_ERROR;
1658 }
1659
1660 // Check if function interface matches the call and fill argument list.
1661 const code_typet::parameterst &params{called_type.parameters()};
1663 std::vector<code_frontend_assignt> assignments;
1664 for(const auto &expr : op_code.operands())
1665 {
1666 if(auto assign = expr_try_dynamic_cast<code_frontend_assignt>(expr))
1667 assignments.push_back(*assign);
1668 }
1669
1670 for(const code_typet::parametert &param : params)
1671 args.emplace_back(
1673
1674 // Check the return value if present.
1675 if(called_type.return_type().is_nil())
1676 tia_element.value.add_to_operands(
1678 else
1679 {
1680 const exprt lhs{typecheck_return_value_assignment(
1681 assignments, called_type.return_type(), tia_element)};
1682 tia_element.value.add_to_operands(
1684 }
1685}
1686
1688 const codet &op_code,
1690{
1691 // TODO: Implement support for function block calls.
1692 // Needs code statements which assign the parameters to the instance data
1693 // block, call the function and write the result back to the parameters
1694 // afterwards.
1695 error() << "Calls to function blocks are not supported yet" << eom;
1696 throw TYPECHECK_ERROR;
1697}
1698
1700 const std::vector<code_frontend_assignt> &assignments,
1702 const symbolt &tia_element)
1703{
1704 const irep_idt &param_name = param.get_base_name();
1705 const typet &param_type = param.type();
1706 for(const auto &assignment : assignments)
1707 {
1708 const symbol_exprt &lhs{to_symbol_expr(assignment.lhs())};
1709 if(param_name == lhs.get_identifier())
1710 {
1713
1714 if(param_type == assigned_variable.type())
1715 return assigned_variable;
1716 else
1717 {
1718 error() << "Types of parameter assignment do not match: "
1719 << param.type().id() << " != " << assigned_variable.type().id()
1720 << eom;
1721 throw TYPECHECK_ERROR;
1722 }
1723 }
1724 }
1725 error() << "No assignment found for function parameter "
1726 << param.get_identifier() << eom;
1727 throw TYPECHECK_ERROR;
1728}
1729
1731 const symbolt &tia_element,
1732 const exprt &rhs)
1733{
1735 const symbol_exprt *const symbol_rhs =
1737 if(symbol_rhs)
1739 typecheck_identifier(tia_element, symbol_rhs->get_identifier());
1740 else // constant_exprt.
1741 assigned_operand = rhs;
1742 return assigned_operand;
1743}
1744
1746 const std::vector<code_frontend_assignt> &assignments,
1747 const typet &return_type,
1748 const symbolt &tia_element)
1749{
1750 for(const auto &assignment : assignments)
1751 {
1752 const symbol_exprt &lhs{to_symbol_expr(assignment.lhs())};
1753 if(ID_statement_list_return_value_id == lhs.get_identifier())
1754 {
1755 const symbol_exprt &rhs{to_symbol_expr(assignment.rhs())};
1757 typecheck_identifier(tia_element, rhs.get_identifier())};
1758 if(return_type == assigned_variable.type())
1759 return assigned_variable;
1760 else
1761 {
1762 error() << "Types of return value assignment do not match: "
1763 << return_type.id() << " != " << assigned_variable.type().id()
1764 << eom;
1765 throw TYPECHECK_ERROR;
1766 }
1767 }
1768 }
1769 error() << "No assignment found for function return value" << eom;
1770 throw TYPECHECK_ERROR;
1771}
1772
1774{
1776
1778 or_wrapper.op1();
1779 else if(can_cast_expr<and_exprt>(or_wrapper.op1()))
1780 {
1782 and_op.add_to_operands(op);
1783 or_wrapper.op1() = and_op;
1784 }
1785 else
1786 {
1787 and_exprt and_op{or_wrapper.op1(), op};
1788 or_wrapper.op1() = and_op;
1789 }
1791}
1792
1794{
1795 fc_bit = true;
1796 or_bit = false;
1797 rlo_bit = op;
1798}
1799
1801{
1802 rlo_bit = true_exprt{};
1803 fc_bit = false;
1804 or_bit = false;
1806}
1807
1814
virtual void clear()
Reset the abstract state.
Definition ai.h:265
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
Boolean AND.
Definition std_expr.h:2125
A base class for relations, i.e., binary predicates whose two operands have the same type.
Definition std_expr.h:762
A non-fatal assertion, which checks a condition then permits execution to continue.
Definition std_code.h:270
A goto_instruction_codet representing an assignment in the program.
An assumption, which must hold in subsequent code.
Definition std_code.h:217
A codet representing sequential composition of program statements.
Definition std_code.h:130
A goto_instruction_codet representing the declaration of a local variable.
goto_instruction_codet representation of a function call statement.
codet representation of a goto statement.
Definition std_code.h:841
codet representation of an if-then-else statement.
Definition std_code.h:460
codet representation of a label for branch targets.
Definition std_code.h:959
const irep_idt & get_label() const
Definition std_code.h:967
codet & code()
Definition std_code.h:977
A codet representing a skip statement.
Definition std_code.h:322
Base type of functions.
Definition std_types.h:583
std::vector< parametert > parameterst
Definition std_types.h:586
Data structure for representing an arbitrary statement in a program.
const irep_idt & get_statement() const
Operator to dereference a pointer.
Division.
Definition std_expr.h:1157
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition dstring.h:38
The empty type.
Definition std_types.h:51
Base class for all expressions.
Definition expr.h:56
typet & type()
Return the type of the expression.
Definition expr.h:84
The Boolean constant false.
Definition std_expr.h:3199
const irep_idt & id() const
Definition irep.h:388
Extract member of struct or union.
Definition std_expr.h:2971
message_handlert * message_handler
Definition message.h:431
mstreamt & error() const
Definition message.h:391
static eomt eom
Definition message.h:289
Binary minus.
Definition std_expr.h:1061
Binary multiplication Associativity is not specified.
Definition std_expr.h:1107
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition namespace.h:94
Boolean negation.
Definition std_expr.h:2454
Boolean OR.
Definition std_expr.h:2270
Symbol table entry of function parameterThis is a symbol generated as part of type checking.
Definition symbol.h:179
The plus expression Associativity is not specified.
Definition std_expr.h:1002
The pointer type These are both 'bitvector_typet' (they have a width) and 'type_with_subtypet' (they ...
Fixed-width bit-vector with two's complement interpretation.
Intermediate representation of a parsed Statement List file before converting it into a goto program.
std::list< var_declarationt > var_declarationst
Class for encapsulating the current state of the type check.
void typecheck_accumulator_compare_instruction(const irep_idt &comparison)
Performs a typecheck on an STL comparison instruction.
void typecheck_statement_list_accu_real_div(const codet &op_code)
Performs a typecheck on a STL accumulator divide instruction for reals.
struct_typet create_instance_data_block_type(const statement_list_parse_treet::function_blockt &function_block)
Creates a data block type for the given function block.
const symbol_exprt & typecheck_instruction_with_non_const_operand(const codet &op_code)
Performs a typecheck on a STL instruction with an additional operand that should be no constant.
void typecheck_statement_list_accu_real_lte(const codet &op_code)
Performs a typecheck on a STL accumulator less than or equal comparison instruction for integers.
const statement_list_parse_treet & parse_tree
Parse tree which is used to fill the symbol table.
void typecheck_statement_list_nesting_closed(const codet &op_code)
Performs a typecheck on a Nesting Closed instruction.
void typecheck_statement_list_accu_real_sub(const codet &op_code)
Performs a typecheck on a STL accumulator subtract instruction for reals.
void typecheck_statement_list_networks(const statement_list_parse_treet::tia_modulet &tia_module, symbolt &tia_symbol)
Performs a typecheck on the networks of a TIA module and saves the result to the given symbol.
void clear_module_state()
Modifies the state of the typecheck to resemble the beginning of a new module.
void typecheck_statement_list_accu_int_add(const codet &op_code)
Performs a typecheck on a STL accumulator add instruction for integers.
void typecheck_jump_locations(const code_labelt &label, const stl_label_locationt &location)
Performs a typecheck on all references for the given label.
void typecheck_label_reference(const irep_idt &label, bool sets_fc_false)
Checks if the given label is already present and compares the current state with it.
void typecheck_statement_list_clr_rlo(const codet &op_code)
Performs a typecheck on a STL 'CLR' instruction and modifies the RLO, OR and FC bit.
statement_list_typecheckt(const statement_list_parse_treet &parse_tree, symbol_table_baset &symbol_table, const std::string &module, message_handlert &message_handler)
Creates a new instance of statement_list_typecheckt.
symbol_table_baset & symbol_table
Reference to the symbol table that should be filled during the typecheck.
const irep_idt std::vector< exprt > accumulator
Name of the module this typecheck belongs to.
void typecheck_statement_list_transfer(const codet &op_code, symbolt &tia_element)
Performs a typecheck on a STL transfer instruction and saves the result to the given symbol.
void typecheck_function_declaration(const statement_list_parse_treet::functiont &function)
Performs a typecheck on a function declaration inside of the parse tree and adds symbols for it and i...
void typecheck_statement_list_accu_dint_gte(const codet &op_code)
Performs a typecheck on a STL accumulator greater than or equal comparison instruction for double int...
void typecheck_statement_list_and_not(const codet &op_code, const symbolt &tia_element)
Performs a typecheck on a STL boolean And Not instruction.
void add_to_or_rlo_wrapper(const exprt &op)
Adds the given expression to the operands of the Or expression that is saved in the RLO.
void typecheck_function_block_var_decls(const statement_list_parse_treet::var_declarationst &var_decls, struct_union_typet::componentst &components, const irep_idt &var_property)
Performs a typecheck on a variable declaration list and saves the result to the given component eleme...
exprt typecheck_return_value_assignment(const std::vector< code_frontend_assignt > &assignments, const typet &return_type, const symbolt &tia_element)
Checks if there is a return value assignment inside of the assignment list of a function call and ret...
exprt typecheck_function_call_argument_rhs(const symbolt &tia_element, const exprt &rhs)
Checks if the given assigned expression is a variable or a constant and returns the typechecked versi...
void typecheck() override
Performs the actual typecheck by using the parse tree with which the object was initialized and modif...
void typecheck_statement_list_accu_dint_mul(const codet &op_code)
Performs a typecheck on a STL accumulator divide instruction for double integers.
void typecheck_statement_list_accu_int_gte(const codet &op_code)
Performs a typecheck on a STL accumulator greater than or equal comparison instruction for integers.
void typecheck_statement_list_nested_xor(const codet &op_code)
Performs a typecheck on a nested XOR instruction.
void typecheck_statement_list_accu_int_mul(const codet &op_code)
Performs a typecheck on a STL accumulator multiply instruction for integers.
void typecheck_statement_list_accu_int_lt(const codet &op_code)
Performs a typecheck on a STL accumulator less than comparison instruction for integers.
void typecheck_statement_list_nested_or_not(const codet &op_code)
Performs a typecheck on a nested Or Not instruction.
void typecheck_statement_list_set_rlo(const codet &op_code)
Performs a typecheck on a STL 'SET' instruction and modifies the RLO, OR and FC bit.
void typecheck_statement_list_accu_dint_add(const codet &op_code)
Performs a typecheck on a STL accumulator add instruction for double integers.
void typecheck_statement_list_accu_real_gt(const codet &op_code)
Performs a typecheck on a STL accumulator greater than comparison instruction for double integers.
void typecheck_statement_list_nested_xor_not(const codet &op_code)
Performs a typecheck on a nested XOR Not instruction.
void clear_network_state()
Modifies the state of the typecheck to resemble the beginning of a new network.
void typecheck_statement_list_accu_real_eq(const codet &op_code)
Performs a typecheck on a STL accumulator equality comparison instruction for double integers.
void typecheck_statement_list_xor(const codet &op_code, const symbolt &tia_element)
Performs a typecheck on a STL boolean XOR instruction.
exprt typecheck_identifier(const symbolt &tia_element, const irep_idt &identifier)
Performs a typecheck on the given identifier and returns its symbol.
void typecheck_tag_list()
Performs a typecheck on the tag list of the referenced parse tree and adds symbols for its contents t...
void typecheck_statement_list_xor_not(const codet &op_code, const symbolt &tia_element)
Performs a typecheck on a STL boolean XOR Not instruction.
void typecheck_called_tia_element(const codet &op_code, symbolt &tia_element)
Performs a typecheck on a call of a TIA element and saves the result to the given symbol.
void typecheck_statement_list_jump_unconditional(const codet &op_code, symbolt &tia_element)
Performs a typecheck on an unconditional jump instruction (JU) and adds the jump to the given symbol.
void typecheck_code(const codet &instruction, symbolt &tia_element)
Performs a typecheck for the specified instruction in code form.
void typecheck_CPROVER_assume(const codet &op_code, symbolt &tia_element)
Performs a typecheck on a call of __CPOVER_ASSUME and saves the result to the given symbol.
void typecheck_statement_list_accu_real_add(const codet &op_code)
Performs a typecheck on a STL accumulator add instruction for reals.
label_referencest label_references
Holds associations between labels and jumps that are referencing it.
exprt rlo_bit
Result of Logic Operation (Part of the TIA status word).
exprt typecheck_simple_boolean_instruction_operand(const codet &op_code, const symbolt &tia_element, bool negate)
Performs a typecheck on the operand of a not nested boolean instruction and returns the result.
bool or_bit
Or (Part of the TIA status word).
void typecheck_statement_list_accu_dint_lt(const codet &op_code)
Performs a typecheck on a STL accumulator less than comparison instruction for double integers.
stl_labelst stl_labels
Data structure that contains data about the labels of the current module.
void typecheck_function_block_declaration(const statement_list_parse_treet::function_blockt &function_block)
Performs a typecheck on a function block declaration inside of the parse tree and adds symbols for it...
void typecheck_statement_list_load(const codet &op_code, const symbolt &tia_element)
Performs a typecheck on a STL load instruction.
void typecheck_statement_list_accu_int_div(const codet &op_code)
Performs a typecheck on a STL accumulator divide instruction for integers.
stl_label_locationt typecheck_label_location(const code_labelt &label)
Converts the properties of the current typecheck state to a label location.
void typecheck_statement_list_accu_int_neq(const codet &op_code)
Performs a typecheck on a STL accumulator inequality comparison instruction for integers.
void typecheck_statement_list_or(const codet &op_code, const symbolt &tia_element)
Performs a typecheck on a STL boolean Or instruction.
void typecheck_statement_list_accu_int_arith(const codet &op_code)
Performs a typecheck on a STL Accumulator instruction for integers.
void typecheck_statement_list_and(const codet &op_code, const symbolt &tia_element)
Performs a typecheck on a STL boolean And instruction.
void typecheck_statement_list_accu_real_lt(const codet &op_code)
Performs a typecheck on a STL accumulator less than comparison instruction for double integers.
void typecheck_instruction_without_operand(const codet &op_code)
Performs a typecheck on an operand-less STL instruction.
void typecheck_label(const codet &instruction, symbolt &tia_element)
Performs a typecheck for the given label in code form.
bool fc_bit
First Check (Part of the TIA status word).
void typecheck_statement_list_jump_conditional(const codet &op_code, symbolt &tia_element)
Performs a typecheck on a conditional jump instruction (JC) and adds it to the given symbol.
void typecheck_statement_list_jump_conditional_not(const codet &op_code, symbolt &tia_element)
Performs a typecheck on a inverted conditional jump instruction (JCN) and adds it to the given symbol...
void typecheck_statement_list_or_not(const codet &op_code, const symbolt &tia_element)
Performs a typecheck on a STL boolean Or Not instruction.
void typecheck_label_references()
Checks if all jumps reference labels that exist.
void typecheck_binary_accumulator_instruction(const codet &op_code)
Performs a typecheck on a STL instruction that uses two accumulator entries.
void initialize_bit_expression(const exprt &op)
Initializes the FC, RLO an OR bits for the scenario when a new boolean instruction was encontered.
void typecheck_statement_list_call(const codet &op_code, symbolt &tia_element)
Performs a typecheck on a STL Call instruction and saves the result to the given symbol.
void typecheck_statement_list_nested_or(const codet &op_code)
Performs a typecheck on a nested Or instruction.
void typecheck_statement_list_accu_dint_neq(const codet &op_code)
Performs a typecheck on a STL accumulator inequality comparison instruction for double integers.
void typecheck_statement_list_accu_real_mul(const codet &op_code)
Performs a typecheck on a STL accumulator multiply instruction for reals.
exprt typecheck_function_call_arguments(const std::vector< code_frontend_assignt > &assignments, const code_typet::parametert &param, const symbolt &tia_element)
Checks if the given parameter is inside of the assignment list of a function call and returns the exp...
void typecheck_temp_var_decls(const statement_list_parse_treet::tia_modulet &tia_module, symbolt &tia_symbol)
Performs a typecheck on the temp variables of a TIA module and saves the result to the given symbol v...
void typecheck_statement_list_accu_dint_arith(const codet &op_code)
Performs a typecheck on a STL Accumulator instruction for double integers.
void typecheck_CPROVER_assert(const codet &op_code, symbolt &tia_element)
Performs a typecheck on a call of __CPOVER_ASSERT and saves the result to the given symbol.
void typecheck_statement_list_nested_and_not(const codet &op_code)
Performs a typecheck on a nested And Not instruction.
void typecheck_statement_list_accu_int_gt(const codet &op_code)
Performs a typecheck on a STL accumulator greater than comparison instruction for integers.
void typecheck_statement_list_accu_int_sub(const codet &op_code)
Performs a typecheck on a STL accumulator subtract instruction for integers.
void typecheck_function_var_decls(const statement_list_parse_treet::var_declarationst &var_decls, code_typet::parameterst &params, const irep_idt &function_name, const irep_idt &var_property)
Performs a typecheck on a variable declaration list and saves the result to the given component eleme...
void typecheck_statement_list_instruction(const statement_list_parse_treet::instructiont &instruction, symbolt &tia_element)
Performs a typecheck on a single instruction and saves the result to the given symbol body if necessa...
void typecheck_statement_list_accu_dint_eq(const codet &op_code)
Performs a typecheck on a STL accumulator equality comparison instruction for double integers.
void typecheck_statement_list_accu_real_arith(const codet &op_code)
Performs a typecheck on a STL Accumulator instruction for reals.
void typecheck_statement_list_accu_real_gte(const codet &op_code)
Performs a typecheck on a STL accumulator greater than or equal comparison instruction for double int...
void typecheck_statement_list_reset(const codet &op_code, symbolt &tia_element)
Performs a typecheck on a STL 'R' instruction and saves the result to the given symbol.
void typecheck_statement_list_accu_real_neq(const codet &op_code)
Performs a typecheck on a STL accumulator inequality comparison instruction for double integers.
nesting_stackt nesting_stack
Representation of the nesting stack.
void typecheck_statement_list_not(const codet &op_code)
Performs a typecheck on a STL boolean NOT instruction.
void typecheck_statement_list_accu_dint_lte(const codet &op_code)
Performs a typecheck on a STL accumulator less than or equal comparison instruction for double intege...
void typecheck_called_function(const codet &op_code, symbolt &tia_element)
Performs a typecheck on a call of a TIA function and saves the result to the given symbol.
void typecheck_statement_list_accu_int_lte(const codet &op_code)
Performs a typecheck on a STL accumulator less than or equal comparison instruction for integers.
void typecheck_statement_list_accu_dint_gt(const codet &op_code)
Performs a typecheck on a STL accumulator greater than comparison instruction for double integers.
void typecheck_statement_list_assign(const codet &op_code, symbolt &tia_element)
Performs a typecheck on a STL assign instruction and saves the result to the given symbol.
void typecheck_statement_list_accu_int_eq(const codet &op_code)
Performs a typecheck on a STL accumulator equality comparison instruction for integers.
void typecheck_statement_list_accu_dint_sub(const codet &op_code)
Performs a typecheck on a STL accumulator subtract instruction for double integers.
void typecheck_called_function_block(const codet &op_code, symbolt &tia_element)
Performs a typecheck on a call of a TIA function block and saves the result to the given symbol.
void typecheck_statement_list_accu_dint_div(const codet &op_code)
Performs a typecheck on a STL accumulator divide instruction for double integers.
void add_temp_rlo()
Adds a symbol for the RLO to the symbol table.
void typecheck_statement_list_nested_and(const codet &op_code)
Performs a typecheck on a nested And instruction.
void save_rlo_state(symbolt &tia_element)
Saves the current RLO bit to a temporary variable to prevent false overrides when modifying boolean v...
void typecheck_nested_boolean_instruction(const codet &op_code, const exprt &rlo_value)
Performs a typecheck on a STL instruction that initializes a new boolean nesting.
void typecheck_statement_list_set(const codet &op_code, symbolt &tia_element)
Performs a typecheck on a STL 'S' instruction and saves the result to the given symbol.
void typecheck_statement_list_and_before_or()
Performs a typecheck on a STL operand-less Or instruction.
Structure type, corresponds to C style structs.
Definition std_types.h:231
std::vector< componentt > componentst
Definition std_types.h:140
Expression to hold a symbol (variable)
Definition std_expr.h:131
const irep_idt & get_identifier() const
Definition std_expr.h:160
The symbol table base class interface.
symbolt & get_writeable_ref(const irep_idt &name)
Find a symbol in the symbol table for read-write access.
bool has_symbol(const irep_idt &name) const
Check whether a symbol exists in the symbol table.
bool add(const symbolt &symbol)
Add a new symbol to the symbol table.
const symbolt & lookup_ref(const irep_idt &name) const
Find a symbol in the symbol table for read-only access.
Symbol table entry.
Definition symbol.h:28
The Boolean constant true.
Definition std_expr.h:3190
Symbol table entry describing a data typeThis is a symbol generated as part of type checking.
Definition symbol.h:139
The type of an expression, extends irept.
Definition type.h:29
Boolean XOR.
Definition std_expr.h:2370
const std::string & id2string(const irep_idt &d)
Definition irep.h:44
API to expression classes for Pointers.
exprt simplify_expr(exprt src, const namespacet &ns)
#define UNREACHABLE
This should be used to mark dead code.
Definition invariant.h:525
bool statement_list_typecheck(const statement_list_parse_treet &parse_tree, symbol_table_baset &symbol_table, const std::string &module, message_handlert &message_handler)
Create a new statement_list_typecheckt object and perform a type check to fill the symbol table.
#define CPROVER_ASSERT
Name of the CBMC assert function.
#define CPROVER_TEMP_RLO
Name of the RLO symbol used in some operations.
static code_typet::parametert create_data_block_parameter(const struct_typet &data_block_type, const irep_idt &function_block_name)
Creates the artificial data block parameter with a generic name and the specified type.
#define DATA_BLOCK_PARAMETER_NAME
Artificial name for the data block interface of a function block.
#define DATA_BLOCK_TYPE_POSTFIX
Postfix for the type of a data block.
#define STATEMENT_LIST_PTR_WIDTH
Size of pointers in Siemens TIA.
static const std::vector< irep_idt > logic_sequence_terminators
#define TYPECHECK_ERROR
#define CPROVER_ASSUME
Name of the CBMC assume function.
static const std::vector< irep_idt > logic_sequence_initializers
Statement List Language Type Checking.
bool_typet get_bool_type()
Creates a new type that resembles the 'Bool' type of the Siemens PLC languages.
Statement List Type Helper.
#define STL_INT_WIDTH
#define STL_DINT_WIDTH
const code_labelt & to_code_label(const codet &code)
Definition std_code.h:1004
auto component(T &struct_expr, const irep_idt &name, const namespacet &ns) -> decltype(struct_expr.op0())
Definition std_expr.cpp:97
const and_exprt & to_and_expr(const exprt &expr)
Cast an exprt to a and_exprt.
Definition std_expr.h:2172
const or_exprt & to_or_expr(const exprt &expr)
Cast an exprt to a or_exprt.
Definition std_expr.h:2317
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition std_expr.h:272
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition std_types.h:788
Structure for a simple function block in Statement List.
Structure for a simple function in Statement List.
const typet return_type
FC-exclusive return type.
Represents a regular Statement List instruction which consists out of one or more codet tokens.
std::vector< codet > tokens
Data structure for all tokens of the instruction.
Base element of all modules in the Totally Integrated Automation (TIA) portal by Siemens.
var_declarationst var_input
Input variable declarations.
var_declarationst var_inout
Inout variable declarations.
var_declarationst var_output
Output variable declarations.
Struct for a single variable declaration in Statement List.
Every time branching occurs inside of a boolean expression string in STL, the current value of the RL...
nesting_stack_entryt(exprt rlo_bit, bool or_bit, codet function_code)
Holds information about the properties of a jump instruction.
stl_jump_locationt(size_t nesting_depth, bool sets_fc_false)
Constructs a new location with the specified properties.
Holds information about the instruction and the nesting depth to which a label points.
const bool jumps_permitted
States if jumps to this location are permitted or if the location is invalid.
stl_label_locationt(size_t nesting_depth, bool jumps_permitted, bool fc_false_required)
Constructs a new location with the specified properties.
const bool fc_false_required
States if jump instructions to this location need to set the /FC bit to false.
Author: Diffblue Ltd.
const type_with_subtypet & to_type_with_subtype(const typet &type)
Definition type.h:208