2
0
Эх сурвалжийг харах

* Fixed parameter generation for dispatch calls: assuming that everything is passed by reference and needs only sizeof(ptruint) bytes is wrong. 64-bit primitive types (Double,Int64) are passed by value and require twice more space on 32-bit platforms.

git-svn-id: trunk@16350 -
sergei 14 жил өмнө
parent
commit
2d860e356c
1 өөрчлөгдсөн 34 нэмэгдсэн , 41 устгасан
  1. 34 41
      compiler/ncal.pas

+ 34 - 41
compiler/ncal.pas

@@ -295,7 +295,6 @@ implementation
         assignmenttype,
         vardatadef,
         pvardatadef : tdef;
-        dispatchbyref : boolean;
         useresult: boolean;
         restype: byte;
 
@@ -313,18 +312,23 @@ implementation
         dispintfinvoke,
         variantdispatch : boolean;
 
-      procedure increase_paramssize;
+      function is_byref_para(out assign_type: tdef): boolean;
         begin
-          { for now we pass everything by reference
-          case para.left.resultdef.typ of
-            variantdef:
-              inc(paramssize,para.left.resultdef.size);
-            else
-          }
-              inc(paramssize,voidpointertype.size);
-          {
-          end;
-          }
+          // !! This condition is subject to change, see Mantis #17904
+          result:=(assigned(para.parasym) and (para.parasym.varspez in [vs_var,vs_out,vs_constref])) or
+                  (para.left.resultdef.typ in [variantdef]);
+
+          if result then
+            assign_type:=voidpointertype
+          else
+            case para.left.resultdef.size of
+              1..4:
+                assign_type:=u32inttype;
+              8:
+                assign_type:=u64inttype;
+              else
+                internalerror(2007042801);
+            end;
         end;
 
       function getvardef(sourcedef: TDef): longint;
@@ -412,7 +416,8 @@ implementation
                 CGMessagePos1(para.left.fileinfo,type_e_not_automatable,para.left.resultdef.typename);
 
             { we've to know the parameter size to allocate the temp. space }
-            increase_paramssize;
+            is_byref_para(assignmenttype);
+            inc(paramssize, assignmenttype.size);
 
             para:=tcallparanode(para.nextpara);
           end;
@@ -461,41 +466,29 @@ implementation
                   internalerror(200611041);
               end;
 
-            dispatchbyref:=(assigned(para.parasym) and (para.parasym.varspez in [vs_var,vs_out,vs_constref])) or
-                           (para.left.resultdef.typ in [variantdef]);
+            calldesc.argtypes[currargpos]:=getvardef(para.left.resultdef);
 
             { assign the argument/parameter to the temporary location }
 
-            if dispatchbyref then
-              addstatement(statements,cassignmentnode.create(
-                ctypeconvnode.create_internal(cderefnode.create(caddnode.create(addn,
-                  caddrnode.create(ctemprefnode.create(params)),
-                  cordconstnode.create(qword(paramssize),ptruinttype,false)
-                )),voidpointertype),
-                ctypeconvnode.create_internal(caddrnode.create_internal(para.left),voidpointertype)))
-            else
+            if is_byref_para(assignmenttype) then
               begin
-                case para.left.resultdef.size of
-                  1..4:
-                    assignmenttype:=u32inttype;
-                  8:
-                    assignmenttype:=u64inttype;
-                  else
-                    internalerror(2007042801);
-                end;
                 addstatement(statements,cassignmentnode.create(
                   ctypeconvnode.create_internal(cderefnode.create(caddnode.create(addn,
-                    caddrnode.create(ctemprefnode.create(params)),
-                    cordconstnode.create(paramssize,ptruinttype,false)
-                  )),assignmenttype),
-                  ctypeconvnode.create_internal(para.left,assignmenttype)));
-              end;
-
-            calldesc.argtypes[currargpos]:=getvardef(para.left.resultdef);
-            if dispatchbyref then
-              calldesc.argtypes[currargpos]:=calldesc.argtypes[currargpos] or $80;
+                      caddrnode.create(ctemprefnode.create(params)),
+                    cordconstnode.create(qword(paramssize),ptruinttype,false)
+                  )),voidpointertype),
+                  ctypeconvnode.create_internal(caddrnode.create_internal(para.left),voidpointertype)));
+                calldesc.argtypes[currargpos]:=calldesc.argtypes[currargpos] or $80;
+              end
+            else
+              addstatement(statements,cassignmentnode.create(
+                ctypeconvnode.create_internal(cderefnode.create(caddnode.create(addn,
+                  caddrnode.create(ctemprefnode.create(params)),
+                  cordconstnode.create(paramssize,ptruinttype,false)
+                )),assignmenttype),
+                ctypeconvnode.create_internal(para.left,assignmenttype)));
 
-            increase_paramssize;
+            inc(paramssize,assignmenttype.size);
 
             para.left:=nil;
             inc(currargpos);