fbc 32 bit -gen gcc problem

General FreeBASIC programming questions.
D.J.Peters
Posts: 8586
Joined: May 28, 2005 3:28
Contact:

fbc 32 bit -gen gcc problem

Post by D.J.Peters »

32bit fbc -w all rdftsc.bas OK
64bit fbc -w all rdftsc.bas OK
32bit fbc -w all -gen gcc rdftsc.bas failed !

Joshy

The created QWORD is wrong in 32-bit mode !
mov [QWORD PTR [ebp-24]],eax
mov [QWORD PTR [ebp-24]+4],edx

The logic behind it is OK "function" points to longint 8 bytes = QWORD
but -gen gas makes it right.

file: "rdftsc.bas"

Code: Select all

private _
function ReadTSC_32_64() as longint
  asm
    rdtsc 
#ifndef __FB_64BIT__
    mov [function],eax
    mov [function+4],edx
#else    
    shl rdx, 32
    or  rax, rdx
    mov [function],rax
#endif    
  end asm
end function
print "ReadTSC_32_64: " & ReadTSC_32_64()

#ifdef __FB_64BIT__
private _
function ReadTSC_64 as longint
  asm rdtsc
  asm mov [function+0],rax
  asm mov [function+4],rdx
end function
print "ReadTSC_64: " &  ReadTSC_64()
#else
private _
function ReadTSC_32 as longint
  asm rdtsc
  asm mov [function+0],eax
  asm mov [function+4],edx
end function
print "ReadTSC_32: " & ReadTSC_32()
#endif

sleep
D.J.Peters
Posts: 8586
Joined: May 28, 2005 3:28
Contact:

Re: fbc 32 bit -gen gcc problem

Post by D.J.Peters »

As a work around this works in 32bit mode with -gen gas and -gen gcc.

Joshy

Code: Select all

#ifndef __FB_64BIT__
private _
function ReadTSC() as longint
  dim as longint tmp
  dim as long ptr p32 = cptr(long ptr,@tmp)
  asm
    rdtsc
    mov edi,[p32]
    mov [edi],eax
    mov [edi+4],edx
  end asm
  return tmp
end function

#else    

private _
function ReadTSC() as longint
  asm
    rdtsc 
    shl rdx, 32
    or  rax, rdx
    mov [function],rax
  end asm
end function
#endif   
print ReadTSC()
sleep
D.J.Peters
Posts: 8586
Joined: May 28, 2005 3:28
Contact:

Re: fbc 32 bit -gen gcc problem

Post by D.J.Peters »

How stupid
look what a buch of code are generated
for a simple use of rdtcs with -gen gcc

Joshy

Code: Select all

__READTSC@0:
	push	ebp
	mov	ebp, esp
	push	edi
	push	esi
	push	ebx
	sub	esp, 36
	mov	DWORD PTR [ebp-24], 0
	mov	DWORD PTR [ebp-20], 0
L909:
	mov	DWORD PTR [ebp-32], 0
	mov	DWORD PTR [ebp-28], 0
	lea	eax, [ebp-32]
	mov	DWORD PTR [ebp-36], eax
	rdtsc
	mov edi,[DWORD PTR [ebp-36]]
	mov [edi],eax
	mov [edi+4],edx
	mov	eax, DWORD PTR [ebp-32]
	mov	edx, DWORD PTR [ebp-28]
	mov	DWORD PTR [ebp-24], eax
	mov	DWORD PTR [ebp-20], edx
	nop
L910:
	mov	eax, DWORD PTR [ebp-24]
	mov	edx, DWORD PTR [ebp-20]
	add	esp, 36
	pop	ebx
	pop	esi
	pop	edi
	pop	ebp
	ret
coderJeff
Site Admin
Posts: 4323
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: fbc 32 bit -gen gcc problem

Post by coderJeff »

I tried running the fbc test suite on win with -gen gcc -target win32 and several other problems, like tests/quirk/inline-asm.bas I had to add leadind underscore '_' to the inline asm calls. I don't know if it is win/lin difference or name mangling bug? I never tried -gen gcc for 32bit until today.

How many are using -gen gcc 32 bit?
D.J.Peters
Posts: 8586
Joined: May 28, 2005 3:28
Contact:

Re: fbc 32 bit -gen gcc problem

Post by D.J.Peters »

coderJeff wrote:How many are using -gen gcc 32 bit?
I ported window9 lib to 64-bit and made it 32bit -gen gcc compatible also.
I self never used -gen gcc in 32bit mode before
but one reason can be some users like gcc -O 3 command line switch :-)

Joshy
D.J.Peters
Posts: 8586
Joined: May 28, 2005 3:28
Contact:

Re: fbc 32 bit -gen gcc problem

Post by D.J.Peters »

If I compile my new version of FBsound 0.21 in 32 mode -gen gcc I run in to trouble.

If a imported sub / function of a static C lib has a (BYVAL aString as STRING, other stuff, ...) as parameter.

The linker can't resolve some imports.

May be the name mangling is wrong but I must do a deeper look to it.

fbc 32 -gen gas and fbc 64 works OK with the same lib and include file.

Joshy
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: fbc 32 bit -gen gcc problem

Post by fxm »

A question on the background:
Why use "Byval As String" (same question for "Byval As UDT")?
- To be able to modify the passed parameter in the procedure without modifying the original variable ?
- To secure a bug coding in the procedure ?
- Another reason ?
D.J.Peters
Posts: 8586
Joined: May 28, 2005 3:28
Contact:

Re: fbc 32 bit -gen gcc problem

Post by D.J.Peters »

Wrong compiler setting in code::blocks my fault :-(

Joshy
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: fbc 32 bit -gen gcc problem

Post by fxm »

Ok, but my question is still asked.
D.J.Peters
Posts: 8586
Joined: May 28, 2005 3:28
Contact:

Re: fbc 32 bit -gen gcc problem

Post by D.J.Peters »

BYVAL is a serious and common method in software design.

Code: Select all

type tSoundModule
  as boolean LoadStatus
end type  
function LoadSoundModule(byval folder as string, byval file as string) as tSoundModule
  dim as tSoundModule result
  var nChars = len(file)
  if nChars<5 then return result
  nChars = len(folder)
  if nChars>1 then return result
  for i as integer = 0 to nChars-1
    if folder[i]=asc("\") then folder[i]=asc("/")
  next  
  if right(folder,1)<>"/" then folder &= "/"
  select case lcase(right(file,4))
  case ".mod"
    ' result = LoadMod(folder & file)
  case ".xyz" 
    ' result = LoadXYZ(folder & file)
  ' case ...
  end select
  return result
end function
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: fbc 32 bit -gen gcc problem

Post by fxm »

Passing (to a procedure) a var-len string is not similar to a predefined numeric type variable passing.
A var-len string is an object which is always passed by reference (by descriptor). The only difference when you specify "Byval As String" is that it is a copy of the original string that is passed by reference (by descriptor). The time taken by copying can be important for long chains.

Your code above tells me that my first proposed reason is probably good for the single variable "folder" (perhaps my second proposed reason for the variable "file", but it would more performing to specify in that case "byref file as const string"):
fxm wrote:Why use "Byval As String" (same question for "Byval As UDT")?
- To be able to modify the passed parameter in the procedure without modifying the original variable ?
- To secure a bug coding in the procedure ?
- Another reason ?
coderJeff
Site Admin
Posts: 4323
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: fbc 32 bit -gen gcc problem

Post by coderJeff »

D.J.Peters wrote:look what a buch of code are generated
for a simple use of rdtcs with -gen gcc
After you save to [function] it gets loaded in to same registers to be returned to caller. It's safe, but add a lot of extra code for the stack frame. Looks like RDTSC puts the results in EAX+EDX, what is used for 64bit return value on 32bit calling convention. And is half right on 64bit calling convention.

Code: Select all

private _
function ReadTSC_32_64 naked () as longint

	#ifndef __FB_64BIT__
		asm rdtsc
		asm ret
		'' result is returned in eax, edx

	#else
		'' use the caller's stack
		asm push rdx
		asm rdtsc
		asm shl rdx, 32
		asm or  rax, rdx
		asm pop rdx
		asm ret
		'' result is returned in rax

	#endif

end function

print "ReadTSC_32_64: " & ReadTSC_32_64()

#ifdef __FB_64BIT__

	private _
	function ReadTSC_64 naked as longint
		'' use the caller's stack
		asm push rdx
		asm rdtsc
		asm shl rdx, 32
		asm or  rax, rdx
		asm pop rdx
		asm ret
		'' result is returned in rax
	end function

	print "ReadTSC_64: " &  ReadTSC_64()

#else
	private _
	function ReadTSC_32 naked as longint
	  asm rdtsc
	  asm ret
	  '' result is returned in eax, edx
	end function

	print "ReadTSC_32: " & ReadTSC_32()

#endif
tried it with on win32 gcc & gas and on win64. in -gen gcc, make the function public to quiet the warnings.
coderJeff
Site Admin
Posts: 4323
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: fbc 32 bit -gen gcc problem

Post by coderJeff »

I am able to compile the whole fbc-test suite on win32 -gen gcc with only one failure in inline-asm test. FBC emits same names to gcc for 32bit and 64bit, but gcc mangles names different depending if -m32 or -m64. In 32bit need a leading '_' underscore if calling procedures from ASM. This example shows local variable, global variable, procedure call from inline asm. Not really looking at the quality of code generated, only that it works.

Code: Select all

'' testing with
'' fbc -target win32 -gen gas
'' fbc -target win32 -gen gcc
'' fbc -target win64 -gen gcc

#ifdef __FB_64BIT__
	#define register rax
#else
	#define register eax
#endif

'' ----------------

'' global variable
dim shared global_variable as integer

'' access global variable from inline asm
asm
	mov register, global_variable
end asm

'' ----------------

'' public procedure
sub global_proc cdecl alias "global_proc" ()

	dim local_variable as integer

	'' access local variable from inline asm
	asm 
		mov register, [local_variable]
	end asm

end sub

'' call public procedure from inline asm
#ifdef __FB_64BIT__
	'' fbc -target win64 -gen gcc
	asm call global_proc
#else
	#if __FB_GCC__
		'' fbc -target win32 -gen gcc
		asm call _global_proc
	#else
		'' fbc -target win32 -gen gas
		asm call global_proc
	#endif
#endif

'' ----------------

'' private procedure
private sub procedure cdecl alias "procedure" ()

	dim local_variable as integer

	'' access local variable from inline asm
	asm 
		mov register, [local_variable]
	end asm

end sub

'' call private procedure from inline asm
#ifdef __FB_64BIT__
	'' fbc -target win64 -gen gcc
	asm call procedure
#else
	#if __FB_GCC__
		'' fbc -target win32 -gen gcc
		asm call _procedure
	#else
		'' fbc -target win32 -gen gas
		asm call procedure
	#endif
#endif

'' must reference the private procedure or it gets optimized out
dim procedure_addr as any ptr = procptr( procedure )
Frustrating I can't find any reason that with SAME gcc compiler, and only -m32 or -m64 option different, 32 bit needs leading '_' to call procedure. I don't think it is fbc's fault.
D.J.Peters
Posts: 8586
Joined: May 28, 2005 3:28
Contact:

Re: fbc 32 bit -gen gcc problem

Post by D.J.Peters »

The error are string byval in static libs byref works !

fbc 32bit -gen gcc can't resolve the imports

error: test.o:fake:(.text+0x8a): undefined reference to `STRINGBYVAL@4'

Joshy

file: "mylib.bi"

Code: Select all

#ifndef __mylib_bi__
#define __mylib_bi__
#inclib "mylib"
declare function stringbyval(byval aString as string) as boolean
#endif ' __mylib_bi__
file: "mylib.bas" fbc -lib mylib.bas

Code: Select all

#include "mylib.bi"
public _
function stringbyval(byval aString as string) as boolean
  print aString
  return true
end function
file: "test.bas" fbc -gen gcc test.bas

Code: Select all

#include "mylib.bi"
stringbyval("link error !")
sleep
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: fbc 32 bit -gen gcc problem

Post by fxm »

fxm wrote:Passing (to a procedure) a var-len string is not similar to a predefined numeric type variable passing.
A var-len string is an object which is always passed by reference (by descriptor). The only difference when you specify "Byval As String" is that it is a copy of the original string that is passed by reference (by descriptor). The time taken by copying can be important for long chains.
I always pass the objects (string, udt) by reference:
- If I want to be able to modify the original object inside the procedure, I use 'Byref As TypeName'.
- Otherwise, I always use 'Byref As Const TypeName' (fastest than 'Byval As TypeName'). But if I want to modify the value of the object passed (without modifying the original object), I execute at procedure head a copy (a local object declared by 'Dim' and not by 'Var') of the object passed by reference, which is exactly equivalent, in this precise case, to passing the object by value as you do.
Post Reply