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
Edited by Fibonacci