Sign in Join

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

Mailing lists / fpc-pascal / 2009-08

Porting Delphi ASM code to FPC

9 messages · 3 people ·

Reply by email Subscribe to this list Your subscription

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

Graeme Geldenhuys

Hi,

I have ported the DUnit2 testing framework from Delphi to FPC. DUnit2 works perfectly under 32bit FPC, but I am getting a compiler error when trying to compile DUnit2 with 64bit FPC. The error 'Unknown identifier "EAX"' occurs in the first line of function CallerAddr(...).

I know that using ASM is not portable in FPC. CallerAddr() is used is the raise <exception> at <address> call in method Fail(...) shown below.

Is there an existing function in FPC that does the same as CallerAddr(..), but in a cross platform way? Alternatively, how can I solve this compiler error under 64bit FPC (currently testing under 64bit Linux).

function CallerAddr: Pointer; assembler;
const

  CallerIP = $4;

asm
mov eax, ebp
call IsBadPointer
test eax,eax
jne @@Error

mov eax, [ebp].CallerIP
sub eax, 5 // 5 bytes for call

push eax
call IsBadPointer
test eax,eax
pop eax
je @@Finish

@@Error:
xor eax, eax
@@Finish:
end;

procedure TTestProc.Fail(const ErrorMsg: string; const ErrorAddress:
Pointer);
begin
//  raise ETestFailure.Create(ErrorMsg);
  if ErrorAddress = nil then
    raise ETestFailure.Create(ErrorMsg) at CallerAddr
  else
    raise ETestFailure.Create(ErrorMsg) at ErrorAddress;
end;

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://opensoft.homeip.net/fpgui/

Reply by email

Jonas Maebe
to Graeme Geldenhuys
Graeme Geldenhuys wrote 6 lines
I have ported the DUnit2 testing framework from Delphi to FPC. DUnit2 works perfectly under 32bit FPC, but I am getting a compiler error when trying to compile DUnit2 with 64bit FPC. The error 'Unknown identifier "EAX"' occurs in the first line of function CallerAddr(...).

That's because we don't support Intel assembler syntax for x86_64.

Show quoted text 6 lines
I know that using ASM is not portable in FPC. CallerAddr() is used is the raise <exception> at <address> call in method Fail(...) shown below. Is there an existing function in FPC that does the same as CallerAddr(..), but in a cross platform way?

get_caller_addr(get_frame)

Alternatively, how can I solve this compiler error under 64bit FPC (currently testing under 64bit Linux).

It would crash (or at the very least give wrong results) if you'd solve the compiler errors.

Jonas

Reply by email

Graeme Geldenhuys
to Graeme Geldenhuys: I have ported the DUnit2 testing framework from Delphi to FPC. DUnit2 works perfectly…
Graeme Geldenhuys wrote 23 lines
function CallerAddr: Pointer; assembler; const CallerIP = $4; asm mov eax, ebp call IsBadPointer test eax,eax jne @@Error mov eax, [ebp].CallerIP sub eax, 5 // 5 bytes for call push eax call IsBadPointer test eax,eax pop eax je @@Finish @@Error: xor eax, eax @@Finish: end;

By the way... Simply adding {$ASMMODE intel} at the top of the unit, does not solve the problem either. It just moves the compiler message down a few lines giving the following error.

/opt/git/dunit2/src/TestFramework.pas(2076,21) Error: Asm: 16 or 32 Bit
references not supported

Hence the reason I ask if there is a cross-platform function in FPC that does similar to CallerAddr(..).

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://opensoft.homeip.net/fpgui/

Reply by email

Vincent Snijders
to Graeme Geldenhuys: I have ported the DUnit2 testing framework from Delphi to FPC. DUnit2 works perfectly…
Graeme Geldenhuys wrote 14 lines
Hi, I have ported the DUnit2 testing framework from Delphi to FPC. DUnit2 works perfectly under 32bit FPC, but I am getting a compiler error when trying to compile DUnit2 with 64bit FPC. The error 'Unknown identifier "EAX"' occurs in the first line of function CallerAddr(...). I know that using ASM is not portable in FPC. CallerAddr() is used is the raise <exception> at <address> call in method Fail(...) shown below. Is there an existing function in FPC that does the same as CallerAddr(..), but in a cross platform way? Alternatively, how can I solve this compiler error under 64bit FPC (currently testing under 64bit Linux).

There is http://lazarus-ccr.sourceforge.net/docs/rtl/system/get_caller_addr.html

It is used for example in LCLProc.GetStackTracePointers

  bp:=get_caller_frame(get_frame);
  if bpnil then
     addr:=get_caller_addr(bp);

Vincent

Reply by email

Graeme Geldenhuys
to Jonas Maebe: That's because we don't support Intel assembler syntax for x86_64.…
Jonas Maebe wrote 5 lines
> > Is there an existing function in FPC that does the same as > CallerAddr(..), but in a cross platform way? get_caller_addr(get_frame)

Just what I was looking for. Thank you! :-) It compiles now without problem, but Lazarus IDE can't seem to resolve the get_frame() function. By that I mean, Ctrl+Click on get_frame() doesn't go anywhere in Lazarus IDE..

I found get_frame() function definition and noticed that it is wrapped in IFDEF as shown below. When is the INTERNAL_BACKTRACE active? I'm using Core 2 Quad processor with 64bit Ubuntu Linux. Do I fall in the ELSE part or not?

{$IFDEF INTERNAL_BACKTRACE}
  // nothing
{$ELSE}
function get_frame:pointer;{$ifdef SYSTEMINLINE}inline;{$endif}
{$ENDIF}

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://opensoft.homeip.net/fpgui/

Reply by email

Jonas Maebe
to Graeme Geldenhuys
Graeme Geldenhuys wrote 10 lines
I found get_frame() function definition and noticed that it is wrapped in IFDEF as shown below. When is the INTERNAL_BACKTRACE active? I'm using Core 2 Quad processor with 64bit Ubuntu Linux. Do I fall in the ELSE part or not? {$IFDEF INTERNAL_BACKTRACE} // nothing {$ELSE} function get_frame:pointer;{$ifdef SYSTEMINLINE}inline;{$endif} {$ENDIF}

Compile with -va and look whether the compiler defines INTERNAL_BACKTRACE. Whether or not is irrelevant to the actual functionality though, it works in both cases.

Jonas

Reply by email

Graeme Geldenhuys
to Jonas Maebe: Compile with -va and look whether the compiler defines INTERNAL_BACKTRACE. Whether or not…
Jonas Maebe wrote 10 lines
> > {$IFDEF INTERNAL_BACKTRACE} > // nothing > {$ELSE} > function get_frame:pointer;{$ifdef SYSTEMINLINE}inline;{$endif} > {$ENDIF} Compile with -va and look whether the compiler defines INTERNAL_BACKTRACE. Whether or not is irrelevant to the actual functionality though, it works in both cases.

OK, my 64bit FPC does have INTERNAL_BACKTRACE defined, but does NOT have FPC_SYSTEM_HAS_GET_FRAME.

So it seems my FPC doesn't have get_frame() function, but yet FPC is able to compile DUnit2. This is weird and I don't understand how

  get_caller_addr(get_frame);

is able to compile without errors.

I did a 'find in files' for 'function get_frame' and found 8 implementations and not one match my compiler (IFDEF's).

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://opensoft.homeip.net/fpgui/

Reply by email

Jonas Maebe
to Graeme Geldenhuys
Graeme Geldenhuys wrote 8 lines
OK, my 64bit FPC does have INTERNAL_BACKTRACE defined, but does NOT have FPC_SYSTEM_HAS_GET_FRAME. So it seems my FPC doesn't have get_frame() function, but yet FPC is able to compile DUnit2. This is weird and I don't understand how get_caller_addr(get_frame); is able to compile without errors.

It does have it, because INTERNAL_BACKTRACE means "the backtrace- related functions are handled internally in the compiler for this platform".

Jonas

Reply by email