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

General FreeBASIC programming questions.
deltarho[1859]
Posts: 4704
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

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

Post by deltarho[1859] »

dodicat wrote:Sorry for going severely off the thread topic Löwenherz.
Ideally you should have started a new thread.
dodicat
Posts: 8267
Joined: Jan 10, 2006 20:30
Location: Scotland

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

Post by dodicat »

deltarho[]
A lot of my recent generators are byref, so you can easily seed them , i.e. change a value inside the generator from outside.
But it looks like they have all gone to the wall now in -gen gcc.
Maybe our developers will repair things.
deltarho[1859]
Posts: 4704
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

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

Post by deltarho[1859] »

dodicat wrote:But it looks like they have all gone to the wall now in -gen gcc.
Why?

Your recent generators are only passing one value so will not be affected by the possible 'bug' being looked at above.
fxm
Moderator
Posts: 12577
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

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

Post by fxm »

The calling convention (stdcall, pascal, cdecl) imposes the order of passing the parameters (in the stack) relative to the order in which they are listed in the declaration, but nothing specifically imposes that the corresponding arguments are evaluated (for passing by value) in the same order.

Otherwise, I think gas(32) is right, and it is not because the arguments provided are references that they should not still be passed by value as stipulated in the declaration.
dodicat
Posts: 8267
Joined: Jan 10, 2006 20:30
Location: Scotland

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

Post by dodicat »

The windows default must be stdcall because;
for ellipses you must write cdecl, so cdecl is not default
for my code to load left to right you must write pascal, so pascal is not the default.
deltarho
Never mind my byref generators gone to the wall with -gen gcc, it's out the window and over the hills and far away.

Code: Select all


Function rnd32(n as long=0)  byref As Ulong
   const k=2147483647
     static as ulong z(1 to 5)={k,2,k,4,5}
   if n=0 then
    z(5) = z(1) - ((z(2) shl 27) or (z(2) shr (32 - 27)))
	z(1) = z(2) xor ((z(3) shl 17) or (z(3) shr (32 - 17)))
	z(2) = z(3) + z(4)
	z(3) = z(4) + z(5)
	z(4) = z(5) + z(1)
    else
    z(1)=k:z(2)=2:z(3)=k:z(5)=5
    end if
	return z(4)
End Function

sub seed32(n as ulong)
    if n=0 then n=1
        (rnd32(4))=n
        rnd32
end  sub
const k=2^32
#define range(f,l) clng((rnd32() mod (((l)-(f))+(1))) + (f))
#define frnd rnd32/k

seed32(20000)

screen 19,32 
for n as long=1 to 20
    circle(frnd*800,frnd*600),20+frnd*20,rgb(frnd*255,frnd*255,frnd*255),,,,f
next
dim as double lasts
for n as long=0 to 800
    var s=abs(600-150*sin(n/500))
    line(n,s)-(n,800),rgb(frnd*10,200+500*(s-lasts),frnd*10)
    lasts=s
    next

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

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

Post by SARG »

fxm wrote: Aug 15, 2024 11:33 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.
They are evaluated in the right order and used in the right order :

Code: Select all

gas32
-----
call RND2 (first parameter)
push on stack value from address1
call RND2 (second parameter)
push on stack value from address1
call RND2(third parameter)
push on stack value from address1
call TEST

Code: Select all

gas64/gcc
---------
call RND2 (first parameter)
store address1 to V1
call RND2 (second parameter)
store address1 to V2
call RND2 (third parameter)
store address1 to V3
use V1 to retrieve value first parameter but same like third parameter due to address1
use V2 to retrieve value second parameter but same like third parameter
use V3 to retrieve value third parameter
call TEST
I agree need to be moved to another thread
deltarho[1859]
Posts: 4704
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

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

Post by deltarho[1859] »

I doubt that the following is related to the issue currently being looked at, but it is related to a function returning a value ByRef.

Suppose we have:

Code: Select all

Function foo() ByRef As Long
Static As Long Ret
'Do something according to the value of Ret
'Some code
Return Ret
End Function
Suppose we execute foo() = <whatever>

Foo() will be executed, but the value of Ret on entry will be zero.

The 'Do something according to the value of Ret' will be skipped if 'Ret = 0' is not considered. The 'Some code' will get executed, which could be a problem.

When we come to execute foo(), as in Print foo() for example, it is at that point that Ret will be equal to <whatever>.

To avoid any issues, we should consider 'Ret = 0' when we execute 'foo() = <whatever>'. If true, then we should exit foo() with 'Return Ret' without further ado. The <whatever> will bite when we execute foo() the first time.

Here is an example:

Code: Select all

Function foo1() ByRef As Long
Static Ret As long
Static SomeValue As Long
  If Ret < 0 Then
    Print "Initialize code"
  Elseif Ret = 0 Then
    Return Ret
  End If
  SomeValue+=1
  Ret = SomeValue
  Return Ret
End Function
  
foo1()=-1
Print foo1()
Print foo1()
Sleep
We get:

Code: Select all

Initialize code
 1
 2
If we don't consider 'Ret = 0' we get:

Code: Select all

Initialize code
 2
 3
dodicat
Posts: 8267
Joined: Jan 10, 2006 20:30
Location: Scotland

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

Post by dodicat »

Like most things in fb, you can have a workaround.
For gcc we must have a different memory location each parameter call.

Code: Select all

Function foo1()  As Long Ptr
    Static As Long x(0 To 100)
    Static As Long somevalue,inc
    Static Ret As Long Ptr
    ret=@x(inc)
    inc+=1
    If inc>100 Then inc=0
    SomeValue+=1
    *Ret = SomeValue
    Return Ret
End Function


Function foo2()  As Long Ptr
    Static As Long u
    u+=1
    Return @u
End Function


Print Chr(48+*foo1,48+*foo1,48+*foo1,48+*foo1,48+*foo1,48+*foo1,48+*foo1,48+*foo1,48+*foo1) 'OK in gas/gcc

Print Chr(48+*foo2,48+*foo2,48+*foo2,48+*foo2,48+*foo2,48+*foo2,48+*foo2,48+*foo2,48+*foo2) 'OK in gas

Sleep 
Maybe I can do the similar in a random generator for gcc, but it is all getting a little exasperating, so I'll leave it just now.
coderJeff
Site Admin
Posts: 4386
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

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

Post by coderJeff »

New topic split from original What is randomize / rnd ?

fxm, thank-you for the bug report. Yes when days become shorter and nights colder I may have time again ...
I will post an example of a related behaviour on sf.net
----

My opinion is that if the code author's intent is clear and there are specific rules to follow the yes of course we should want predictable behaviour. Should be obvious that this is not what we currently have; returning references of functions with side effects on global state, plus c/c++ doesn't specify anything in standards about evaluation order. Not an expert, but I read c++17 begins to introduce some standards to enforce the sequencing of instructions, but I think is mainly related to chaining (e.g. object.method(args...).method(args...).etc) trying to ensure that the code author's intent is respected.
adeyblue
Posts: 357
Joined: Nov 07, 2019 20:08

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

Post by adeyblue »

I don't know about C++ 17 but both of the 'what fbc curretly does' and 'what fbc should probably do' in that sf post are done by C++ compilers now, so neither one is 'more' correct than the other. The a's have to be done in order but all that has to happen in respect of the d's is that the d happens before its corresponding a, so whether batched or interleaved they both fulfill that.

One could say, in C++ land at least, that if your code relies on either order, it's probably broken even if not technically broken by the letter of the law. Because who knows when your compiler will change it (Hey, whaddaya know, GCC before version 7 generates the current MSVC order, so it has changed in GCC at least once)

Code: Select all

T:\>cl /Ox /TP /Fe:testmsvc.exe test.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 18.00.21005.1 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

test.cpp
Microsoft (R) Incremental Linker Version 12.00.21005.1
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:testmsvc.exe
test.obj

T:\>testmsvc.exe
Q.d(3)
Q.d(2)
Q.d(1)
Q.a(1)
Q.a(2)
Q.a(3)

T:\>g++ -o testgcc.exe test.cpp

T:\>testgcc
Q.d(1)
Q.a(1)
Q.d(2)
Q.a(2)
Q.d(3)
Q.a(3)

--
test.cpp
#include <stdio.h>

struct Q
{
	float x;
	int d(int arg)
	{
		printf("Q.d(%d)\n", arg);
		return arg;
	}
	Q& a(int arg)
	{
		printf("Q.a(%d)\n", arg);
		return *this;
	}
};

int main()
{
	Q t;
	t.a( t.d(1) ).a( t.d(2) ).a( t.d(3) );
}
dodicat
Posts: 8267
Joined: Jan 10, 2006 20:30
Location: Scotland

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

Post by dodicat »

Using PASCAL, left to right parameter read, solves the order problem, but not the memory problem in -gen gcc.

Code: Select all

type Q
    x as single
    declare function d( byval arg as single ) as single
    declare function a pascal( byval arg as single ) byref as Q
    declare constructor()
end type

constructor Q()
end constructor

function Q.d( byval arg as single ) as single
    print "Q.d(" & arg & ")"
    return arg
end function

function Q.a pascal( byval arg as single ) byref as Q
   if arg then print "Q.a(" & arg & ")"
    x+=1
    return this
end function

var t = Q()

t.a( t.d(1) ).a( t.d(2) ).a( t.d(3) )
var temp=Q()
temp.x=48
(t.a(0))=temp 'byref function test

print chr( t.a(0).x,t.a(0).x,t.a(0).x,t.a(0).x,t.a(0).x,t.a(0).x,t.a(0).x,t.a(0).x,t.a(0).x)

sleep 
Using adeyblue's c++

Code: Select all

#include <stdio.h>
struct Q
{
	float x;
	int d(int arg)
	{
		printf("Q.d(%d)\n", arg);
		return arg;
	}
	Q& a(int arg)
	{
	if (arg != 0)	{printf("Q.a(%d)\n", arg);};
		x+=1;
		return *this;
	}
};

int main()
{
	#define z char(t.a(0).x)
	Q t;
	t.a( t.d(1) ).a( t.d(2) ).a( t.d(3) );
	Q temp;
	temp.x=48;
	t.a(0)=temp; // testing byref behaviour
	printf("%c%c%c%c%c%c%c%c%c",z,z,z,z,z,z,z,z,z);
} 
gives:

Code: Select all

Q.d(1)
Q.a(1)
Q.d(2)
Q.a(2)
Q.d(3)
Q.a(3)
987654321 
deltarho[1859]
Posts: 4704
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

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

Post by deltarho[1859] »

@dodicat

I learned a few things in the 'What is randomize / rnd thread.'

The most important one was in sorting out a segmentation error. fxm spotted a weakness in my code, which I initially disagreed with.

So I came here and checked out your opening post.

It uses my code which produced a segmentation error.

I replaced that with my latest code shown here to save you time:

Code: Select all

Function Rnd2() ByRef As Double
Static As ULong seed_value
Static As Double d
  If d = 0 Then ' first pass
    Return d     ' As assigned in main by Rnd2() = <whatever> and we do not fall through
  ElseIf d<0 Then ' second pass
    seed_value=-d ' and fall throgh
  End If
  ' on third pass d > 0
  seed_value = seed_value * 1664525 + 1013904223
  d=seed_value/2^32
  Return d
End Function
Do the same to see what you now get.

I doubt that the above will be of any assistance regarding the 'Argument evaluation order' but at least Rnd2 is now doing what it should have done.
dodicat
Posts: 8267
Joined: Jan 10, 2006 20:30
Location: Scotland

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

Post by dodicat »

Works OK now.
deltarho[1859]
Posts: 4704
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

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

Post by deltarho[1859] »

I get two blank screens with gas64.
SARG
Posts: 1888
Joined: May 27, 2005 7:15
Location: FRANCE

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

Post by SARG »

deltarho[1859] wrote: Aug 19, 2024 8:28 I get two blank screens with gas64.
As reported in a previous post there is a bug : optimization prevented converting 32bit memory/register
I fixed it. So you can try with this version :
https://users.freebasic-portal.de/sarg/fbc64_120.zip

Edit : that was another bug... Anyway fixed in this version.
Last edited by SARG on Aug 19, 2024 12:41, edited 2 times in total.
Post Reply