Argument evaluation order and byref (from: What is randomize / rnd ?)

General FreeBASIC programming questions.
srvaldez
Posts: 3542
Joined: Sep 25, 2005 21:54

Re: Argument evaluation order and byref (from: What is randomize / rnd ?)

Post by srvaldez »

by the fact that gcc outputs Pi/4 means that both parameters to atan2 have the same value, apparently the num function is called only once
fxm
Moderator
Posts: 12396
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Argument evaluation order and byref (from: What is randomize / rnd ?)

Post by fxm »

dodicat wrote: Aug 14, 2024 15:41
srvaldez wrote: Aug 14, 2024 15:11 dodicat
I get the same result on gas, gas64, gcc32 and gcc64: 50, 100, 150, 255, 255, 255
would you post the gcc compile command options ?
suggest the use of #cmdline
<edit> what FB and gcc versions do you use ?
Hi srvaldez.
No options bar -gen gcc when testing 32 bits.
tested fbide and command line
I have simplified this, no static variable and no byref function, just straight pointer.

Code: Select all

Dim Shared As Integer u
Function num()  As Integer Ptr
    u+=50
    Print u
    Return @u
End Function

Function myfunction(a As Integer,b As Integer) As Double
    Print "return value = ";a;"/";b
    Return a/b
End Function

Print Atan2(*num,*num) 'a freebasic built in
Print Atan2(50,100)
Print
Print myfunction(*num,*num) ' a made procedure
Print myfunction(150,200)
Sleep

 
fb 1.10.1 winlibs -gcc-9.3 (the present standalone distro)
It is as if 'a' and 'b' were passed by reference (or by pointer) to myfunction (and not by value).
Maybe a quick optimization of the generated code (the argument being available by reference (or by pointer))!
dodicat
Posts: 8168
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Argument evaluation order and byref (from: What is randomize / rnd ?)

Post by dodicat »

fxm
You can put in a bug report if you like, thank you.
SARG
Posts: 1846
Joined: May 27, 2005 7:15
Location: FRANCE

Re: Argument evaluation order and byref (from: What is randomize / rnd ?)

Post by SARG »

FYI
First issue in gas64 fixed (an optimization in generated asm code prevented a correct converting ulong to integer).
Currently working on a second bug (byref function).
dodicat
Posts: 8168
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Argument evaluation order and byref (from: What is randomize / rnd ?)

Post by dodicat »

I tried gcc proper
code:

Code: Select all

#include<stdio.h>
#include<stdlib.h>
#include<math.h>

 int *  num()
{
static int u=0;
    u+=50;
    printf("%d\n",u);
    return &u;
}

double myfunction(int a,int b)
{
    printf("%s  %d %s %d \n" ,"return value = ",a,"/",b);
    return (double)(a)/(double)(b);
}


int main()
{
printf("%f\n",atan2(*num(),*num()));
printf("%f\n",atan2(50,100));
printf("\n");	
printf("%.5f\n", myfunction(*num(),*num())  ); // a made procedure
printf("%.5f\n", myfunction(150,200));
system("pause");
}

 
Results both 32 bit and 64 bit gcc compiler

Code: Select all

50
100
1.107149
0.463648

150
200
return value =   200 / 150
1.33333
return value =   150 / 200
0.75000
Press any key to continue . . . 
fxm
Moderator
Posts: 12396
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Argument evaluation order and byref (from: What is randomize / rnd ?)

Post by fxm »

What bothers me a little to fill out a bug report is that the code used is not safe, even when the function returns by value.
Indeed, there is no constraint on the order of evaluation of the arguments passed to a procedure compared to its declaration (from the last parameter to the first or vice versa?);
Which means that when the value returned by the function varies with each call, a precise behavior is not ensured seen from the procedure body.
gas and gcc/gas64 have a different behavior on unsafe code. Is this a bug?

Test program:

Code: Select all

Function ReturnByVal() As Integer
    Static As Integer I
    I+= 1
    Return I
End Function

Function ReturnByRef() Byref As Integer
    Static As Integer I
    I+= 1
    Return I
End Function

Function ReturnByPtr() As Integer Ptr
    Static As Integer I
    I+= 1
    Return @I
End Function

Sub Test(Byval I1 As Integer, Byval I2 As Integer, Byval I3 As Integer)
    Print "   First received parameter  : " & I1
    Print "   Second received parameter : " & I2
    Print "   Third received parameter  : " & I3
End Sub

Print "Arguments are function returns by value)
Test(ReturnByVal(), ReturnByVal(), ReturnByVal())
Print
Print "Arguments are function returns by reference)
Test(ReturnByRef(), ReturnByRef(), ReturnByRef())
Print
Print "Arguments are function returns by pointer)
Test(*ReturnByPtr(), *ReturnByPtr(), *ReturnByPtr())

Sleep
Output with gas(32):

Code: Select all

Arguments are function returns by value)
   First received parameter  : 3
   Second received parameter : 2
   Third received parameter  : 1

Arguments are function returns by reference)
   First received parameter  : 3
   Second received parameter : 2
   Third received parameter  : 1

Arguments are function returns by pointer)
   First received parameter  : 3
   Second received parameter : 2
   Third received parameter  : 1
Output with gcc(32/64) or gas64:

Code: Select all

Arguments are function returns by value)
   First received parameter  : 3
   Second received parameter : 2
   Third received parameter  : 1

Arguments are function returns by reference)
   First received parameter  : 3
   Second received parameter : 3
   Third received parameter  : 3

Arguments are function returns by pointer)
   First received parameter  : 3
   Second received parameter : 3
   Third received parameter  : 3
dodicat
Posts: 8168
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Argument evaluation order and byref (from: What is randomize / rnd ?)

Post by dodicat »

looks like the gcc C compiler is loading the parameters in reverse order both with the math.h atan2 and myfunction.
Whereas fb is loading correctly (this simple function) with gcc and giving same result as the c compiler.
Whereas the gas fb is loading atan2 in order and myfunction in reverse order.
this simple code is surely safe.

Code: Select all



Function num()  As Integer
    static as integer u
    u+=50
    Print u
    Return u
End Function

Function myfunction(a As Integer,b As Integer) As Double
    Print "return value = ";a;"/";b
    Return a/b
End Function

Print Atan2(num,num) 'a freebasic built in
Print Atan2(50,100)
Print
Print myfunction(num,num) ' a made procedure
Print myfunction(150,200)
Sleep

 
SARG
Posts: 1846
Joined: May 27, 2005 7:15
Location: FRANCE

Re: Argument evaluation order and byref (from: What is randomize / rnd ?)

Post by SARG »

Bug explained with this code.

Code: Select all

Function Rnd2() byref As integer

    Static As Ulong seed_value
    Static As integer d

    seed_value = (seed_value * 2 + 10 )
    d=seed_value
    Return d
End Function 

screen 20,32
rnd2()=200
circle(rnd2*5,rnd2*4),30,rgb(255,120,40),,,,f
Snippet of C code :

Code: Select all

int64* vr$2 = RND2(  );
int64* vr$5 = RND2(  );
fb_GfxEllipse( (void*)0ull, (float)(*vr$5 * 5ll), (float)(*vr$2 << (2ll & 63ll))
The C version stores the addresses for returned values not the values.
The problem is that they are the same and after the second call the first return value is replaced by the new one.....
fxm
Moderator
Posts: 12396
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Argument evaluation order and byref (from: What is randomize / rnd ?)

Post by fxm »

SARG
Posts: 1846
Joined: May 27, 2005 7:15
Location: FRANCE

Re: Argument evaluation order and byref (from: What is randomize / rnd ?)

Post by SARG »

Based on your example.
With test(byval....) gas32 pushes immediately the values on stack after each call.
Instead gcc/gas64 store the addresses then use them after all the calls. Obviously the last and same value is used for the 3 parameters.

With test(byref...) we get the same result for all the versions.
Is it a bug ?
As different behaviours between the versions it's a bug, however which one is the right one ;-)
fxm
Moderator
Posts: 12396
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Argument evaluation order and byref (from: What is randomize / rnd ?)

Post by fxm »

Yes, but my philosophical question is:
Is the different behavior of gas and gcc/gas64 on the same code a bug when the code is not safe ?

Indeed, there is no constraint (in my opinion) on the order of evaluation of the arguments passed to a procedure compared to its declaration (from the last parameter to the first, or vice versa ?).
Which means that when the value returned by the function varies with each call, a precise behavior is already not ensured seen from the procedure body on its received parameters.
SARG
Posts: 1846
Joined: May 27, 2005 7:15
Location: FRANCE

Re: Argument evaluation order and byref (from: What is randomize / rnd ?)

Post by SARG »

The order of evaluation is correct, not a problem of first/last.
The difference is that the source (value) is changed when retrieved before the call for the 2 first parameters.

3 solutions:
- gas32 behaves like the other versions
- gcc/gas64 behave like gas32
- forbid a such code : multiple calls to a byref function used as parameter. Force to use temporary variables.
dodicat
Posts: 8168
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Argument evaluation order and byref (from: What is randomize / rnd ?)

Post by dodicat »

SARG wrote: Aug 15, 2024 10:41 The order of evaluation is correct, not a problem of first/last.
The difference is that the source (value) is changed when retrieved before the call for the 2 first parameters.

3 solutions:
- gas32 behaves like the other versions
- gcc/gas64 behave like gas32
- forbid a such code : multiple calls to a byref function used as parameter. Force to use temporary variables.
The function does not need to be byref, the variable incrementing can be shared as I posted previously.
Here is an update with my own atan2, to see the input values, and resetting the shared variable each time.
(fxm what do you mean by unsafe code?)

Code: Select all

Dim Shared As Integer u
Function num() As Integer Ptr
    u+=50
    Print u
    Return @u
End Function

Function MyATN(Byval x As Double) As Double
    Dim As Double y,temp=x
    Dim As Uinteger limit=16, f=2^limit
    For n As Integer =1 To limit
        y=temp/(1+Sqr(1+temp*temp))
        temp=y
    Next n
    Dim As Double accum
    Dim As Integer c=1,counter,sign
    Dim As Double xx=y*y,term,p=y,temp1=y,temp2
    Do
        c+=2
        temp2=temp1
        counter+=1
        p=p*XX
        term=p/c
        If (counter And 1) Then sign=-1 Else sign=1
        accum=temp1+sign*term
        temp1=accum
    Loop Until temp1=temp2
    Return f*accum
End Function

Function MyAtan2(Byval x As Double,Byval y As Double) As Double
     Print "input value = ";x;",";y
    Dim k As Integer
    Dim As Double pi=4*MyATN(1),temp
    If y=0 Then Return Sgn(x)*pi/2
    If Sgn(y)=1 Or Sgn(y)=0 Then k=0 Else k=1
    k=k*Sgn(x)
    If x=0 And y=0 Then Return 0
    If Sgn(x)=0 And Sgn(y)=-1 Then Return Pi
    temp=MyATN(x/y)
    Return (temp)+k*Pi
End Function

Function myfunction(a As Integer,b As Integer) As Double
    Print "return value = ";a;"/";b
    Return a/b
End Function

Print Atan2(*num,*num),"fb atan2 using the function num()" 'a freebasic built in
Print Atan2(50,100),"fb atan2 using the numbers above from function num()"
u=0
Print
Print myfunction(*num,*num) ' a made procedure
Print myfunction(50,100)
print
u=0
print myatan2(*num,*num),"My atan2 using the function num()"
print myatan2(50,100),"My atan2 using the numbers above from function num()"

Sleep

  
Sorry for going severly off the thread topic Löwenherz.
fxm
Moderator
Posts: 12396
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Argument evaluation order and byref (from: What is randomize / rnd ?)

Post by fxm »

I apologize, but I repeat the same question again:
Is there a specification that imposes the order of evaluation of the parameters passed to a procedure (case of parameters passed by value)?

gcc(32/64) and gas(32/64) evaluate them from the last to the first (compared to the procedure declaration), but is this order specified anywhere?

If there is no evaluation order specified, using it like this in his code corresponds to unsafe (unsecure / dangerous) code.
dodicat
Posts: 8168
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Argument evaluation order and byref (from: What is randomize / rnd ?)

Post by dodicat »

If you do pascal
viz
Function MyAtan2 pascal(Byval x As Double,Byval y As Double) As Double
...
and
Function myfunction pascal(a As Integer,b As Integer) As Double
...

gas loads in the correct order.
(but should you really have to gp pascal)

but gcc still errors.
Post Reply