소스 검색

* fix passing of 64bit values when using -Or

peter 20 년 전
부모
커밋
dd0664156d
3개의 변경된 파일68개의 추가작업 그리고 109개의 파일을 삭제
  1. 21 7
      compiler/cg64f32.pas
  2. 12 49
      compiler/i386/cpupara.pas
  3. 35 53
      compiler/ncgutil.pas

+ 21 - 7
compiler/cg64f32.pas

@@ -135,15 +135,20 @@ unit cg64f32;
         { 2 parameter fields? }
         if assigned(cgpara.location^.next) then
           begin
-            if target_info.endian = endian_big then
+            { Order for multiple locations is always
+                paraloc^ -> high
+                paraloc^.next -> low }
+            if (target_info.endian=ENDIAN_BIG) then
               begin
-                { low is in second location }
-                move(cgpara.location^.next^,paraloclo^,sizeof(paraloclo^));
+                { paraloc^ -> high
+                  paraloc^.next -> low }
                 move(cgpara.location^,paralochi^,sizeof(paralochi^));
+                move(cgpara.location^.next^,paraloclo^,sizeof(paraloclo^));
               end
             else
               begin
-                { low is in first location }
+                { paraloc^ -> low
+                  paraloc^.next -> high }
                 move(cgpara.location^,paraloclo^,sizeof(paraloclo^));
                 move(cgpara.location^.next^,paralochi^,sizeof(paralochi^));
               end;
@@ -157,9 +162,9 @@ unit cg64f32;
             move(cgpara.location^,paralochi^,sizeof(paralochi^));
             { for big endian low is at +4, for little endian high }
             if target_info.endian = endian_big then
-              inc(cgparalo.location^.reference.offset,tcgsize2size[cgparahi.size])
+              inc(cgparalo.location^.reference.offset,4)
             else
-              inc(cgparahi.location^.reference.offset,tcgsize2size[cgparalo.size]);
+              inc(cgparahi.location^.reference.offset,4);
           end;
         { fix size }
         paraloclo^.size:=cgparalo.size;
@@ -488,6 +493,8 @@ unit cg64f32;
         tmploclo.init;
         tmplochi.init;
         splitparaloc64(paraloc,tmploclo,tmplochi);
+        { Keep this order of first hi before lo to have
+          the correct push order for i386 }
         cg.a_param_reg(list,OS_32,reg.reghi,tmplochi);
         cg.a_param_reg(list,OS_32,reg.reglo,tmploclo);
         tmploclo.done;
@@ -502,6 +509,8 @@ unit cg64f32;
         tmploclo.init;
         tmplochi.init;
         splitparaloc64(paraloc,tmploclo,tmplochi);
+        { Keep this order of first hi before lo to have
+          the correct push order for i386 }
         cg.a_param_const(list,OS_32,aint(hi(value)),tmplochi);
         cg.a_param_const(list,OS_32,aint(lo(value)),tmploclo);
         tmploclo.done;
@@ -523,6 +532,8 @@ unit cg64f32;
           inc(tmpreflo.offset,4)
         else
           inc(tmprefhi.offset,4);
+        { Keep this order of first hi before lo to have
+          the correct push order for i386 }
         cg.a_param_ref(list,OS_32,tmprefhi,tmplochi);
         cg.a_param_ref(list,OS_32,tmpreflo,tmploclo);
         tmploclo.done;
@@ -781,7 +792,10 @@ unit cg64f32;
 end.
 {
   $Log$
-  Revision 1.69  2005-02-14 17:13:06  peter
+  Revision 1.70  2005-02-15 19:16:04  peter
+    * fix passing of 64bit values when using -Or
+
+  Revision 1.69  2005/02/14 17:13:06  peter
     * truncate log
 
   Revision 1.68  2005/02/13 18:55:19  florian

+ 12 - 49
compiler/i386/cpupara.pas

@@ -399,6 +399,8 @@ unit cpupara;
                   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
@@ -421,41 +423,13 @@ unit cpupara;
                       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;
-        { Adapt offsets for left-to-right calling }
-        if p.proccalloption in pushleftright_pocalls then
-          begin
-            for i:=0 to paras.count-1 do
-              begin
-                hp:=tparavarsym(paras[i]);
-                l:=push_size(hp.varspez,hp.vartype.def,p.proccalloption);
-                varalign:=used_align(size_2_align(l),paraalign,paraalign);
-                l:=align(l,varalign);
-                with hp.paraloc[side].location^ do
-                  begin
-                    reference.offset:=parasize-reference.offset-l;
-                    if side=calleeside then
-                      inc(reference.offset,target_info.first_parm_offset);
-                  end;
-              end;
-          end
-        else
-          begin
-            { Only need to adapt the callee side to include the
-              standard stackframe size }
-            if side=calleeside then
-              begin
-                for i:=0 to paras.count-1 do
-                  begin
-                    hp:=tparavarsym(paras[i]);
-                    inc(hp.paraloc[side].location^.reference.offset,target_info.first_parm_offset);
-                  end;
-               end;
-          end;
       end;
 
 
@@ -529,6 +503,8 @@ unit cpupara;
                       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
@@ -551,30 +527,14 @@ unit cpupara;
                           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;
-        { Register parameters are assigned from left-to-right, adapt offset
-          for calleeside to be reversed }
-        for i:=0 to paras.count-1 do
-          begin
-            hp:=tparavarsym(paras[i]);
-            with hp.paraloc[side].location^ do
-              begin
-                if (loc=LOC_REFERENCE) then
-                  begin
-                    l:=push_size(hp.varspez,hp.vartype.def,p.proccalloption);
-                    varalign:=used_align(size_2_align(l),paraalign,paraalign);
-                    l:=align(l,varalign);
-                    reference.offset:=parasize-reference.offset-l;
-                    if side=calleeside then
-                      inc(reference.offset,target_info.first_parm_offset);
-                  end;
-               end;
-          end;
       end;
 
 
@@ -639,7 +599,10 @@ begin
 end.
 {
   $Log$
-  Revision 1.67  2005-02-14 19:42:02  peter
+  Revision 1.68  2005-02-15 19:16:04  peter
+    * fix passing of 64bit values when using -Or
+
+  Revision 1.67  2005/02/14 19:42:02  peter
   win32 stdcall fixes needed for tw3650
 
   Revision 1.66  2005/02/14 17:13:09  peter

+ 35 - 53
compiler/ncgutil.pas

@@ -1332,13 +1332,15 @@ implementation
 
       var
         i : longint;
-        sizeleft : aint;
         currpara : tparavarsym;
-        paraloc : pcgparalocation;
+        paraloc  : pcgparalocation;
+        hreflo,
+        hrefhi,
+        href     : treference;
 {$ifdef sparc}
-        tempref,
+        sizeleft : aint;
+        tempref  : treference;
 {$endif sparc}
-        href    : treference;
       begin
         if (po_assembler in current_procinfo.procdef.procoptions) then
           exit;
@@ -1348,7 +1350,6 @@ implementation
           begin
             currpara:=tparavarsym(current_procinfo.procdef.paras[i]);
             paraloc:=currpara.paraloc[calleeside].location;
-            sizeleft:=currpara.paraloc[calleeside].intsize;
             while assigned(paraloc) do
               begin
                 if paraloc^.loc in [LOC_REGISTER,LOC_FPUREGISTER,LOC_MMREGISTER] then
@@ -1365,7 +1366,6 @@ implementation
             { skip e.g. empty records }
             if (paraloc^.loc = LOC_VOID) then
               continue;
-            sizeleft:=currpara.paraloc[calleeside].intsize;
             if not assigned(paraloc) then
               internalerror(200408203);
             case currpara.localloc.loc of
@@ -1376,80 +1376,59 @@ implementation
                   if not paramanager.param_use_paraloc(currpara.paraloc[calleeside]) then
                     begin
                       href:=currpara.localloc.reference;
-                      while assigned(paraloc) do
+                      if (currpara.paraloc[calleeside].is_single_reference(paraloc)) then
                         begin
                           unget_para(paraloc^);
-                          if (currpara.paraloc[calleeside].is_single_reference(paraloc)) then
-                            begin
-                              gen_load_ref(paraloc^,href,sizeleft);
-                              { May be needed later, when we add support for     }
-                              { passing the same parameter in multiple locations }
-                              { Currently, is_single_reference returns only true }
-                              { if paraloc^.next = nil (JM)                      }
-                              inc(href.offset,sizeleft);
-                              sizeleft := 0;
-                            end
-                          else
+                          gen_load_ref(paraloc^,href,currpara.paraloc[calleeside].intsize);
+                        end
+                      else
+                        begin
+                          while assigned(paraloc) do
                             begin
+                              unget_para(paraloc^);
                               if (paraloc^.size = OS_NO) then
                                 internalerror(2005013010);
                               gen_load_ref(paraloc^,href,tcgsize2size[paraloc^.size]);
                               inc(href.offset,TCGSize2Size[paraloc^.size]);
-                              dec(sizeleft,TCGSize2Size[paraloc^.size]);
+                              paraloc:=paraloc^.next;
                             end;
-                          paraloc:=paraloc^.next;
                         end;
                     end;
                 end;
               LOC_CREGISTER :
                 begin
 {$ifndef cpu64bit}
-                  if currpara.localloc.size in [OS_64,OS_S64] then
+                  if (currpara.paraloc[calleeside].size in [OS_64,OS_S64]) and
+                     is_64bit(currpara.vartype.def) then
                     begin
-                      { Special case for single location 64bit LOC_REFERENCE parameter }
-                      if paraloc^.size in [OS_64,OS_S64] then
+                      if not assigned(paraloc^.next) then
+                        internalerror(200410104);
+                      if (target_info.endian=ENDIAN_BIG) then
                         begin
-                          if paraloc^.loc<>LOC_REFERENCE then
-                            internalerror(200412031);
-                          reference_reset_base(href,paraloc^.reference.index,paraloc^.reference.offset);
-                          if (target_info.endian=ENDIAN_BIG) then
-                            begin
-                              cg.a_load_ref_reg(list,OS_32,OS_32,href,currpara.localloc.register64.reghi);
-                              inc(href.offset,4);
-                              cg.a_load_ref_reg(list,OS_32,OS_32,href,currpara.localloc.register64.reglo);
-                            end
-                          else
-                            begin
-                              cg.a_load_ref_reg(list,OS_32,OS_32,href,currpara.localloc.register64.reglo);
-                              inc(href.offset,4);
-                              cg.a_load_ref_reg(list,OS_32,OS_32,href,currpara.localloc.register64.reghi);
-                            end;
+                          { paraloc^ -> high
+                            paraloc^.next -> low }
+                          unget_para(paraloc^);
+                          gen_load_reg(paraloc^,currpara.localloc.register64.reghi);
+                          unget_para(paraloc^.next^);
+                          gen_load_reg(paraloc^.next^,currpara.localloc.register64.reglo);
                         end
                       else
                         begin
-                          { First 32bits }
+                          { paraloc^ -> low
+                            paraloc^.next -> high }
                           unget_para(paraloc^);
-                          if (target_info.endian=ENDIAN_BIG) then
-                            gen_load_reg(paraloc^,currpara.localloc.register64.reghi)
-                          else
-                            gen_load_reg(paraloc^,currpara.localloc.register64.reglo);
-                          { Second 32bits }
-                          if not assigned(paraloc^.next) then
-                            internalerror(200410104);
+                          gen_load_reg(paraloc^,currpara.localloc.register64.reglo);
                           unget_para(paraloc^.next^);
-                          if (target_info.endian=ENDIAN_BIG) then
-                            gen_load_reg(paraloc^.next^,currpara.localloc.register64.reglo)
-                          else
-                            gen_load_reg(paraloc^.next^,currpara.localloc.register64.reghi);
+                          gen_load_reg(paraloc^.next^,currpara.localloc.register64.reghi);
                         end;
                     end
                   else
 {$endif cpu64bit}
                     begin
-                      unget_para(paraloc^);
-                      gen_load_reg(paraloc^,currpara.localloc.register);
                       if assigned(paraloc^.next) then
                         internalerror(200410105);
+                      unget_para(paraloc^);
+                      gen_load_reg(paraloc^,currpara.localloc.register);
                     end;
                 end;
               LOC_CFPUREGISTER :
@@ -2422,7 +2401,10 @@ implementation
 end.
 {
   $Log$
-  Revision 1.260  2005-02-14 17:13:06  peter
+  Revision 1.261  2005-02-15 19:16:04  peter
+    * fix passing of 64bit values when using -Or
+
+  Revision 1.260  2005/02/14 17:13:06  peter
     * truncate log
 
   Revision 1.259  2005/01/30 21:51:57  jonas