Skip to content

Commit 237313c

Browse files
committed
refactor: Change order of vtable member fields
Moves the `__body` field right after the "parent" vtable field if it exists. Also add introduce some further vtable specific codegen tests.
1 parent 2dd01f8 commit 237313c

File tree

7 files changed

+999
-608
lines changed

7 files changed

+999
-608
lines changed

src/codegen/tests/initialization_test.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ mod complex_initializers;
22
mod global_initializers;
33
mod pou_initializers;
44
mod type_initializers;
5+
mod vtable_initializers;
Lines changed: 379 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,379 @@
1+
use driver::generate_to_string;
2+
use plc_source::SourceCode;
3+
4+
fn codegen(source: &str) -> String {
5+
generate_to_string("Test", vec![SourceCode::from(source)]).unwrap()
6+
}
7+
8+
#[test]
9+
fn function_block_without_parent() {
10+
let result = codegen(
11+
"
12+
FUNCTION_BLOCK fb
13+
METHOD foo
14+
END_METHOD
15+
END_FUNCTION_BLOCK
16+
",
17+
);
18+
19+
insta::assert_snapshot!(result, @r###"
20+
; ModuleID = '<internal>'
21+
source_filename = "<internal>"
22+
23+
%fb = type { i32* }
24+
%__vtable_fb_type = type { i32*, i32* }
25+
26+
@__fb__init = constant %fb zeroinitializer
27+
@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @__init___Test, i8* null }]
28+
@____vtable_fb_type__init = constant %__vtable_fb_type zeroinitializer
29+
@__vtable_fb = global %__vtable_fb_type zeroinitializer
30+
31+
define void @fb(%fb* %0) {
32+
entry:
33+
%__vtable = getelementptr inbounds %fb, %fb* %0, i32 0, i32 0
34+
ret void
35+
}
36+
37+
define void @fb_foo(%fb* %0) {
38+
entry:
39+
%__vtable = getelementptr inbounds %fb, %fb* %0, i32 0, i32 0
40+
ret void
41+
}
42+
43+
define void @__init___vtable_fb_type(%__vtable_fb_type* %0) {
44+
entry:
45+
%self = alloca %__vtable_fb_type*, align 8
46+
store %__vtable_fb_type* %0, %__vtable_fb_type** %self, align 8
47+
ret void
48+
}
49+
50+
define void @__init_fb(%fb* %0) {
51+
entry:
52+
%self = alloca %fb*, align 8
53+
store %fb* %0, %fb** %self, align 8
54+
%deref = load %fb*, %fb** %self, align 8
55+
%__vtable = getelementptr inbounds %fb, %fb* %deref, i32 0, i32 0
56+
store i32* bitcast (%__vtable_fb_type* @__vtable_fb to i32*), i32** %__vtable, align 8
57+
ret void
58+
}
59+
60+
define void @__user_init_fb(%fb* %0) {
61+
entry:
62+
%self = alloca %fb*, align 8
63+
store %fb* %0, %fb** %self, align 8
64+
ret void
65+
}
66+
67+
define void @__init___Test() {
68+
entry:
69+
call void @__init___vtable_fb_type(%__vtable_fb_type* @__vtable_fb)
70+
ret void
71+
}
72+
"###);
73+
}
74+
75+
#[test]
76+
fn function_block_with_parent() {
77+
let result = codegen(
78+
"
79+
FUNCTION_BLOCK parent
80+
METHOD foo
81+
END_METHOD
82+
END_FUNCTION_BLOCK
83+
84+
FUNCTION_BLOCK child EXTENDS parent
85+
METHOD bar
86+
END_METHOD
87+
END_FUNCTION_BLOCK
88+
",
89+
);
90+
91+
insta::assert_snapshot!(result, @r###"
92+
; ModuleID = '<internal>'
93+
source_filename = "<internal>"
94+
95+
%parent = type { i32* }
96+
%child = type { %parent }
97+
%__vtable_parent_type = type { i32*, i32* }
98+
%__vtable_child_type = type { %__vtable_parent_type, i32*, i32* }
99+
100+
@__parent__init = constant %parent zeroinitializer
101+
@__child__init = constant %child zeroinitializer
102+
@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @__init___Test, i8* null }]
103+
@____vtable_parent_type__init = constant %__vtable_parent_type zeroinitializer
104+
@__vtable_parent = global %__vtable_parent_type zeroinitializer
105+
@____vtable_child_type__init = constant %__vtable_child_type zeroinitializer
106+
@__vtable_child = global %__vtable_child_type zeroinitializer
107+
108+
define void @parent(%parent* %0) {
109+
entry:
110+
%__vtable = getelementptr inbounds %parent, %parent* %0, i32 0, i32 0
111+
ret void
112+
}
113+
114+
define void @parent_foo(%parent* %0) {
115+
entry:
116+
%__vtable = getelementptr inbounds %parent, %parent* %0, i32 0, i32 0
117+
ret void
118+
}
119+
120+
define void @child(%child* %0) {
121+
entry:
122+
%__parent = getelementptr inbounds %child, %child* %0, i32 0, i32 0
123+
ret void
124+
}
125+
126+
define void @child_bar(%child* %0) {
127+
entry:
128+
%__parent = getelementptr inbounds %child, %child* %0, i32 0, i32 0
129+
ret void
130+
}
131+
132+
define void @__init___vtable_parent_type(%__vtable_parent_type* %0) {
133+
entry:
134+
%self = alloca %__vtable_parent_type*, align 8
135+
store %__vtable_parent_type* %0, %__vtable_parent_type** %self, align 8
136+
ret void
137+
}
138+
139+
define void @__init___vtable_child_type(%__vtable_child_type* %0) {
140+
entry:
141+
%self = alloca %__vtable_child_type*, align 8
142+
store %__vtable_child_type* %0, %__vtable_child_type** %self, align 8
143+
%deref = load %__vtable_child_type*, %__vtable_child_type** %self, align 8
144+
%__vtable_parent_type = getelementptr inbounds %__vtable_child_type, %__vtable_child_type* %deref, i32 0, i32 0
145+
call void @__init___vtable_parent_type(%__vtable_parent_type* %__vtable_parent_type)
146+
ret void
147+
}
148+
149+
define void @__init_parent(%parent* %0) {
150+
entry:
151+
%self = alloca %parent*, align 8
152+
store %parent* %0, %parent** %self, align 8
153+
%deref = load %parent*, %parent** %self, align 8
154+
%__vtable = getelementptr inbounds %parent, %parent* %deref, i32 0, i32 0
155+
store i32* bitcast (%__vtable_parent_type* @__vtable_parent to i32*), i32** %__vtable, align 8
156+
ret void
157+
}
158+
159+
define void @__init_child(%child* %0) {
160+
entry:
161+
%self = alloca %child*, align 8
162+
store %child* %0, %child** %self, align 8
163+
%deref = load %child*, %child** %self, align 8
164+
%__parent = getelementptr inbounds %child, %child* %deref, i32 0, i32 0
165+
call void @__init_parent(%parent* %__parent)
166+
%deref1 = load %child*, %child** %self, align 8
167+
%__parent2 = getelementptr inbounds %child, %child* %deref1, i32 0, i32 0
168+
%__vtable = getelementptr inbounds %parent, %parent* %__parent2, i32 0, i32 0
169+
store i32* bitcast (%__vtable_child_type* @__vtable_child to i32*), i32** %__vtable, align 8
170+
ret void
171+
}
172+
173+
define void @__user_init_child(%child* %0) {
174+
entry:
175+
%self = alloca %child*, align 8
176+
store %child* %0, %child** %self, align 8
177+
%deref = load %child*, %child** %self, align 8
178+
%__parent = getelementptr inbounds %child, %child* %deref, i32 0, i32 0
179+
call void @__user_init_parent(%parent* %__parent)
180+
ret void
181+
}
182+
183+
define void @__user_init_parent(%parent* %0) {
184+
entry:
185+
%self = alloca %parent*, align 8
186+
store %parent* %0, %parent** %self, align 8
187+
ret void
188+
}
189+
190+
define void @__init___Test() {
191+
entry:
192+
call void @__init___vtable_parent_type(%__vtable_parent_type* @__vtable_parent)
193+
call void @__init___vtable_child_type(%__vtable_child_type* @__vtable_child)
194+
ret void
195+
}
196+
"###);
197+
}
198+
199+
#[test]
200+
fn function_block_with_parent_chained() {
201+
let result = codegen(
202+
"
203+
FUNCTION_BLOCK grandparent
204+
METHOD foo
205+
END_METHOD
206+
END_FUNCTION_BLOCK
207+
208+
FUNCTION_BLOCK parent EXTENDS grandparent
209+
METHOD bar
210+
END_METHOD
211+
END_FUNCTION_BLOCK
212+
213+
FUNCTION_BLOCK child EXTENDS parent
214+
METHOD baz
215+
END_METHOD
216+
END_FUNCTION_BLOCK
217+
",
218+
);
219+
220+
insta::assert_snapshot!(result, @r###"
221+
; ModuleID = '<internal>'
222+
source_filename = "<internal>"
223+
224+
%parent = type { %grandparent }
225+
%grandparent = type { i32* }
226+
%child = type { %parent }
227+
%__vtable_grandparent_type = type { i32*, i32* }
228+
%__vtable_parent_type = type { %__vtable_grandparent_type, i32*, i32* }
229+
%__vtable_child_type = type { %__vtable_parent_type, i32*, i32* }
230+
231+
@__parent__init = constant %parent zeroinitializer
232+
@__grandparent__init = constant %grandparent zeroinitializer
233+
@__child__init = constant %child zeroinitializer
234+
@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @__init___Test, i8* null }]
235+
@____vtable_grandparent_type__init = constant %__vtable_grandparent_type zeroinitializer
236+
@__vtable_grandparent = global %__vtable_grandparent_type zeroinitializer
237+
@____vtable_parent_type__init = constant %__vtable_parent_type zeroinitializer
238+
@__vtable_parent = global %__vtable_parent_type zeroinitializer
239+
@____vtable_child_type__init = constant %__vtable_child_type zeroinitializer
240+
@__vtable_child = global %__vtable_child_type zeroinitializer
241+
242+
define void @grandparent(%grandparent* %0) {
243+
entry:
244+
%__vtable = getelementptr inbounds %grandparent, %grandparent* %0, i32 0, i32 0
245+
ret void
246+
}
247+
248+
define void @grandparent_foo(%grandparent* %0) {
249+
entry:
250+
%__vtable = getelementptr inbounds %grandparent, %grandparent* %0, i32 0, i32 0
251+
ret void
252+
}
253+
254+
define void @parent(%parent* %0) {
255+
entry:
256+
%__grandparent = getelementptr inbounds %parent, %parent* %0, i32 0, i32 0
257+
ret void
258+
}
259+
260+
define void @parent_bar(%parent* %0) {
261+
entry:
262+
%__grandparent = getelementptr inbounds %parent, %parent* %0, i32 0, i32 0
263+
ret void
264+
}
265+
266+
define void @child(%child* %0) {
267+
entry:
268+
%__parent = getelementptr inbounds %child, %child* %0, i32 0, i32 0
269+
ret void
270+
}
271+
272+
define void @child_baz(%child* %0) {
273+
entry:
274+
%__parent = getelementptr inbounds %child, %child* %0, i32 0, i32 0
275+
ret void
276+
}
277+
278+
define void @__init___vtable_grandparent_type(%__vtable_grandparent_type* %0) {
279+
entry:
280+
%self = alloca %__vtable_grandparent_type*, align 8
281+
store %__vtable_grandparent_type* %0, %__vtable_grandparent_type** %self, align 8
282+
ret void
283+
}
284+
285+
define void @__init___vtable_parent_type(%__vtable_parent_type* %0) {
286+
entry:
287+
%self = alloca %__vtable_parent_type*, align 8
288+
store %__vtable_parent_type* %0, %__vtable_parent_type** %self, align 8
289+
%deref = load %__vtable_parent_type*, %__vtable_parent_type** %self, align 8
290+
%__vtable_grandparent_type = getelementptr inbounds %__vtable_parent_type, %__vtable_parent_type* %deref, i32 0, i32 0
291+
call void @__init___vtable_grandparent_type(%__vtable_grandparent_type* %__vtable_grandparent_type)
292+
ret void
293+
}
294+
295+
define void @__init___vtable_child_type(%__vtable_child_type* %0) {
296+
entry:
297+
%self = alloca %__vtable_child_type*, align 8
298+
store %__vtable_child_type* %0, %__vtable_child_type** %self, align 8
299+
%deref = load %__vtable_child_type*, %__vtable_child_type** %self, align 8
300+
%__vtable_parent_type = getelementptr inbounds %__vtable_child_type, %__vtable_child_type* %deref, i32 0, i32 0
301+
call void @__init___vtable_parent_type(%__vtable_parent_type* %__vtable_parent_type)
302+
ret void
303+
}
304+
305+
define void @__init_parent(%parent* %0) {
306+
entry:
307+
%self = alloca %parent*, align 8
308+
store %parent* %0, %parent** %self, align 8
309+
%deref = load %parent*, %parent** %self, align 8
310+
%__grandparent = getelementptr inbounds %parent, %parent* %deref, i32 0, i32 0
311+
call void @__init_grandparent(%grandparent* %__grandparent)
312+
%deref1 = load %parent*, %parent** %self, align 8
313+
%__grandparent2 = getelementptr inbounds %parent, %parent* %deref1, i32 0, i32 0
314+
%__vtable = getelementptr inbounds %grandparent, %grandparent* %__grandparent2, i32 0, i32 0
315+
store i32* bitcast (%__vtable_parent_type* @__vtable_parent to i32*), i32** %__vtable, align 8
316+
ret void
317+
}
318+
319+
define void @__init_grandparent(%grandparent* %0) {
320+
entry:
321+
%self = alloca %grandparent*, align 8
322+
store %grandparent* %0, %grandparent** %self, align 8
323+
%deref = load %grandparent*, %grandparent** %self, align 8
324+
%__vtable = getelementptr inbounds %grandparent, %grandparent* %deref, i32 0, i32 0
325+
store i32* bitcast (%__vtable_grandparent_type* @__vtable_grandparent to i32*), i32** %__vtable, align 8
326+
ret void
327+
}
328+
329+
define void @__init_child(%child* %0) {
330+
entry:
331+
%self = alloca %child*, align 8
332+
store %child* %0, %child** %self, align 8
333+
%deref = load %child*, %child** %self, align 8
334+
%__parent = getelementptr inbounds %child, %child* %deref, i32 0, i32 0
335+
call void @__init_parent(%parent* %__parent)
336+
%deref1 = load %child*, %child** %self, align 8
337+
%__parent2 = getelementptr inbounds %child, %child* %deref1, i32 0, i32 0
338+
%__grandparent = getelementptr inbounds %parent, %parent* %__parent2, i32 0, i32 0
339+
%__vtable = getelementptr inbounds %grandparent, %grandparent* %__grandparent, i32 0, i32 0
340+
store i32* bitcast (%__vtable_child_type* @__vtable_child to i32*), i32** %__vtable, align 8
341+
ret void
342+
}
343+
344+
define void @__user_init_grandparent(%grandparent* %0) {
345+
entry:
346+
%self = alloca %grandparent*, align 8
347+
store %grandparent* %0, %grandparent** %self, align 8
348+
ret void
349+
}
350+
351+
define void @__user_init_child(%child* %0) {
352+
entry:
353+
%self = alloca %child*, align 8
354+
store %child* %0, %child** %self, align 8
355+
%deref = load %child*, %child** %self, align 8
356+
%__parent = getelementptr inbounds %child, %child* %deref, i32 0, i32 0
357+
call void @__user_init_parent(%parent* %__parent)
358+
ret void
359+
}
360+
361+
define void @__user_init_parent(%parent* %0) {
362+
entry:
363+
%self = alloca %parent*, align 8
364+
store %parent* %0, %parent** %self, align 8
365+
%deref = load %parent*, %parent** %self, align 8
366+
%__grandparent = getelementptr inbounds %parent, %parent* %deref, i32 0, i32 0
367+
call void @__user_init_grandparent(%grandparent* %__grandparent)
368+
ret void
369+
}
370+
371+
define void @__init___Test() {
372+
entry:
373+
call void @__init___vtable_grandparent_type(%__vtable_grandparent_type* @__vtable_grandparent)
374+
call void @__init___vtable_parent_type(%__vtable_parent_type* @__vtable_parent)
375+
call void @__init___vtable_child_type(%__vtable_child_type* @__vtable_child)
376+
ret void
377+
}
378+
"###);
379+
}

0 commit comments

Comments
 (0)