Browse Source

* handle stack parameters like delphi when using register calling conventions, resolves #8199

git-svn-id: trunk@6201 -
florian 18 years ago
parent
commit
e923c6072d
1 changed files with 125 additions and 85 deletions
  1. 125 85
      compiler/i386/cpupara.pas

+ 125 - 85
compiler/i386/cpupara.pas

@@ -503,104 +503,144 @@ unit cpupara;
         varalign : longint;
         varalign : longint;
         pushaddr : boolean;
         pushaddr : boolean;
         paraalign : shortint;
         paraalign : shortint;
+        pass : byte;
       begin
       begin
+        if paras.count=0 then
+          exit;
         paraalign:=get_para_align(p.proccalloption);
         paraalign:=get_para_align(p.proccalloption);
-        { Register parameters are assigned from left to right }
+
+        { clean up here so we can later detect properly if a parameter has been
+          assigned or not
+        }
         for i:=0 to paras.count-1 do
         for i:=0 to paras.count-1 do
+          tparavarsym(paras[i]).paraloc[side].reset;
+        { Register parameters are assigned from left to right,
+          stack parameters from right to left so assign first the
+          register parameters in a first pass, in the second
+          pass all unhandled parameters are done }
+        for pass:=1 to 2 do
           begin
           begin
-            hp:=tparavarsym(paras[i]);
-            pushaddr:=push_addr_param(hp.varspez,hp.vardef,p.proccalloption);
-            if pushaddr then
-              begin
-                paralen:=sizeof(aint);
-                paracgsize:=OS_ADDR;
-              end
-            else
-              begin
-                paralen:=push_size(hp.varspez,hp.vardef,p.proccalloption);
-                paracgsize:=def_cgsize(hp.vardef);
-              end;
-            hp.paraloc[side].reset;
-            hp.paraloc[side].size:=paracgsize;
-            hp.paraloc[side].intsize:=paralen;
-            hp.paraloc[side].Alignment:=paraalign;
-            {
-              EAX
-              EDX
-              ECX
-              Stack
-              Stack
-
-              64bit values,floats,arrays and records are always
-              on the stack.
-            }
-            if (parareg<=high(parasupregs)) and
-               (paralen<=sizeof(aint)) and
-               (
-                not(hp.vardef.typ in [floatdef,recorddef,arraydef]) or
-                pushaddr
-               ) then
-              begin
-                paraloc:=hp.paraloc[side].add_location;
-                paraloc^.size:=paracgsize;
-                paraloc^.loc:=LOC_REGISTER;
-                paraloc^.register:=newreg(R_INTREGISTER,parasupregs[parareg],cgsize2subreg(paracgsize));
-                inc(parareg);
-              end
+            if pass=1 then
+              i:=0
             else
             else
+              i:=paras.count-1;
+            while true do
               begin
               begin
-                { Copy to stack? }
-                if (use_fixed_stack) or
-                   (paracgsize=OS_NO) then
+                hp:=tparavarsym(paras[i]);
+                if not(assigned(hp.paraloc[side].location)) then
                   begin
                   begin
-                    paraloc:=hp.paraloc[side].add_location;
-                    paraloc^.loc:=LOC_REFERENCE;
-                    paraloc^.size:=paracgsize;
-                    if side=callerside then
-                      paraloc^.reference.index:=NR_STACK_POINTER_REG
+
+                    pushaddr:=push_addr_param(hp.varspez,hp.vardef,p.proccalloption);
+                    if pushaddr then
+                      begin
+                        paralen:=sizeof(aint);
+                        paracgsize:=OS_ADDR;
+                      end
                     else
                     else
-                      paraloc^.reference.index:=NR_FRAME_POINTER_REG;
-                    varalign:=used_align(size_2_align(paralen),paraalign,paraalign);
-                    paraloc^.reference.offset:=parasize;
-                    if side=calleeside then
-                      inc(paraloc^.reference.offset,target_info.first_parm_offset);
-                    parasize:=align(parasize+paralen,varalign);
-                  end
-                else
-                  begin
-                    if paralen=0 then
-                      internalerror(200501163);
-                    while (paralen>0) do
                       begin
                       begin
-                        paraloc:=hp.paraloc[side].add_location;
-                        paraloc^.loc:=LOC_REFERENCE;
-                        { Extended and double need a single location }
-                        if (paracgsize in [OS_F64,OS_F32]) then
+                        paralen:=push_size(hp.varspez,hp.vardef,p.proccalloption);
+                        paracgsize:=def_cgsize(hp.vardef);
+                      end;
+                    hp.paraloc[side].size:=paracgsize;
+                    hp.paraloc[side].intsize:=paralen;
+                    hp.paraloc[side].Alignment:=paraalign;
+                    {
+                      EAX
+                      EDX
+                      ECX
+                      Stack
+                      Stack
+
+                      64bit values,floats,arrays and records are always
+                      on the stack.
+                    }
+                    if (parareg<=high(parasupregs)) and
+                       (paralen<=sizeof(aint)) and
+                       (
+                        not(hp.vardef.typ in [floatdef,recorddef,arraydef]) or
+                        pushaddr
+                       ) then
+                      begin
+                        if pass=1 then
                           begin
                           begin
+                            paraloc:=hp.paraloc[side].add_location;
                             paraloc^.size:=paracgsize;
                             paraloc^.size:=paracgsize;
-                            l:=paralen;
-                          end
-                        else
-                          begin
-                            { We can allocate at maximum 32 bits per location }
-                            if paralen>sizeof(aint) then
-                              l:=sizeof(aint)
-                            else
-                              l:=paralen;
-                            paraloc^.size:=int_cgsize(l);
+                            paraloc^.loc:=LOC_REGISTER;
+                            paraloc^.register:=newreg(R_INTREGISTER,parasupregs[parareg],cgsize2subreg(paracgsize));
+                            inc(parareg);
                           end;
                           end;
-                        if side=callerside then
-                          paraloc^.reference.index:=NR_STACK_POINTER_REG
-                        else
-                          paraloc^.reference.index:=NR_FRAME_POINTER_REG;
-                        varalign:=used_align(size_2_align(l),paraalign,paraalign);
-                        paraloc^.reference.offset:=parasize;
-                        if side=calleeside then
-                          inc(paraloc^.reference.offset,target_info.first_parm_offset);
-                        parasize:=align(parasize+l,varalign);
-                        dec(paralen,l);
-                      end;
+                      end
+                    else
+                      if pass=2 then
+                        begin
+                          { Copy to stack? }
+                          if (use_fixed_stack) or
+                             (paracgsize=OS_NO) then
+                            begin
+                              paraloc:=hp.paraloc[side].add_location;
+                              paraloc^.loc:=LOC_REFERENCE;
+                              paraloc^.size:=paracgsize;
+                              if side=callerside then
+                                paraloc^.reference.index:=NR_STACK_POINTER_REG
+                              else
+                                paraloc^.reference.index:=NR_FRAME_POINTER_REG;
+                              varalign:=used_align(size_2_align(paralen),paraalign,paraalign);
+                              paraloc^.reference.offset:=parasize;
+                              if side=calleeside then
+                                inc(paraloc^.reference.offset,target_info.first_parm_offset);
+                              parasize:=align(parasize+paralen,varalign);
+                            end
+                          else
+                            begin
+                              if paralen=0 then
+                                internalerror(200501163);
+                              while (paralen>0) do
+                                begin
+                                  paraloc:=hp.paraloc[side].add_location;
+                                  paraloc^.loc:=LOC_REFERENCE;
+                                  { Extended and double need a single location }
+                                  if (paracgsize in [OS_F64,OS_F32]) then
+                                    begin
+                                      paraloc^.size:=paracgsize;
+                                      l:=paralen;
+                                    end
+                                  else
+                                    begin
+                                      { We can allocate at maximum 32 bits per location }
+                                      if paralen>sizeof(aint) then
+                                        l:=sizeof(aint)
+                                      else
+                                        l:=paralen;
+                                      paraloc^.size:=int_cgsize(l);
+                                    end;
+                                  if side=callerside then
+                                    paraloc^.reference.index:=NR_STACK_POINTER_REG
+                                  else
+                                    paraloc^.reference.index:=NR_FRAME_POINTER_REG;
+                                  varalign:=used_align(size_2_align(l),paraalign,paraalign);
+                                  paraloc^.reference.offset:=parasize;
+                                  if side=calleeside then
+                                    inc(paraloc^.reference.offset,target_info.first_parm_offset);
+                                  parasize:=align(parasize+l,varalign);
+                                  dec(paralen,l);
+                                end;
+                            end;
+                        end;
                   end;
                   end;
+                case pass of
+                  1:
+                    begin
+                      if i=paras.count-1 then
+                        break;
+                      inc(i);
+                    end;
+                  2:
+                    begin
+                      if i=0 then
+                        break;
+                      dec(i);
+                    end;
+                end;
               end;
               end;
           end;
           end;
       end;
       end;