Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2014-11

Question about functions returning a string

8 messages · 5 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Ewald

Hi,

Take the following function prototype (in {$mode objfpc}{$H+} for the record):

    Function SomeFunction(const Data: PChar; const Len: LongWord):
String; cdecl; public;

Looking at the dissasembly of this function, I see that is actually has three arguments. It looks more like this from an assembler perspective:

    Function SomeFunction(HiddenArgument: Pointer; const Data: PChar;
const Len: LongWord): String; cdecl; public;

Which is, well, quite fascinating really. What is it doing there? I suspect it has something to do with the result type of the function, being a string?

Can anybody shed some light on this?

Ewald

Reply by email

Flávio Etrusco
to Ewald
Ewald wrote 22 lines
Hi, Take the following function prototype (in {$mode objfpc}{$H+} for the record): Function SomeFunction(const Data: PChar; const Len: LongWord): String; cdecl; public; Looking at the dissasembly of this function, I see that is actually has three arguments. It looks more like this from an assembler perspective: Function SomeFunction(HiddenArgument: Pointer; const Data: PChar; const Len: LongWord): String; cdecl; public; Which is, well, quite fascinating really. What is it doing there? I suspect it has something to do with the result type of the function, being a string? Can anybody shed some light on this? -- Ewald

Are you sure it's not the result that is passed in the first parameter?

http://en.wikipedia.org/wiki/X86_calling_conventions#cdecl

Best regards,
Flávio

Reply by email

Ewald
to Flávio Etrusco
Flávio Etrusco wrote
Are you sure it's not the result that is passed in the first parameter? http://en.wikipedia.org/wiki/X86_calling_conventions#cdecl

Good question, but I don't think so. The first few lines of assembly from this function seem to read three arguments you see:

44b360: 53 push %rbx
44b361: 41 54 push %r12
44b363: 41 55 push %r13
44b365: 48 89 fb mov %rdi,%rbx <-- first argument, %rdi
44b368: 41 89 f4 mov %esi,%r12d <-- second argument, %rsi
44b36b: 49 89 d5 mov %rdx,%r13 <-- third argument, %rdx

What I forgot to mention was that this is on a x86_64 architecture, so I based myself on the table found at
http://wiki.osdev.org/Calling_Conventions .

Ewald

Reply by email

Sven Barth
to Ewald
Ewald wrote 22 lines
On 11/29/2014 12:41 AM, Flávio Etrusco wrote: > Are you sure it's not the result that is passed in the first parameter? > > http://en.wikipedia.org/wiki/X86_calling_conventions#cdecl Good question, but I don't think so. The first few lines of assembly from this function seem to read three arguments you see: 44b360: 53 push %rbx 44b361: 41 54 push %r12 44b363: 41 55 push %r13 44b365: 48 89 fb mov %rdi,%rbx <-- first argument, %rdi 44b368: 41 89 f4 mov %esi,%r12d <-- second argument, %rsi 44b36b: 49 89 d5 mov %rdx,%r13 <-- third argument, %rdx What I forgot to mention was that this is on a x86_64 architecture, so I based myself on the table found at http://wiki.osdev.org/Calling_Conventions .

Just compile with "-al" and you'll see what the compiler uses the parameters for (the following example is for i386):

=== listing begin ===

.section .text
.balign 16,0x90
.globl P$TCALLCONV_SOMEFUNCTION$PCHAR$LONGWORD$$ANSISTRING .type P$TCALLCONV_SOMEFUNCTION$PCHAR$LONGWORD$$ANSISTRING,@function P$TCALLCONV_SOMEFUNCTION$PCHAR$LONGWORD$$ANSISTRING: .Lc1:
# Temps allocated between ebp-524 and ebp-12
# [callconv.pp]
# [6] begin
pushl %ebp
.Lc3:
.Lc4:
movl %esp,%ebp
.Lc5:
subl $524,%esp
# Var aData located at ebp-4
# Var aLen located at ebp-8
# Var $result located at ebp-12
movl %eax,-4(%ebp)
movl %edx,-8(%ebp)
movl %ecx,-12(%ebp)
# [7] Result := Copy(StrPas(aData), 1, aLen);
leal -268(%ebp),%eax
pushl %eax
leal -524(%ebp),%edx
movl -4(%ebp),%eax
call SYSTEM_STRPAS$PCHAR$$SHORTSTRING
leal -524(%ebp),%eax
movl -8(%ebp),%ecx
movl $1,%edx
call fpc_shortstr_copy
leal -268(%ebp),%eax
movl -12(%ebp),%edx
call fpc_shortstr_to_ansistr
# [8] end;
leave
ret
.Lc2:
.Le0:
.size P$TCALLCONV_SOMEFUNCTION$PCHAR$LONGWORD$$ANSISTRING, .Le0 - P$TCALLCONV_SOMEFUNCTION$PCHAR$LONGWORD$$ANSISTRING

=== listing end ===

In general managed types (which a (Ansi)String is) are passed as parameters.

Regards,
Sven

Reply by email

Ewald
to Sven Barth
Sven Barth wrote
In general managed types (which a (Ansi)String is) are passed as parameters.

That is very interesting knowledge. Thanks!

So in general, one should not use managed types in the prototype of an exported (public) function? While I do know that the other language can't do anything useful with it, my thought was that it would be possible to pass along these managed types (especially string, as it is a pointer internally) to another pascal function (a callback in my case).

Ewald

Reply by email

leledumbo
to Ewald
So in general, one should not use managed types in the prototype of an

exported (public) function?

Bingo. At least not until we have properly sharable RTL.

my thought was that it would be

possible to pass along these managed types (especially string, as it is a pointer internally) to another pascal function (a callback in my case).

You can still pass pointer to its first element as a PChar, treating it read-only in the caller for safety reason (though it's possible to make it writable as well, but the safety burden is propagated to the caller).

View this message in context: http://free-pascal-general.1045716.n5.nabble.com/Question-about-functions-returning-a-string-tp5720544p5720552.html Sent from the Free Pascal - General mailing list .

Reply by email

Ewald
to leledumbo
leledumbo wrote
> So in general, one should not use managed types in the prototype of an > exported (public) function? Bingo. At least not until we have properly sharable RTL.

The problem lies not with a sharable RTL. As mentioned, I do not want to /use/ these managed types in another language. I just want to pass them along :-)

Show quoted text 7 lines
> my thought was that it would be > possible to pass along these managed types (especially string, as it is > a pointer internally) to another pascal function (a callback in my case). You can still pass pointer to its first element as a PChar, treating it read-only in the caller for safety reason (though it's possible to make it writable as well, but the safety burden is propagated to the caller).

Actually I was trying to avoid PChar's ;-)

In the meanwhile, I've fixed my issue by not returning a string as a result, but as an out parameter:

Function Bla: String;

... becomes ...

Procedure Bla(out Result: String);

This seems to work. How portable it is, I do not know, I guess time will be the judge and jury on that.

Anyway, thanks to you all!

Ewald

Reply by email

Dan
to Ewald: Take the following function prototype (in {$mode objfpc}{$H+} for the record): Function…
"Ewald" wrote 28 lines
Hi, Take the following function prototype (in {$mode objfpc}{$H+} for the record): Function SomeFunction(const Data: PChar; const Len: LongWord): String; cdecl; public; Looking at the dissasembly of this function, I see that is actually has three arguments. It looks more like this from an assembler perspective: Function SomeFunction(HiddenArgument: Pointer; const Data: PChar; const Len: LongWord): String; cdecl; public; Which is, well, quite fascinating really. What is it doing there? I suspect it has something to do with the result type of the function, being a string? Can anybody shed some light on this? -- Ewald _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply by email