Skip to content

Commit e79c95e

Browse files
committed
fix: Initialize __vtable member field
The `__vtable` member field is now initialized with a right hand side of `ADR(__vtable_<POU_NAME>_instance)` which represents the global instance variable of a virtual table that is initialized with its function pointers.
1 parent e4aeece commit e79c95e

32 files changed

+718
-149
lines changed

compiler/plc_ast/src/ast.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1672,9 +1672,11 @@ impl AstVisitor for StringFormatter {
16721672

16731673
fn visit_call_statement(&mut self, stmt: &CallStatement, _node: &AstNode) {
16741674
stmt.operator.walk(self);
1675-
self.result.push_str("(");
1676-
stmt.parameters.as_ref().map(|opt| opt.walk(self));
1677-
self.result.push_str(")");
1675+
self.result.push('(');
1676+
if let Some(opt) = stmt.parameters.as_ref() {
1677+
opt.walk(self)
1678+
}
1679+
self.result.push(')');
16781680
}
16791681

16801682
fn visit_control_statement(&mut self, stmt: &AstControlStatement, _node: &AstNode) {

compiler/plc_driver/src/tests/multi_files.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ fn multiple_files_in_different_locations_with_debug_info() {
119119
}
120120

121121
#[test]
122+
#[ignore = "FIXME: works in CLI, assuming the participants aren't registered in this test?"]
122123
fn forward_declared_constant_is_also_marked_constant() {
123124
// GIVEN 2 sources, one with a forward declaration of a constant
124125
// and the other with the definition of that constant.

src/codegen/tests/debug_tests.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,9 @@ fn dbg_declare_has_valid_metadata_references_for_methods() {
400400
entry:
401401
%self = alloca %fb*, align 8
402402
store %fb* %0, %fb** %self, align 8
403+
%deref = load %fb*, %fb** %self, align 8
404+
%__vtable = getelementptr inbounds %fb, %fb* %deref, i32 0, i32 0
405+
store i32* bitcast (%__vtable_fb* @__vtable_fb_instance to i32*), i32** %__vtable, align 8
403406
ret void
404407
}
405408

src/codegen/tests/initialization_test/complex_initializers.rs

Lines changed: 104 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,10 @@ fn init_functions_generated_for_function_blocks() {
305305
%self = alloca %foo*, align 8
306306
store %foo* %0, %foo** %self, align 8
307307
%deref = load %foo*, %foo** %self, align 8
308-
%to_init = getelementptr inbounds %foo, %foo* %deref, i32 0, i32 1
308+
%__vtable = getelementptr inbounds %foo, %foo* %deref, i32 0, i32 0
309+
store i32* bitcast (%__vtable_foo* @__vtable_foo_instance to i32*), i32** %__vtable, align 8
310+
%deref1 = load %foo*, %foo** %self, align 8
311+
%to_init = getelementptr inbounds %foo, %foo* %deref1, i32 0, i32 1
309312
store [81 x i8]* @s, [81 x i8]** %to_init, align 8
310313
ret void
311314
}
@@ -510,7 +513,10 @@ fn nested_initializer_pous() {
510513
%b = getelementptr inbounds %foo, %foo* %deref, i32 0, i32 2
511514
call void @__init_bar(%bar* %b)
512515
%deref1 = load %foo*, %foo** %self, align 8
513-
%str_ref = getelementptr inbounds %foo, %foo* %deref1, i32 0, i32 1
516+
%__vtable = getelementptr inbounds %foo, %foo* %deref1, i32 0, i32 0
517+
store i32* bitcast (%__vtable_foo* @__vtable_foo_instance to i32*), i32** %__vtable, align 8
518+
%deref2 = load %foo*, %foo** %self, align 8
519+
%str_ref = getelementptr inbounds %foo, %foo* %deref2, i32 0, i32 1
514520
store [81 x i8]* @str, [81 x i8]** %str_ref, align 8
515521
ret void
516522
}
@@ -522,6 +528,9 @@ fn nested_initializer_pous() {
522528
%deref = load %bar*, %bar** %self, align 8
523529
%b = getelementptr inbounds %bar, %bar* %deref, i32 0, i32 1
524530
call void @__init_baz(%baz* %b)
531+
%deref1 = load %bar*, %bar** %self, align 8
532+
%__vtable = getelementptr inbounds %bar, %bar* %deref1, i32 0, i32 0
533+
store i32* bitcast (%__vtable_bar* @__vtable_bar_instance to i32*), i32** %__vtable, align 8
525534
ret void
526535
}
527536
@@ -530,7 +539,10 @@ fn nested_initializer_pous() {
530539
%self = alloca %baz*, align 8
531540
store %baz* %0, %baz** %self, align 8
532541
%deref = load %baz*, %baz** %self, align 8
533-
%str_ref = getelementptr inbounds %baz, %baz* %deref, i32 0, i32 1
542+
%__vtable = getelementptr inbounds %baz, %baz* %deref, i32 0, i32 0
543+
store i32* bitcast (%__vtable_baz* @__vtable_baz_instance to i32*), i32** %__vtable, align 8
544+
%deref1 = load %baz*, %baz** %self, align 8
545+
%str_ref = getelementptr inbounds %baz, %baz* %deref1, i32 0, i32 1
534546
store [81 x i8]* @str, [81 x i8]** %str_ref, align 8
535547
ret void
536548
}
@@ -720,9 +732,12 @@ fn local_address() {
720732
%self = alloca %foo*, align 8
721733
store %foo* %0, %foo** %self, align 8
722734
%deref = load %foo*, %foo** %self, align 8
723-
%pi = getelementptr inbounds %foo, %foo* %deref, i32 0, i32 2
735+
%__vtable = getelementptr inbounds %foo, %foo* %deref, i32 0, i32 0
736+
store i32* bitcast (%__vtable_foo* @__vtable_foo_instance to i32*), i32** %__vtable, align 8
724737
%deref1 = load %foo*, %foo** %self, align 8
725-
%i = getelementptr inbounds %foo, %foo* %deref1, i32 0, i32 1
738+
%pi = getelementptr inbounds %foo, %foo* %deref1, i32 0, i32 2
739+
%deref2 = load %foo*, %foo** %self, align 8
740+
%i = getelementptr inbounds %foo, %foo* %deref2, i32 0, i32 1
726741
store i16* %i, i16** %pi, align 8
727742
ret void
728743
}
@@ -840,6 +855,9 @@ fn user_init_called_for_variables_on_stack() {
840855
entry:
841856
%self = alloca %foo*, align 8
842857
store %foo* %0, %foo** %self, align 8
858+
%deref = load %foo*, %foo** %self, align 8
859+
%__vtable = getelementptr inbounds %foo, %foo* %deref, i32 0, i32 0
860+
store i32* bitcast (%__vtable_foo* @__vtable_foo_instance to i32*), i32** %__vtable, align 8
843861
ret void
844862
}
845863
@@ -1172,6 +1190,9 @@ fn stateful_pous_methods_and_structs_get_init_functions() {
11721190
entry:
11731191
%self = alloca %foo*, align 8
11741192
store %foo* %0, %foo** %self, align 8
1193+
%deref = load %foo*, %foo** %self, align 8
1194+
%__vtable = getelementptr inbounds %foo, %foo* %deref, i32 0, i32 0
1195+
store i32* bitcast (%__vtable_foo* @__vtable_foo_instance to i32*), i32** %__vtable, align 8
11751196
ret void
11761197
}
11771198
@@ -1186,6 +1207,9 @@ fn stateful_pous_methods_and_structs_get_init_functions() {
11861207
entry:
11871208
%self = alloca %cl*, align 8
11881209
store %cl* %0, %cl** %self, align 8
1210+
%deref = load %cl*, %cl** %self, align 8
1211+
%__vtable = getelementptr inbounds %cl, %cl* %deref, i32 0, i32 0
1212+
store i32* bitcast (%__vtable_cl* @__vtable_cl_instance to i32*), i32** %__vtable, align 8
11891213
ret void
11901214
}
11911215
@@ -1300,7 +1324,10 @@ fn global_instance() {
13001324
%self = alloca %foo*, align 8
13011325
store %foo* %0, %foo** %self, align 8
13021326
%deref = load %foo*, %foo** %self, align 8
1303-
%s = getelementptr inbounds %foo, %foo* %deref, i32 0, i32 1
1327+
%__vtable = getelementptr inbounds %foo, %foo* %deref, i32 0, i32 0
1328+
store i32* bitcast (%__vtable_foo* @__vtable_foo_instance to i32*), i32** %__vtable, align 8
1329+
%deref1 = load %foo*, %foo** %self, align 8
1330+
%s = getelementptr inbounds %foo, %foo* %deref1, i32 0, i32 1
13041331
store [81 x i8]* @ps, [81 x i8]** %s, align 8
13051332
ret void
13061333
}
@@ -1422,7 +1449,10 @@ fn aliased_types() {
14221449
%self = alloca %foo*, align 8
14231450
store %foo* %0, %foo** %self, align 8
14241451
%deref = load %foo*, %foo** %self, align 8
1425-
%s = getelementptr inbounds %foo, %foo* %deref, i32 0, i32 1
1452+
%__vtable = getelementptr inbounds %foo, %foo* %deref, i32 0, i32 0
1453+
store i32* bitcast (%__vtable_foo* @__vtable_foo_instance to i32*), i32** %__vtable, align 8
1454+
%deref1 = load %foo*, %foo** %self, align 8
1455+
%s = getelementptr inbounds %foo, %foo* %deref1, i32 0, i32 1
14261456
store [81 x i8]* @ps, [81 x i8]** %s, align 8
14271457
ret void
14281458
}
@@ -1621,6 +1651,9 @@ fn var_config_aliased_variables_initialized() {
16211651
entry:
16221652
%self = alloca %FB*, align 8
16231653
store %FB* %0, %FB** %self, align 8
1654+
%deref = load %FB*, %FB** %self, align 8
1655+
%__vtable = getelementptr inbounds %FB, %FB* %deref, i32 0, i32 0
1656+
store i32* bitcast (%__vtable_FB* @__vtable_FB_instance to i32*), i32** %__vtable, align 8
16241657
ret void
16251658
}
16261659
@@ -1749,6 +1782,9 @@ fn var_external_blocks_are_ignored_in_init_functions() {
17491782
entry:
17501783
%self = alloca %foo*, align 8
17511784
store %foo* %0, %foo** %self, align 8
1785+
%deref = load %foo*, %foo** %self, align 8
1786+
%__vtable = getelementptr inbounds %foo, %foo* %deref, i32 0, i32 0
1787+
store i32* bitcast (%__vtable_foo* @__vtable_foo_instance to i32*), i32** %__vtable, align 8
17521788
ret void
17531789
}
17541790
@@ -1832,20 +1868,23 @@ fn ref_to_local_member() {
18321868
%self = alloca %foo*, align 8
18331869
store %foo* %0, %foo** %self, align 8
18341870
%deref = load %foo*, %foo** %self, align 8
1835-
%ptr = getelementptr inbounds %foo, %foo* %deref, i32 0, i32 2
1871+
%__vtable = getelementptr inbounds %foo, %foo* %deref, i32 0, i32 0
1872+
store i32* bitcast (%__vtable_foo* @__vtable_foo_instance to i32*), i32** %__vtable, align 8
18361873
%deref1 = load %foo*, %foo** %self, align 8
1837-
%s = getelementptr inbounds %foo, %foo* %deref1, i32 0, i32 1
1838-
store [81 x i8]* %s, [81 x i8]** %ptr, align 8
1874+
%ptr = getelementptr inbounds %foo, %foo* %deref1, i32 0, i32 2
18391875
%deref2 = load %foo*, %foo** %self, align 8
1840-
%alias = getelementptr inbounds %foo, %foo* %deref2, i32 0, i32 3
1876+
%s = getelementptr inbounds %foo, %foo* %deref2, i32 0, i32 1
1877+
store [81 x i8]* %s, [81 x i8]** %ptr, align 8
18411878
%deref3 = load %foo*, %foo** %self, align 8
1842-
%s4 = getelementptr inbounds %foo, %foo* %deref3, i32 0, i32 1
1843-
store [81 x i8]* %s4, [81 x i8]** %alias, align 8
1844-
%deref5 = load %foo*, %foo** %self, align 8
1845-
%reference_to = getelementptr inbounds %foo, %foo* %deref5, i32 0, i32 4
1879+
%alias = getelementptr inbounds %foo, %foo* %deref3, i32 0, i32 3
1880+
%deref4 = load %foo*, %foo** %self, align 8
1881+
%s5 = getelementptr inbounds %foo, %foo* %deref4, i32 0, i32 1
1882+
store [81 x i8]* %s5, [81 x i8]** %alias, align 8
18461883
%deref6 = load %foo*, %foo** %self, align 8
1847-
%s7 = getelementptr inbounds %foo, %foo* %deref6, i32 0, i32 1
1848-
store [81 x i8]* %s7, [81 x i8]** %reference_to, align 8
1884+
%reference_to = getelementptr inbounds %foo, %foo* %deref6, i32 0, i32 4
1885+
%deref7 = load %foo*, %foo** %self, align 8
1886+
%s8 = getelementptr inbounds %foo, %foo* %deref7, i32 0, i32 1
1887+
store [81 x i8]* %s8, [81 x i8]** %reference_to, align 8
18491888
ret void
18501889
}
18511890
@@ -1933,20 +1972,23 @@ fn ref_to_local_member_shadows_global() {
19331972
%self = alloca %foo*, align 8
19341973
store %foo* %0, %foo** %self, align 8
19351974
%deref = load %foo*, %foo** %self, align 8
1936-
%ptr = getelementptr inbounds %foo, %foo* %deref, i32 0, i32 2
1975+
%__vtable = getelementptr inbounds %foo, %foo* %deref, i32 0, i32 0
1976+
store i32* bitcast (%__vtable_foo* @__vtable_foo_instance to i32*), i32** %__vtable, align 8
19371977
%deref1 = load %foo*, %foo** %self, align 8
1938-
%s = getelementptr inbounds %foo, %foo* %deref1, i32 0, i32 1
1939-
store [81 x i8]* %s, [81 x i8]** %ptr, align 8
1978+
%ptr = getelementptr inbounds %foo, %foo* %deref1, i32 0, i32 2
19401979
%deref2 = load %foo*, %foo** %self, align 8
1941-
%alias = getelementptr inbounds %foo, %foo* %deref2, i32 0, i32 3
1980+
%s = getelementptr inbounds %foo, %foo* %deref2, i32 0, i32 1
1981+
store [81 x i8]* %s, [81 x i8]** %ptr, align 8
19421982
%deref3 = load %foo*, %foo** %self, align 8
1943-
%s4 = getelementptr inbounds %foo, %foo* %deref3, i32 0, i32 1
1944-
store [81 x i8]* %s4, [81 x i8]** %alias, align 8
1945-
%deref5 = load %foo*, %foo** %self, align 8
1946-
%reference_to = getelementptr inbounds %foo, %foo* %deref5, i32 0, i32 4
1983+
%alias = getelementptr inbounds %foo, %foo* %deref3, i32 0, i32 3
1984+
%deref4 = load %foo*, %foo** %self, align 8
1985+
%s5 = getelementptr inbounds %foo, %foo* %deref4, i32 0, i32 1
1986+
store [81 x i8]* %s5, [81 x i8]** %alias, align 8
19471987
%deref6 = load %foo*, %foo** %self, align 8
1948-
%s7 = getelementptr inbounds %foo, %foo* %deref6, i32 0, i32 1
1949-
store [81 x i8]* %s7, [81 x i8]** %reference_to, align 8
1988+
%reference_to = getelementptr inbounds %foo, %foo* %deref6, i32 0, i32 4
1989+
%deref7 = load %foo*, %foo** %self, align 8
1990+
%s8 = getelementptr inbounds %foo, %foo* %deref7, i32 0, i32 1
1991+
store [81 x i8]* %s8, [81 x i8]** %reference_to, align 8
19501992
ret void
19511993
}
19521994
@@ -2036,6 +2078,9 @@ fn temporary_variable_ref_to_local_member() {
20362078
entry:
20372079
%self = alloca %foo*, align 8
20382080
store %foo* %0, %foo** %self, align 8
2081+
%deref = load %foo*, %foo** %self, align 8
2082+
%__vtable = getelementptr inbounds %foo, %foo* %deref, i32 0, i32 0
2083+
store i32* bitcast (%__vtable_foo* @__vtable_foo_instance to i32*), i32** %__vtable, align 8
20392084
ret void
20402085
}
20412086
@@ -2187,6 +2232,9 @@ fn initializing_method_variables_with_refs() {
21872232
entry:
21882233
%self = alloca %foo*, align 8
21892234
store %foo* %0, %foo** %self, align 8
2235+
%deref = load %foo*, %foo** %self, align 8
2236+
%__vtable = getelementptr inbounds %foo, %foo* %deref, i32 0, i32 0
2237+
store i32* bitcast (%__vtable_foo* @__vtable_foo_instance to i32*), i32** %__vtable, align 8
21902238
ret void
21912239
}
21922240
@@ -2283,6 +2331,9 @@ fn initializing_method_variables_with_refs_referencing_parent_pou_variable() {
22832331
entry:
22842332
%self = alloca %foo*, align 8
22852333
store %foo* %0, %foo** %self, align 8
2334+
%deref = load %foo*, %foo** %self, align 8
2335+
%__vtable = getelementptr inbounds %foo, %foo* %deref, i32 0, i32 0
2336+
store i32* bitcast (%__vtable_foo* @__vtable_foo_instance to i32*), i32** %__vtable, align 8
22862337
ret void
22872338
}
22882339
@@ -2378,6 +2429,9 @@ fn initializing_method_variables_with_refs_referencing_global_variable() {
23782429
entry:
23792430
%self = alloca %foo*, align 8
23802431
store %foo* %0, %foo** %self, align 8
2432+
%deref = load %foo*, %foo** %self, align 8
2433+
%__vtable = getelementptr inbounds %foo, %foo* %deref, i32 0, i32 0
2434+
store i32* bitcast (%__vtable_foo* @__vtable_foo_instance to i32*), i32** %__vtable, align 8
23812435
ret void
23822436
}
23832437
@@ -2476,6 +2530,9 @@ fn initializing_method_variables_with_refs_shadowing() {
24762530
entry:
24772531
%self = alloca %foo*, align 8
24782532
store %foo* %0, %foo** %self, align 8
2533+
%deref = load %foo*, %foo** %self, align 8
2534+
%__vtable = getelementptr inbounds %foo, %foo* %deref, i32 0, i32 0
2535+
store i32* bitcast (%__vtable_foo* @__vtable_foo_instance to i32*), i32** %__vtable, align 8
24792536
ret void
24802537
}
24812538
@@ -2569,6 +2626,9 @@ fn initializing_method_variables_with_alias() {
25692626
entry:
25702627
%self = alloca %foo*, align 8
25712628
store %foo* %0, %foo** %self, align 8
2629+
%deref = load %foo*, %foo** %self, align 8
2630+
%__vtable = getelementptr inbounds %foo, %foo* %deref, i32 0, i32 0
2631+
store i32* bitcast (%__vtable_foo* @__vtable_foo_instance to i32*), i32** %__vtable, align 8
25722632
ret void
25732633
}
25742634
@@ -2662,6 +2722,9 @@ fn initializing_method_variables_with_reference_to() {
26622722
entry:
26632723
%self = alloca %foo*, align 8
26642724
store %foo* %0, %foo** %self, align 8
2725+
%deref = load %foo*, %foo** %self, align 8
2726+
%__vtable = getelementptr inbounds %foo, %foo* %deref, i32 0, i32 0
2727+
store i32* bitcast (%__vtable_foo* @__vtable_foo_instance to i32*), i32** %__vtable, align 8
26652728
ret void
26662729
}
26672730
@@ -2781,9 +2844,12 @@ fn methods_call_init_functions_for_their_members() {
27812844
%self = alloca %foo*, align 8
27822845
store %foo* %0, %foo** %self, align 8
27832846
%deref = load %foo*, %foo** %self, align 8
2784-
%y = getelementptr inbounds %foo, %foo* %deref, i32 0, i32 2
2847+
%__vtable = getelementptr inbounds %foo, %foo* %deref, i32 0, i32 0
2848+
store i32* bitcast (%__vtable_foo* @__vtable_foo_instance to i32*), i32** %__vtable, align 8
27852849
%deref1 = load %foo*, %foo** %self, align 8
2786-
%x = getelementptr inbounds %foo, %foo* %deref1, i32 0, i32 1
2850+
%y = getelementptr inbounds %foo, %foo* %deref1, i32 0, i32 2
2851+
%deref2 = load %foo*, %foo** %self, align 8
2852+
%x = getelementptr inbounds %foo, %foo* %deref2, i32 0, i32 1
27872853
store i32* %x, i32** %y, align 8
27882854
ret void
27892855
}
@@ -2799,6 +2865,9 @@ fn methods_call_init_functions_for_their_members() {
27992865
entry:
28002866
%self = alloca %bar*, align 8
28012867
store %bar* %0, %bar** %self, align 8
2868+
%deref = load %bar*, %bar** %self, align 8
2869+
%__vtable = getelementptr inbounds %bar, %bar* %deref, i32 0, i32 0
2870+
store i32* bitcast (%__vtable_bar* @__vtable_bar_instance to i32*), i32** %__vtable, align 8
28022871
ret void
28032872
}
28042873
@@ -2930,6 +2999,9 @@ fn user_fb_init_is_added_and_called_if_it_exists() {
29302999
entry:
29313000
%self = alloca %foo*, align 8
29323001
store %foo* %0, %foo** %self, align 8
3002+
%deref = load %foo*, %foo** %self, align 8
3003+
%__vtable = getelementptr inbounds %foo, %foo* %deref, i32 0, i32 0
3004+
store i32* bitcast (%__vtable_foo* @__vtable_foo_instance to i32*), i32** %__vtable, align 8
29333005
ret void
29343006
}
29353007
@@ -3091,6 +3163,9 @@ fn user_fb_init_in_global_struct() {
30913163
entry:
30923164
%self = alloca %foo*, align 8
30933165
store %foo* %0, %foo** %self, align 8
3166+
%deref = load %foo*, %foo** %self, align 8
3167+
%__vtable = getelementptr inbounds %foo, %foo* %deref, i32 0, i32 0
3168+
store i32* bitcast (%__vtable_foo* @__vtable_foo_instance to i32*), i32** %__vtable, align 8
30943169
ret void
30953170
}
30963171

0 commit comments

Comments
 (0)