Inlined functions use passed variables as reference or pointer. In some rare cases.
Summary
Inlined function use passed variables as reference or pointer.
What is the current bug behavior?
Inlined functions in some cases use passed to it variables as it was reference or pointer. It happens on both x86 and x64.
What is the expected (correct) behavior?
Value of variable should be copied and then inline function should work on it's own copy of value.
System Information
- Operating system: Windows 10 Pro
- Processor architecture: x86-64
- Compiler version: 3.3.1
- Device: Computer
Steps to reproduce
Code samples attached below. In this case it only happens if both functions are inlined. If one of them is not inline, the problem will not exist.
Compiled this code in Delphi and there was no problem, it's FPC bug.
Example Project
Integer version:
program magic_int;
procedure test(x: integer); inline;
begin
x := 1234;
end;
procedure main; inline;
var
int_test: integer;
begin
//set some integer
int_test := 555;
//call function that "does nothing"
test(int_test);
//expected "555", shows "1234"
writeln(int_test);
readln;
end;
begin
main;
end.
And string version:
program magic_string;
procedure test(s: string); inline;
begin
s := 'magic';
end;
procedure main; inline;
var
some_string: string;
begin
//set some string
some_string := 'some value';
//call function that "does nothing"
test(some_string);
//expected "some value", shows "magic"
writeln(some_string);
readln;
end;
begin
main;
end.
Relevant logs and/or screenshots
From debugger, x86 version:
push ebp
mov ebp,esp
lea esp,dword ptr ss:[esp-0x4]
push ebx
call magic_in.00403660
mov dword ptr ss:[ebp-0x4],0x22b ; set 555
mov dword ptr ss:[ebp-0x4],0x4d2 ; set 1234, should not
call magic_in.00406650
mov ebx,eax
mov ecx,dword ptr ss:[ebp-0x4]
mov edx,ebx
mov eax,0x0
call magic_in.004068d0
call magic_in.00403620
mov eax,ebx
call magic_in.00406760
call magic_in.00403620
call magic_in.00406630
mov ebx,eax
mov eax,ebx
call magic_in.00406a60
call magic_in.00403620
call magic_in.00403920
retn
ASMLIST generated by FPC:
.section .text.n_p$magic_int_$$_main,"ax"
.balign 16,0x90
.globl P$MAGIC_INT_$$_MAIN
P$MAGIC_INT_$$_MAIN:
# Temps allocated between ebp-8 and ebp-4
# [11] begin
pushl %ebp
movl %esp,%ebp
leal -8(%esp),%esp
pushl %ebx
# Var int_test located at ebp-4, size=OS_S32
# [13] int_test := 555;
movl $555,-4(%ebp)
# [16] test(int_test);
movl -4(%ebp),%eax
movl %eax,-8(%ebp) ; these 2 lines are inline function "test"
movl $1234,-8(%ebp) ; these 2 lines are inline function "test"
# [19] writeln(int_test);
call fpc_get_output
movl %eax,%ebx
movl %ebx,%edx
movl -4(%ebp),%ecx
movl $0,%eax
call fpc_write_text_sint
call fpc_iocheck
movl %ebx,%eax
call fpc_writeln_end
call fpc_iocheck
# [21] readln;
call fpc_get_input
movl %eax,%ebx
movl %ebx,%eax
call fpc_readln_end
call fpc_iocheck
# [22] end;
popl %ebx
movl %ebp,%esp
popl %ebp
ret
.section .text.n__main,"ax"
.balign 16,0x90
.globl _main
_main:
.globl PASCALMAIN
PASCALMAIN:
# Temps allocated between ebp-4 and ebp+0
# [24] begin
pushl %ebp
movl %esp,%ebp
leal -4(%esp),%esp
pushl %ebx
call fpc_initializeunits
# [25] main;
movl $555,-4(%ebp)
movl $1234,-4(%ebp) ; and here it happens
call fpc_get_output
movl %eax,%ebx
movl -4(%ebp),%ecx
movl %ebx,%edx
movl $0,%eax
call fpc_write_text_sint
call fpc_iocheck
movl %ebx,%eax
call fpc_writeln_end
call fpc_iocheck
call fpc_get_input
movl %eax,%ebx
movl %ebx,%eax
call fpc_readln_end
call fpc_iocheck
# [26] end.
call fpc_do_exit
ret