[fpc-pascal] Listing the type (even as string) of the parameters and the return of a function

silvioprog silvioprog at gmail.com
Sat Nov 3 17:18:13 CET 2018


On Thu, Nov 1, 2018 at 2:11 AM silvioprog <silvioprog at gmail.com> wrote:
[...]

> I took a look at some System V ABI manuals to start a draft based on them,
> adapting the assembly to the InvokeKernelWin64() signature idea. The
> draft works fine for six or more arguments and returns the function value
> too, but I need to check (probably next weekend) how to pass floating-point
> values to the XMM registers (I'm looking for references/manuals about).
>

Finally, I found a awesome material to study: the GCC's X86-64 assembly for
compiler writers. And after some successful tests, I concluded that:

- floating-point types with size 8 or less (double, single etc.) must be
set in XMM registers aligned in 8;
- floating-point types larger than 8 (extended) must be pushed to the stack
aligned in 10.

This is a small example to check it (environment used in the tests: Lazarus
2.1.0 r59363 FPC 3.1.1 x86_64-linux-gtk2):

===
program project1;

{$MODE DELPHI}
{$MACRO ON}
//{$DEFINE USE_EXTENDED}
{$IFDEF USE_EXTENDED}
 {$DEFINE FLOAT_TYPE := extended} // size 10
{$ELSE}
 {$DEFINE FLOAT_TYPE := double} // size 8
{$ENDIF}

uses sysutils;

procedure test(const a, b: FLOAT_TYPE);
begin
  writeln(a:0:2, ' - ', b:0:2);
end;

procedure call_test(arr: pointer; f: codepointer); assembler; nostackframe;
asm
  { save the base pointer }
  pushq %rbp
  { set new base pointer }
  movq  %rsp, %rbp

  { save callee-saved registers }
  pushq %rbx
  pushq %r12
  pushq %r13
  pushq %r14
  pushq %r15

{$IFDEF USE_EXTENDED}
  leaq 0(%rdi), %rdx
  movq (%rdx), %rax
  movq %rax, (%rsp)
  movq 0x8(%rdx), %ax
  movq %ax, 0x8(%rsp)

  leaq 10(%rdi), %rax
  movq (%rax), %rdx
  movq %rdx, 0x10(%rsp)
  movq 0x8(%rax), %ax
  movq %ax, 0x18(%rsp)
{$ELSE}
  movq 0(%rdi), %xmm0
  movq 8(%rdi), %xmm1
{$ENDIF}

  { call the function }
  callq *%rsi

  { restore callee-saved registers }
  popq %r15
  popq %r14
  popq %r13
  popq %r12
  popq %rbx

  { reset stack to base pointer }
  movq %rbp, %rsp
  { restore the old base pointer }
  popq %rbp
  { return to caller }
  retq
end;

var
  arr: array of FLOAT_TYPE;
begin
  Writeln(IntToStr(SizeOf(FLOAT_TYPE)));
{$PUSH}{$WARN 5090 OFF}
  setlength(arr, 2);
{$POP}
  arr[0] := 12.34;
  arr[1] := 45.67;
  call_test(@arr[0], @test);
end.
===

and the results was:

//{$DEFINE USE_EXTENDED}:

===
...
8
12.34 - 45.67
===

{$DEFINE USE_EXTENDED}:

===
...
10
12.34 - 45.67
===

I'm going to clone the Free Pascal repository from Github to work on this
feature (sysv ABI for Linux 64 for now). After some functional code I'll
send it as patch to the Mantis issues. I'm very interested in rtti.invoke()
support on Linux/ARM and Win32. :-)

(P.S.: Could you check the issue #34496? I'm not sure if saving the base
pointer is best way to solve the problem, but at least fixed the AV for
extended types)

--
Silvio Clécio
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/fpc-pascal/attachments/20181103/d36d2ffa/attachment.html>


More information about the fpc-pascal mailing list