mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-22 04:29:29 +02:00
* copy arrays passed by value to cdecl routines on the callee side even on
platforms that normally must copy value parameters on the caller side, because o if we copy them on the caller side, then the behaviour will be different compared to other platforms if the called routine is implemented in C (since they are passed by reference, changes to the array contents will be visible on other platforms, while they wouldn't be visible if the copy is made on the caller side) o if we don't copy them on the caller nor on the callee side, then behaviour will be different compared to other platforms if the called routine is implemented in Pascal and modifies the array (since then changes won't be visible on the caller side, except on platforms that normally perform the copy on the caller side) git-svn-id: trunk@29873 -
This commit is contained in:
parent
2dbfbd40ab
commit
edb3124ae8
@ -4665,8 +4665,7 @@ implementation
|
||||
{ generate copies of call by value parameters, must be done before
|
||||
the initialization and body is parsed because the refcounts are
|
||||
incremented using the local copies }
|
||||
if not(target_info.system in systems_caller_copy_addr_value_para) then
|
||||
current_procinfo.procdef.parast.SymList.ForEachCall(@g_copyvalueparas,list);
|
||||
current_procinfo.procdef.parast.SymList.ForEachCall(@g_copyvalueparas,list);
|
||||
|
||||
if not(po_assembler in current_procinfo.procdef.procoptions) then
|
||||
begin
|
||||
@ -4693,7 +4692,8 @@ implementation
|
||||
list:=TAsmList(arg);
|
||||
if (tsym(p).typ=paravarsym) and
|
||||
((vo_has_local_copy in tparavarsym(p).varoptions) or
|
||||
((is_open_array(tparavarsym(p).vardef) or
|
||||
(not(target_info.system in systems_caller_copy_addr_value_para) and
|
||||
(is_open_array(tparavarsym(p).vardef) or
|
||||
is_array_of_const(tparavarsym(p).vardef)) and
|
||||
(tparavarsym(p).varspez=vs_value))) then
|
||||
begin
|
||||
|
@ -949,9 +949,11 @@ implementation
|
||||
(parasym.varspez=vs_value)) or
|
||||
(cpf_varargs_para in callparaflags)) and
|
||||
(left.nodetype<>nothingn) and
|
||||
(not(aktcallnode.procdefinition.proccalloption in cdecl_pocalls) or
|
||||
(left.resultdef.typ<>arraydef)) and
|
||||
paramanager.push_addr_param(vs_value,left.resultdef,
|
||||
not(vo_has_local_copy in parasym.varoptions) and
|
||||
((not is_open_array(parasym.vardef) and
|
||||
not is_array_of_const(parasym.vardef)) or
|
||||
not(aktcallnode.procdefinition.proccalloption in cdecl_pocalls)) and
|
||||
paramanager.push_addr_param(vs_value,parasym.vardef,
|
||||
aktcallnode.procdefinition.proccalloption) then
|
||||
copy_value_by_ref_para;
|
||||
|
||||
|
@ -1258,8 +1258,7 @@ implementation
|
||||
{ generate copies of call by value parameters, must be done before
|
||||
the initialization and body is parsed because the refcounts are
|
||||
incremented using the local copies }
|
||||
if not(target_info.system in systems_caller_copy_addr_value_para) then
|
||||
current_procinfo.procdef.parast.SymList.ForEachCall(@hlcg.g_copyvalueparas,list);
|
||||
current_procinfo.procdef.parast.SymList.ForEachCall(@hlcg.g_copyvalueparas,list);
|
||||
{$ifdef powerpc}
|
||||
{ unget the register that contains the stack pointer before the procedure entry, }
|
||||
{ which is used to access the parameters in their original callee-side location }
|
||||
|
@ -331,15 +331,21 @@ implementation
|
||||
{ We need a local copy for a value parameter when only the
|
||||
address is pushed. Open arrays and Array of Const are
|
||||
an exception because they are allocated at runtime and the
|
||||
address that is pushed is patched. Arrays passed to cdecl routines
|
||||
also because arrays are treated like pointers in C. }
|
||||
address that is pushed is patched.
|
||||
|
||||
Arrays passed to cdecl routines are special: they are pointers in
|
||||
C and hence must be passed as such. Due to historical reasons, if
|
||||
a cdecl routine is implemented in Pascal, we still make a copy on
|
||||
the callee side. Do this the same on platforms that normally must
|
||||
make a copy on the caller side, as otherwise the behaviour will
|
||||
be different (and less perfomant) for routines implemented in C }
|
||||
if (varspez=vs_value) and
|
||||
paramanager.push_addr_param(varspez,vardef,pd.proccalloption) and
|
||||
not(is_open_array(vardef) or
|
||||
is_array_of_const(vardef)) and
|
||||
not(target_info.system in systems_caller_copy_addr_value_para) and
|
||||
(not(pd.proccalloption in cdecl_pocalls) or
|
||||
(vardef.typ<>arraydef)) then
|
||||
(not(target_info.system in systems_caller_copy_addr_value_para) or
|
||||
((pd.proccalloption in cdecl_pocalls) and
|
||||
(vardef.typ=arraydef))) then
|
||||
include(varoptions,vo_has_local_copy);
|
||||
|
||||
{ needs high parameter ? }
|
||||
|
Loading…
Reference in New Issue
Block a user