* 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:
Jonas Maebe 2015-02-23 22:50:29 +00:00
parent 2dbfbd40ab
commit edb3124ae8
4 changed files with 20 additions and 13 deletions

View File

@ -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

View File

@ -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;

View File

@ -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 }

View File

@ -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 ? }