Skip to content

Commit 956a3eb

Browse files
committed
fix: Polymorphic function block calls
The `__body` function pointer now points at the function blocks body method in the virtual table struct. As a result, code execution like the following is now possible ``` VAR instanceA: A; instanceB: B; // Child of A refInstanceA: POINTER TO A; END_VAR refInstanceA := ADR(A); refInstanceA^(); // Calls body method of A refInstanceA := ADR(B); refInstanceA^(); // Calls body method of B ```
1 parent 27a06a5 commit 956a3eb

12 files changed

+945
-199
lines changed

src/codegen/tests/debug_tests.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,10 @@ fn dbg_declare_has_valid_metadata_references_for_methods() {
391391
%self = alloca %__vtable_fb*, align 8
392392
store %__vtable_fb* %0, %__vtable_fb** %self, align 8
393393
%deref = load %__vtable_fb*, %__vtable_fb** %self, align 8
394-
%foo = getelementptr inbounds %__vtable_fb, %__vtable_fb* %deref, i32 0, i32 1
394+
%__body = getelementptr inbounds %__vtable_fb, %__vtable_fb* %deref, i32 0, i32 0
395+
store void (%fb*)* @fb, void (%fb*)** %__body, align 8
396+
%deref1 = load %__vtable_fb*, %__vtable_fb** %self, align 8
397+
%foo = getelementptr inbounds %__vtable_fb, %__vtable_fb* %deref1, i32 0, i32 1
395398
store void (%fb*)* @fb__foo, void (%fb*)** %foo, align 8
396399
ret void
397400
}

src/codegen/tests/initialization_test/complex_initializers.rs

Lines changed: 129 additions & 54 deletions
Large diffs are not rendered by default.

src/codegen/tests/oop_tests.rs

Lines changed: 88 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,19 @@ fn members_from_base_class_are_available_in_subclasses() {
6161
entry:
6262
%self = alloca %__vtable_foo*, align 8
6363
store %__vtable_foo* %0, %__vtable_foo** %self, align 8
64+
%deref = load %__vtable_foo*, %__vtable_foo** %self, align 8
65+
%__body = getelementptr inbounds %__vtable_foo, %__vtable_foo* %deref, i32 0, i32 0
66+
store void (%foo*)* @foo, void (%foo*)** %__body, align 8
6467
ret void
6568
}
6669
6770
define void @__init___vtable_bar(%__vtable_bar* %0) {
6871
entry:
6972
%self = alloca %__vtable_bar*, align 8
7073
store %__vtable_bar* %0, %__vtable_bar** %self, align 8
74+
%deref = load %__vtable_bar*, %__vtable_bar** %self, align 8
75+
%__body = getelementptr inbounds %__vtable_bar, %__vtable_bar* %deref, i32 0, i32 0
76+
store void (%bar*)* @bar, void (%bar*)** %__body, align 8
7177
ret void
7278
}
7379
@@ -218,20 +224,29 @@ fn write_to_parent_variable_qualified_access() {
218224
entry:
219225
%self = alloca %__vtable_fb*, align 8
220226
store %__vtable_fb* %0, %__vtable_fb** %self, align 8
227+
%deref = load %__vtable_fb*, %__vtable_fb** %self, align 8
228+
%__body = getelementptr inbounds %__vtable_fb, %__vtable_fb* %deref, i32 0, i32 0
229+
store void (%fb*)* @fb, void (%fb*)** %__body, align 8
221230
ret void
222231
}
223232
224233
define void @__init___vtable_fb2(%__vtable_fb2* %0) {
225234
entry:
226235
%self = alloca %__vtable_fb2*, align 8
227236
store %__vtable_fb2* %0, %__vtable_fb2** %self, align 8
237+
%deref = load %__vtable_fb2*, %__vtable_fb2** %self, align 8
238+
%__body = getelementptr inbounds %__vtable_fb2, %__vtable_fb2* %deref, i32 0, i32 0
239+
store void (%fb2*)* @fb2, void (%fb2*)** %__body, align 8
228240
ret void
229241
}
230242
231243
define void @__init___vtable_foo(%__vtable_foo* %0) {
232244
entry:
233245
%self = alloca %__vtable_foo*, align 8
234246
store %__vtable_foo* %0, %__vtable_foo** %self, align 8
247+
%deref = load %__vtable_foo*, %__vtable_foo** %self, align 8
248+
%__body = getelementptr inbounds %__vtable_foo, %__vtable_foo* %deref, i32 0, i32 0
249+
store void (%foo*)* @foo, void (%foo*)** %__body, align 8
235250
ret void
236251
}
237252
@@ -442,7 +457,10 @@ fn write_to_parent_variable_in_instance() {
442457
%self = alloca %__vtable_foo*, align 8
443458
store %__vtable_foo* %0, %__vtable_foo** %self, align 8
444459
%deref = load %__vtable_foo*, %__vtable_foo** %self, align 8
445-
%baz = getelementptr inbounds %__vtable_foo, %__vtable_foo* %deref, i32 0, i32 1
460+
%__body = getelementptr inbounds %__vtable_foo, %__vtable_foo* %deref, i32 0, i32 0
461+
store void (%foo*)* @foo, void (%foo*)** %__body, align 8
462+
%deref1 = load %__vtable_foo*, %__vtable_foo** %self, align 8
463+
%baz = getelementptr inbounds %__vtable_foo, %__vtable_foo* %deref1, i32 0, i32 1
446464
store void (%foo*)* @foo__baz, void (%foo*)** %baz, align 8
447465
ret void
448466
}
@@ -452,7 +470,10 @@ fn write_to_parent_variable_in_instance() {
452470
%self = alloca %__vtable_bar*, align 8
453471
store %__vtable_bar* %0, %__vtable_bar** %self, align 8
454472
%deref = load %__vtable_bar*, %__vtable_bar** %self, align 8
455-
%baz = getelementptr inbounds %__vtable_bar, %__vtable_bar* %deref, i32 0, i32 1
473+
%__body = getelementptr inbounds %__vtable_bar, %__vtable_bar* %deref, i32 0, i32 0
474+
store void (%bar*)* @bar, void (%bar*)** %__body, align 8
475+
%deref1 = load %__vtable_bar*, %__vtable_bar** %self, align 8
476+
%baz = getelementptr inbounds %__vtable_bar, %__vtable_bar* %deref1, i32 0, i32 1
456477
store void (%foo*)* @foo__baz, void (%foo*)** %baz, align 8
457478
ret void
458479
}
@@ -654,20 +675,29 @@ fn array_in_parent_generated() {
654675
entry:
655676
%self = alloca %__vtable_grandparent*, align 8
656677
store %__vtable_grandparent* %0, %__vtable_grandparent** %self, align 8
678+
%deref = load %__vtable_grandparent*, %__vtable_grandparent** %self, align 8
679+
%__body = getelementptr inbounds %__vtable_grandparent, %__vtable_grandparent* %deref, i32 0, i32 0
680+
store void (%grandparent*)* @grandparent, void (%grandparent*)** %__body, align 8
657681
ret void
658682
}
659683
660684
define void @__init___vtable_parent(%__vtable_parent* %0) {
661685
entry:
662686
%self = alloca %__vtable_parent*, align 8
663687
store %__vtable_parent* %0, %__vtable_parent** %self, align 8
688+
%deref = load %__vtable_parent*, %__vtable_parent** %self, align 8
689+
%__body = getelementptr inbounds %__vtable_parent, %__vtable_parent* %deref, i32 0, i32 0
690+
store void (%parent*)* @parent, void (%parent*)** %__body, align 8
664691
ret void
665692
}
666693
667694
define void @__init___vtable_child(%__vtable_child* %0) {
668695
entry:
669696
%self = alloca %__vtable_child*, align 8
670697
store %__vtable_child* %0, %__vtable_child** %self, align 8
698+
%deref = load %__vtable_child*, %__vtable_child** %self, align 8
699+
%__body = getelementptr inbounds %__vtable_child, %__vtable_child* %deref, i32 0, i32 0
700+
store void (%child*)* @child, void (%child*)** %__body, align 8
671701
ret void
672702
}
673703
@@ -881,20 +911,29 @@ fn complex_array_access_generated() {
881911
entry:
882912
%self = alloca %__vtable_grandparent*, align 8
883913
store %__vtable_grandparent* %0, %__vtable_grandparent** %self, align 8
914+
%deref = load %__vtable_grandparent*, %__vtable_grandparent** %self, align 8
915+
%__body = getelementptr inbounds %__vtable_grandparent, %__vtable_grandparent* %deref, i32 0, i32 0
916+
store void (%grandparent*)* @grandparent, void (%grandparent*)** %__body, align 8
884917
ret void
885918
}
886919
887920
define void @__init___vtable_parent(%__vtable_parent* %0) {
888921
entry:
889922
%self = alloca %__vtable_parent*, align 8
890923
store %__vtable_parent* %0, %__vtable_parent** %self, align 8
924+
%deref = load %__vtable_parent*, %__vtable_parent** %self, align 8
925+
%__body = getelementptr inbounds %__vtable_parent, %__vtable_parent* %deref, i32 0, i32 0
926+
store void (%parent*)* @parent, void (%parent*)** %__body, align 8
891927
ret void
892928
}
893929
894930
define void @__init___vtable_child(%__vtable_child* %0) {
895931
entry:
896932
%self = alloca %__vtable_child*, align 8
897933
store %__vtable_child* %0, %__vtable_child** %self, align 8
934+
%deref = load %__vtable_child*, %__vtable_child** %self, align 8
935+
%__body = getelementptr inbounds %__vtable_child, %__vtable_child* %deref, i32 0, i32 0
936+
store void (%child*)* @child, void (%child*)** %__body, align 8
898937
ret void
899938
}
900939
@@ -1114,10 +1153,13 @@ fn this_in_method_call_chain() {
11141153
%self = alloca %__vtable_FB_Test*, align 8
11151154
store %__vtable_FB_Test* %0, %__vtable_FB_Test** %self, align 8
11161155
%deref = load %__vtable_FB_Test*, %__vtable_FB_Test** %self, align 8
1117-
%Step = getelementptr inbounds %__vtable_FB_Test, %__vtable_FB_Test* %deref, i32 0, i32 1
1118-
store void (%FB_Test*)* @FB_Test__Step, void (%FB_Test*)** %Step, align 8
1156+
%__body = getelementptr inbounds %__vtable_FB_Test, %__vtable_FB_Test* %deref, i32 0, i32 0
1157+
store void (%FB_Test*)* @FB_Test, void (%FB_Test*)** %__body, align 8
11191158
%deref1 = load %__vtable_FB_Test*, %__vtable_FB_Test** %self, align 8
1120-
%Increment = getelementptr inbounds %__vtable_FB_Test, %__vtable_FB_Test* %deref1, i32 0, i32 2
1159+
%Step = getelementptr inbounds %__vtable_FB_Test, %__vtable_FB_Test* %deref1, i32 0, i32 1
1160+
store void (%FB_Test*)* @FB_Test__Step, void (%FB_Test*)** %Step, align 8
1161+
%deref2 = load %__vtable_FB_Test*, %__vtable_FB_Test** %self, align 8
1162+
%Increment = getelementptr inbounds %__vtable_FB_Test, %__vtable_FB_Test* %deref2, i32 0, i32 2
11211163
store void (%FB_Test*)* @FB_Test__Increment, void (%FB_Test*)** %Increment, align 8
11221164
ret void
11231165
}
@@ -1224,7 +1266,10 @@ fn this_in_method_and_body_in_function_block() {
12241266
%self = alloca %__vtable_FB_Test*, align 8
12251267
store %__vtable_FB_Test* %0, %__vtable_FB_Test** %self, align 8
12261268
%deref = load %__vtable_FB_Test*, %__vtable_FB_Test** %self, align 8
1227-
%GetVal = getelementptr inbounds %__vtable_FB_Test, %__vtable_FB_Test* %deref, i32 0, i32 1
1269+
%__body = getelementptr inbounds %__vtable_FB_Test, %__vtable_FB_Test* %deref, i32 0, i32 0
1270+
store void (%FB_Test*)* @FB_Test, void (%FB_Test*)** %__body, align 8
1271+
%deref1 = load %__vtable_FB_Test*, %__vtable_FB_Test** %self, align 8
1272+
%GetVal = getelementptr inbounds %__vtable_FB_Test, %__vtable_FB_Test* %deref1, i32 0, i32 1
12281273
store i16 (%FB_Test*)* @FB_Test__GetVal, i16 (%FB_Test*)** %GetVal, align 8
12291274
ret void
12301275
}
@@ -1369,7 +1414,10 @@ fn pass_this_to_method() {
13691414
%self = alloca %__vtable_FB_Test*, align 8
13701415
store %__vtable_FB_Test* %0, %__vtable_FB_Test** %self, align 8
13711416
%deref = load %__vtable_FB_Test*, %__vtable_FB_Test** %self, align 8
1372-
%foo = getelementptr inbounds %__vtable_FB_Test, %__vtable_FB_Test* %deref, i32 0, i32 1
1417+
%__body = getelementptr inbounds %__vtable_FB_Test, %__vtable_FB_Test* %deref, i32 0, i32 0
1418+
store void (%FB_Test*)* @FB_Test, void (%FB_Test*)** %__body, align 8
1419+
%deref1 = load %__vtable_FB_Test*, %__vtable_FB_Test** %self, align 8
1420+
%foo = getelementptr inbounds %__vtable_FB_Test, %__vtable_FB_Test* %deref1, i32 0, i32 1
13731421
store void (%FB_Test*)* @FB_Test__foo, void (%FB_Test*)** %foo, align 8
13741422
ret void
13751423
}
@@ -1379,7 +1427,10 @@ fn pass_this_to_method() {
13791427
%self = alloca %__vtable_FB_Test2*, align 8
13801428
store %__vtable_FB_Test2* %0, %__vtable_FB_Test2** %self, align 8
13811429
%deref = load %__vtable_FB_Test2*, %__vtable_FB_Test2** %self, align 8
1382-
%bar = getelementptr inbounds %__vtable_FB_Test2, %__vtable_FB_Test2* %deref, i32 0, i32 1
1430+
%__body = getelementptr inbounds %__vtable_FB_Test2, %__vtable_FB_Test2* %deref, i32 0, i32 0
1431+
store void (%FB_Test2*)* @FB_Test2, void (%FB_Test2*)** %__body, align 8
1432+
%deref1 = load %__vtable_FB_Test2*, %__vtable_FB_Test2** %self, align 8
1433+
%bar = getelementptr inbounds %__vtable_FB_Test2, %__vtable_FB_Test2* %deref1, i32 0, i32 1
13831434
store i16 (%FB_Test2*, %FB_Test*)* @FB_Test2__bar, i16 (%FB_Test2*, %FB_Test*)** %bar, align 8
13841435
ret void
13851436
}
@@ -1514,7 +1565,10 @@ fn this_with_shadowed_variable() {
15141565
%self = alloca %__vtable_FB_Test*, align 8
15151566
store %__vtable_FB_Test* %0, %__vtable_FB_Test** %self, align 8
15161567
%deref = load %__vtable_FB_Test*, %__vtable_FB_Test** %self, align 8
1517-
%shadow_val = getelementptr inbounds %__vtable_FB_Test, %__vtable_FB_Test* %deref, i32 0, i32 1
1568+
%__body = getelementptr inbounds %__vtable_FB_Test, %__vtable_FB_Test* %deref, i32 0, i32 0
1569+
store void (%FB_Test*)* @FB_Test, void (%FB_Test*)** %__body, align 8
1570+
%deref1 = load %__vtable_FB_Test*, %__vtable_FB_Test** %self, align 8
1571+
%shadow_val = getelementptr inbounds %__vtable_FB_Test, %__vtable_FB_Test* %deref1, i32 0, i32 1
15181572
store void (%FB_Test*)* @FB_Test__shadow_val, void (%FB_Test*)** %shadow_val, align 8
15191573
ret void
15201574
}
@@ -1613,6 +1667,9 @@ fn this_calling_function_and_passing_this() {
16131667
entry:
16141668
%self = alloca %__vtable_FB_Test*, align 8
16151669
store %__vtable_FB_Test* %0, %__vtable_FB_Test** %self, align 8
1670+
%deref = load %__vtable_FB_Test*, %__vtable_FB_Test** %self, align 8
1671+
%__body = getelementptr inbounds %__vtable_FB_Test, %__vtable_FB_Test* %deref, i32 0, i32 0
1672+
store void (%FB_Test*)* @FB_Test, void (%FB_Test*)** %__body, align 8
16161673
ret void
16171674
}
16181675
@@ -1760,13 +1817,16 @@ fn this_in_property_and_calling_method() {
17601817
%self = alloca %__vtable_FB_Test*, align 8
17611818
store %__vtable_FB_Test* %0, %__vtable_FB_Test** %self, align 8
17621819
%deref = load %__vtable_FB_Test*, %__vtable_FB_Test** %self, align 8
1763-
%DoubleX = getelementptr inbounds %__vtable_FB_Test, %__vtable_FB_Test* %deref, i32 0, i32 1
1764-
store i16 (%FB_Test*)* @FB_Test__DoubleX, i16 (%FB_Test*)** %DoubleX, align 8
1820+
%__body = getelementptr inbounds %__vtable_FB_Test, %__vtable_FB_Test* %deref, i32 0, i32 0
1821+
store void (%FB_Test*)* @FB_Test, void (%FB_Test*)** %__body, align 8
17651822
%deref1 = load %__vtable_FB_Test*, %__vtable_FB_Test** %self, align 8
1766-
%__get_Value = getelementptr inbounds %__vtable_FB_Test, %__vtable_FB_Test* %deref1, i32 0, i32 2
1767-
store i16 (%FB_Test*)* @FB_Test____get_Value, i16 (%FB_Test*)** %__get_Value, align 8
1823+
%DoubleX = getelementptr inbounds %__vtable_FB_Test, %__vtable_FB_Test* %deref1, i32 0, i32 1
1824+
store i16 (%FB_Test*)* @FB_Test__DoubleX, i16 (%FB_Test*)** %DoubleX, align 8
17681825
%deref2 = load %__vtable_FB_Test*, %__vtable_FB_Test** %self, align 8
1769-
%__set_Value = getelementptr inbounds %__vtable_FB_Test, %__vtable_FB_Test* %deref2, i32 0, i32 3
1826+
%__get_Value = getelementptr inbounds %__vtable_FB_Test, %__vtable_FB_Test* %deref2, i32 0, i32 2
1827+
store i16 (%FB_Test*)* @FB_Test____get_Value, i16 (%FB_Test*)** %__get_Value, align 8
1828+
%deref3 = load %__vtable_FB_Test*, %__vtable_FB_Test** %self, align 8
1829+
%__set_Value = getelementptr inbounds %__vtable_FB_Test, %__vtable_FB_Test* %deref3, i32 0, i32 3
17701830
store void (%FB_Test*, i16)* @FB_Test____set_Value, void (%FB_Test*, i16)** %__set_Value, align 8
17711831
ret void
17721832
}
@@ -1864,7 +1924,10 @@ fn this_with_self_pointer() {
18641924
%self = alloca %__vtable_FB_Test*, align 8
18651925
store %__vtable_FB_Test* %0, %__vtable_FB_Test** %self, align 8
18661926
%deref = load %__vtable_FB_Test*, %__vtable_FB_Test** %self, align 8
1867-
%InitRef = getelementptr inbounds %__vtable_FB_Test, %__vtable_FB_Test* %deref, i32 0, i32 1
1927+
%__body = getelementptr inbounds %__vtable_FB_Test, %__vtable_FB_Test* %deref, i32 0, i32 0
1928+
store void (%FB_Test*)* @FB_Test, void (%FB_Test*)** %__body, align 8
1929+
%deref1 = load %__vtable_FB_Test*, %__vtable_FB_Test** %self, align 8
1930+
%InitRef = getelementptr inbounds %__vtable_FB_Test, %__vtable_FB_Test* %deref1, i32 0, i32 1
18681931
store void (%FB_Test*)* @FB_Test__InitRef, void (%FB_Test*)** %InitRef, align 8
18691932
ret void
18701933
}
@@ -1946,6 +2009,9 @@ fn this_in_variable_initialization() {
19462009
entry:
19472010
%self = alloca %__vtable_FB*, align 8
19482011
store %__vtable_FB* %0, %__vtable_FB** %self, align 8
2012+
%deref = load %__vtable_FB*, %__vtable_FB** %self, align 8
2013+
%__body = getelementptr inbounds %__vtable_FB, %__vtable_FB* %deref, i32 0, i32 0
2014+
store void (%FB*)* @FB, void (%FB*)** %__body, align 8
19492015
ret void
19502016
}
19512017
@@ -2030,6 +2096,9 @@ fn this_in_action_in_functionblock() {
20302096
entry:
20312097
%self = alloca %__vtable_fb*, align 8
20322098
store %__vtable_fb* %0, %__vtable_fb** %self, align 8
2099+
%deref = load %__vtable_fb*, %__vtable_fb** %self, align 8
2100+
%__body = getelementptr inbounds %__vtable_fb, %__vtable_fb* %deref, i32 0, i32 0
2101+
store void (%fb*)* @fb, void (%fb*)** %__body, align 8
20332102
ret void
20342103
}
20352104
@@ -2117,7 +2186,10 @@ fn this_calling_functionblock_body_from_method() {
21172186
%self = alloca %__vtable_fb*, align 8
21182187
store %__vtable_fb* %0, %__vtable_fb** %self, align 8
21192188
%deref = load %__vtable_fb*, %__vtable_fb** %self, align 8
2120-
%foo = getelementptr inbounds %__vtable_fb, %__vtable_fb* %deref, i32 0, i32 1
2189+
%__body = getelementptr inbounds %__vtable_fb, %__vtable_fb* %deref, i32 0, i32 0
2190+
store void (%fb*)* @fb, void (%fb*)** %__body, align 8
2191+
%deref1 = load %__vtable_fb*, %__vtable_fb** %self, align 8
2192+
%foo = getelementptr inbounds %__vtable_fb, %__vtable_fb* %deref1, i32 0, i32 1
21212193
store i16 (%fb*)* @fb__foo, i16 (%fb*)** %foo, align 8
21222194
ret void
21232195
}

0 commit comments

Comments
 (0)