Explorar o código

* copy_value_on_stack method added for cdecl record passing

peter %!s(int64=23) %!d(string=hai) anos
pai
achega
8c82be898d
Modificáronse 2 ficheiros con 55 adicións e 10 borrados
  1. 6 4
      compiler/ncgutil.pas
  2. 49 6
      compiler/paramgr.pas

+ 6 - 4
compiler/ncgutil.pas

@@ -772,9 +772,8 @@ implementation
          end
         else
          begin
-           { call by value open array ? }
-           if (calloption in [pocall_cdecl,pocall_cppdecl]) and
-              paramanager.push_addr_param(p.resulttype.def,calloption) then
+           { copy the value on the stack or use normal parameter push? }
+           if paramanager.copy_value_on_stack(p.resulttype.def,calloption) then
             begin
               if not (p.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
                 internalerror(200204241);
@@ -1876,7 +1875,10 @@ function returns in a register and the caller receives it in an other one}
 end.
 {
   $Log$
-  Revision 1.63  2002-11-25 17:43:18  peter
+  Revision 1.64  2002-11-27 02:33:19  peter
+    * copy_value_on_stack method added for cdecl record passing
+
+  Revision 1.63  2002/11/25 17:43:18  peter
     * splitted defbase in defutil,symutil,defcmp
     * merged isconvertable and is_equal into compare_defs(_ext)
     * made operator search faster by walking the list only once

+ 49 - 6
compiler/paramgr.pas

@@ -54,15 +54,19 @@ unit paramgr;
 
           function push_high_param(def : tdef;calloption : tproccalloption) : boolean;virtual;
 
-          {# Returns true if a parameter is too large to copy and only
+          { Returns true if a parameter is too large to copy and only
             the address is pushed
           }
           function push_addr_param(def : tdef;calloption : tproccalloption) : boolean;virtual;
-          {# Returns a structure giving the information on
-             the storage of the parameter (which must be
-             an integer parameter)
+          { Returns true if a parameter needs to be copied on the stack, this
+            is required for cdecl procedures
+          }
+          function copy_value_on_stack(def : tdef;calloption : tproccalloption) : boolean;
+          { Returns a structure giving the information on
+            the storage of the parameter (which must be
+            an integer parameter)
 
-             @param(nr Parameter number of routine, starting from 1)
+            @param(nr Parameter number of routine, starting from 1)
           }
           function getintparaloc(nr : longint) : tparalocation;virtual;abstract;
           procedure create_param_loc_info(p : tabstractprocdef);virtual;abstract;
@@ -184,6 +188,42 @@ unit paramgr;
       end;
 
 
+    { true if a parameter is too large to copy and only the address is pushed }
+    function tparamanager.copy_value_on_stack(def : tdef;calloption : tproccalloption) : boolean;
+      begin
+        copy_value_on_stack:=false;
+        { this is only for cdecl procedures }
+        if not(calloption in [pocall_cdecl,pocall_cppdecl]) then
+         exit;
+        case def.deftype of
+          variantdef,
+          formaldef :
+            copy_value_on_stack:=true;
+          recorddef :
+            copy_value_on_stack:=(def.size>pointer_size);
+          arraydef :
+            copy_value_on_stack:=(
+                              (tarraydef(def).highrange>=tarraydef(def).lowrange) and
+                               (
+                                not(target_info.system=system_i386_win32) or
+                                (def.size>pointer_size)
+                               )
+                             ) or
+                             is_open_array(def) or
+                             is_array_of_const(def) or
+                             is_array_constructor(def);
+          objectdef :
+            copy_value_on_stack:=is_object(def);
+          stringdef :
+            copy_value_on_stack:=tstringdef(def).string_typ in [st_shortstring,st_longstring];
+          procvardef :
+            copy_value_on_stack:=(po_methodpointer in tprocvardef(def).procoptions);
+          setdef :
+            copy_value_on_stack:=(tsetdef(def).settype<>smallset);
+        end;
+      end;
+
+
     function tparamanager.getfuncretparaloc(p : tabstractprocdef) : tparalocation;
       begin
          result.loc:=LOC_REFERENCE;
@@ -339,7 +379,10 @@ end.
 
 {
    $Log$
-   Revision 1.24  2002-11-25 17:43:21  peter
+   Revision 1.25  2002-11-27 02:33:19  peter
+     * copy_value_on_stack method added for cdecl record passing
+
+   Revision 1.24  2002/11/25 17:43:21  peter
      * splitted defbase in defutil,symutil,defcmp
      * merged isconvertable and is_equal into compare_defs(_ext)
      * made operator search faster by walking the list only once