Skip to content

Commit 3c2f151

Browse files
committed
Add some tests
1 parent 6c4b552 commit 3c2f151

File tree

3 files changed

+154
-44
lines changed

3 files changed

+154
-44
lines changed

src/codegen/tests/function_pointer_tests.rs

Lines changed: 48 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::test_utils::tests::codegen;
22
use plc_util::filtered_assert_snapshot;
33

44
#[test]
5-
fn function_pointer_simple() {
5+
fn function_pointer() {
66
let result = codegen(
77
r"
88
FUNCTION echo : DINT
@@ -15,10 +15,10 @@ fn function_pointer_simple() {
1515
1616
FUNCTION main
1717
VAR
18-
echoPtr : REF_TO echo;
18+
echoPtr : POINTER TO echo;
1919
END_VAR
2020
21-
echoPtr := REF(echo);
21+
echoPtr := ADR(echo);
2222
echoPtr^(12345);
2323
END_FUNCTION
2424
",
@@ -56,81 +56,85 @@ fn function_pointer_simple() {
5656
}
5757

5858
#[test]
59-
fn function_pointer_simple_method() {
59+
fn function_pointer_method() {
6060
let result = codegen(
6161
r"
62-
TYPE VTable:
62+
VAR_GLOBAL
63+
instanceVTableFbA: VTableFbA := (foo := ADR(FbA.foo));
64+
END_VAR
65+
66+
TYPE VTableFbA:
6367
STRUCT
64-
fbEcho : REF_TO fb.fbEcho := REF(fb.fbEcho);
68+
foo: POINTER TO FbA.foo;
6569
END_STRUCT
6670
END_TYPE
6771
68-
FUNCTION_BLOCK fb
69-
METHOD fbEcho : DINT
70-
VAR_INPUT
71-
value : INT;
72-
END_VAR
72+
FUNCTION_BLOCK FbA
73+
VAR
74+
vtable: POINTER TO VTableFbA := ADR(instanceVTableFbA);
75+
localVariableInFbA: INT;
76+
END_VAR
7377
74-
fbEcho := value;
78+
METHOD foo: INT
79+
// printf('Hello from FbA::foo$N');
7580
END_METHOD
7681
END_FUNCTION_BLOCK
7782
7883
FUNCTION main
7984
VAR
80-
vt: VTable;
81-
instance : fb;
85+
instanceFbA: FbA;
8286
END_VAR
8387
84-
vt.fbEcho^(instance, INT#5);
88+
instanceFbA.vtable^.foo^(instanceFbA);
8589
END_FUNCTION
8690
",
8791
);
8892

93+
// XXX: The `__init_globals` is missing here, but we're interested in the derefs here anyways
8994
filtered_assert_snapshot!(result, @r#"
9095
; ModuleID = '<internal>'
9196
source_filename = "<internal>"
9297
target datalayout = "[filtered]"
9398
target triple = "[filtered]"
9499
95-
%fb = type {}
96-
%VTable = type { i32 (%fb*, i16)* }
100+
%VTableFbA = type { i16 (%FbA*)* }
101+
%FbA = type { %VTableFbA*, i16 }
97102
98-
@__fb__init = unnamed_addr constant %fb zeroinitializer
99-
@__VTable__init = unnamed_addr constant %VTable zeroinitializer
103+
@instanceVTableFbA = global %VTableFbA zeroinitializer
104+
@__VTableFbA__init = unnamed_addr constant %VTableFbA zeroinitializer
105+
@__FbA__init = unnamed_addr constant %FbA zeroinitializer
100106
101-
define void @fb(%fb* %0) {
107+
define i16 @FbA__foo(%FbA* %0) {
102108
entry:
103-
%this = alloca %fb*, align 8
104-
store %fb* %0, %fb** %this, align 8
105-
ret void
109+
%this = alloca %FbA*, align 8
110+
store %FbA* %0, %FbA** %this, align 8
111+
%vtable = getelementptr inbounds %FbA, %FbA* %0, i32 0, i32 0
112+
%localVariableInFbA = getelementptr inbounds %FbA, %FbA* %0, i32 0, i32 1
113+
%FbA.foo = alloca i16, align 2
114+
store i16 0, i16* %FbA.foo, align 2
115+
%FbA__foo_ret = load i16, i16* %FbA.foo, align 2
116+
ret i16 %FbA__foo_ret
106117
}
107118
108-
define i32 @fb__fbEcho(%fb* %0, i16 %1) {
119+
define void @FbA(%FbA* %0) {
109120
entry:
110-
%this = alloca %fb*, align 8
111-
store %fb* %0, %fb** %this, align 8
112-
%fb.fbEcho = alloca i32, align 4
113-
%value = alloca i16, align 2
114-
store i16 %1, i16* %value, align 2
115-
store i32 0, i32* %fb.fbEcho, align 4
116-
%load_value = load i16, i16* %value, align 2
117-
%2 = sext i16 %load_value to i32
118-
store i32 %2, i32* %fb.fbEcho, align 4
119-
%fb__fbEcho_ret = load i32, i32* %fb.fbEcho, align 4
120-
ret i32 %fb__fbEcho_ret
121+
%this = alloca %FbA*, align 8
122+
store %FbA* %0, %FbA** %this, align 8
123+
%vtable = getelementptr inbounds %FbA, %FbA* %0, i32 0, i32 0
124+
%localVariableInFbA = getelementptr inbounds %FbA, %FbA* %0, i32 0, i32 1
125+
ret void
121126
}
122127
123128
define void @main() {
124129
entry:
125-
%vt = alloca %VTable, align 8
126-
%instance = alloca %fb, align 8
127-
%0 = bitcast %VTable* %vt to i8*
128-
call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 %0, i8* align 1 bitcast (%VTable* @__VTable__init to i8*), i64 ptrtoint (%VTable* getelementptr (%VTable, %VTable* null, i32 1) to i64), i1 false)
129-
%1 = bitcast %fb* %instance to i8*
130-
call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 %1, i8* align 1 bitcast (%fb* @__fb__init to i8*), i64 ptrtoint (%fb* getelementptr (%fb, %fb* null, i32 1) to i64), i1 false)
131-
%fbEcho = getelementptr inbounds %VTable, %VTable* %vt, i32 0, i32 0
132-
%2 = load i32 (%fb*, i16)*, i32 (%fb*, i16)** %fbEcho, align 8
133-
%call = call i32 %2(%fb* %instance, i16 5)
130+
%instanceFbA = alloca %FbA, align 8
131+
%0 = bitcast %FbA* %instanceFbA to i8*
132+
call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 %0, i8* align 1 bitcast (%FbA* @__FbA__init to i8*), i64 ptrtoint (%FbA* getelementptr (%FbA, %FbA* null, i32 1) to i64), i1 false)
133+
%vtable = getelementptr inbounds %FbA, %FbA* %instanceFbA, i32 0, i32 0
134+
%deref = load %VTableFbA*, %VTableFbA** %vtable, align 8
135+
%foo = getelementptr inbounds %VTableFbA, %VTableFbA* %deref, i32 0, i32 0
136+
%1 = load i16 (%FbA*)*, i16 (%FbA*)** %foo, align 8
137+
%call = call i16 %1(%FbA* %instanceFbA)
134138
ret void
135139
}
136140
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// RUN: (%COMPILE %s && %RUN) | %CHECK %s
2+
3+
TYPE VtableFbA:
4+
STRUCT
5+
methodeDefinedInA: POINTER TO FbA.methodeDefinedInA := ADR(FbA.methodeDefinedInA);
6+
END_STRUCT
7+
END_TYPE
8+
9+
VAR_GLOBAL
10+
instanceVtableFbA: VtableFbA;
11+
END_VAR
12+
13+
FUNCTION_BLOCK FbA
14+
VAR
15+
vtable: POINTER TO VtableFbA := ADR(instanceVtableFbA);
16+
END_VAR
17+
18+
METHOD methodeDefinedInA: DINT
19+
printf('Hello from FbA::methodeDefinedInA$N');
20+
END_METHOD
21+
END_FUNCTION_BLOCK
22+
23+
FUNCTION main
24+
VAR
25+
instanceFbA: FbA;
26+
END_VAR
27+
28+
instanceFbA.vtable^.methodeDefinedInA^(instanceFbA); // CHECK: Hello from FbA::methodeDefinedInA
29+
END_FUNCTION
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// RUN: (%COMPILE %s && %RUN) | %CHECK %s
2+
3+
// -- FbA
4+
TYPE VtableFbA:
5+
STRUCT
6+
methodDefinedInA_One: POINTER TO FbA.methodDefinedInA_One := ADR(FbA.methodDefinedInA_One);
7+
methodDefinedInA_Two: POINTER TO FbA.methodDefinedInA_Two := ADR(FbA.methodDefinedInA_Two);
8+
END_STRUCT
9+
END_TYPE
10+
11+
FUNCTION_BLOCK FbA
12+
VAR
13+
vtable: POINTER TO VtableFbA;
14+
oneA: DINT := 1;
15+
twoA: DINT := 2;
16+
END_VAR
17+
18+
METHOD methodDefinedInA_One: DINT
19+
printf('Hello from FbA::methodDefinedInA_One (%d, %d)$N', oneA, twoA);
20+
END_METHOD
21+
22+
METHOD methodDefinedInA_Two: DINT
23+
printf('Hello from FbA::methodDefinedInA_Two (%d, %d)$N', oneA, twoA);
24+
END_METHOD
25+
END_FUNCTION_BLOCK
26+
27+
// -- FbB (overrides methodDefinedInA_Two)
28+
TYPE VtableFbB:
29+
STRUCT
30+
vtableA: VtableFbA := (
31+
methodDefinedInA_One := ADR(FbA.methodDefinedInA_One),
32+
methodDefinedInA_Two := ADR(FbB.methodDefinedInA_Two) // Overridden
33+
);
34+
methodDefinedInB_One: POINTER TO FbB.methodDefinedInB_One := ADR(FbB.methodDefinedInB_One);
35+
END_STRUCT
36+
END_TYPE
37+
38+
FUNCTION_BLOCK FbB EXTENDS FbA
39+
VAR
40+
threeB: DINT := 3;
41+
fourB: DINT := 4;
42+
END_VAR
43+
44+
// Overridden
45+
METHOD methodDefinedInA_Two: DINT
46+
printf('Hello from FbB::methodDefinedInA_Two (%d, %d, %d, %d) (OVERRIDDEN)$N', oneA, twoA, threeB, fourB);
47+
END_METHOD
48+
49+
METHOD methodDefinedInB_One: DINT
50+
printf('Hello from FbB::methodDefinedInB_One (%d, %d)$N', threeB, fourB);
51+
END_METHOD
52+
END_FUNCTION_BLOCK
53+
54+
VAR_GLOBAL
55+
instanceVTableFbA: VtableFbA;
56+
instanceVTableFbB: VtableFbB;
57+
END_VAR
58+
59+
FUNCTION main
60+
VAR
61+
instanceFbA: FbA;
62+
instanceFbB: FbB;
63+
64+
refInstance: POINTER TO FbA;
65+
END_VAR
66+
67+
instanceFbA.vtable := ADR(instanceVTableFbA);
68+
instanceFbB.vtable := ADR(instanceVTableFbB);
69+
70+
refInstance := ADR(instanceFbA);
71+
refInstance^.vtable^.methodDefinedInA_One^(refInstance^); // CHECK: Hello from FbA::methodDefinedInA_One (1, 2)
72+
refInstance^.vtable^.methodDefinedInA_Two^(refInstance^); // CHECK: Hello from FbA::methodDefinedInA_Two (1, 2)
73+
74+
refInstance := ADR(instanceFbB);
75+
refInstance^.vtable^.methodDefinedInA_One^(refInstance^); // CHECK: Hello from FbA::methodDefinedInA_One (1, 2)
76+
refInstance^.vtable^.methodDefinedInA_Two^(refInstance^); // CHECK: Hello from FbB::methodDefinedInA_Two (1, 2, 3, 4) (OVERRIDDEN)
77+
END_FUNCTION

0 commit comments

Comments
 (0)