Kaynağa Gözat

* initial support for system procs that use calling conventions that push left to right on i8086 or i386

git-svn-id: branches/i8086@24282 -
nickysn 12 yıl önce
ebeveyn
işleme
a5c5b05362
6 değiştirilmiş dosya ile 184 ekleme ve 50 silme
  1. 10 2
      compiler/cgobj.pas
  2. 84 19
      compiler/hlcgobj.pas
  3. 53 20
      compiler/ncgflw.pas
  4. 3 1
      compiler/ncgmat.pas
  5. 20 4
      compiler/ncgmem.pas
  6. 14 4
      compiler/ncgutil.pas

+ 10 - 2
compiler/cgobj.pas

@@ -2100,8 +2100,16 @@ implementation
            paramanager.getintparaloc(pd,1,cgpara1);
            paramanager.getintparaloc(pd,2,cgpara2);
            reference_reset_symbol(hrefvmt,current_asmdata.RefAsmSymbol(objdef.vmt_mangledname),0,sizeof(pint));
-           a_loadaddr_ref_cgpara(list,hrefvmt,cgpara2);
-           a_load_reg_cgpara(list,OS_ADDR,reg,cgpara1);
+           if pd.is_pushleftright then
+             begin
+               a_load_reg_cgpara(list,OS_ADDR,reg,cgpara1);
+               a_loadaddr_ref_cgpara(list,hrefvmt,cgpara2);
+             end
+           else
+             begin
+               a_loadaddr_ref_cgpara(list,hrefvmt,cgpara2);
+               a_load_reg_cgpara(list,OS_ADDR,reg,cgpara1);
+             end;
            paramanager.freecgpara(list,cgpara1);
            paramanager.freecgpara(list,cgpara2);
            allocallcpuregisters(list);

+ 84 - 19
compiler/hlcgobj.pas

@@ -2829,9 +2829,18 @@ implementation
       paramanager.getintparaloc(pd,1,cgpara1);
       paramanager.getintparaloc(pd,2,cgpara2);
       paramanager.getintparaloc(pd,3,cgpara3);
-      a_loadaddr_ref_cgpara(list,strdef,dest,cgpara3);
-      a_loadaddr_ref_cgpara(list,strdef,source,cgpara2);
-      a_load_const_cgpara(list,s32inttype,strdef.len,cgpara1);
+      if pd.is_pushleftright then
+        begin
+          a_load_const_cgpara(list,s32inttype,strdef.len,cgpara1);
+          a_loadaddr_ref_cgpara(list,strdef,source,cgpara2);
+          a_loadaddr_ref_cgpara(list,strdef,dest,cgpara3);
+        end
+      else
+        begin
+          a_loadaddr_ref_cgpara(list,strdef,dest,cgpara3);
+          a_loadaddr_ref_cgpara(list,strdef,source,cgpara2);
+          a_load_const_cgpara(list,s32inttype,strdef.len,cgpara1);
+        end;
       paramanager.freecgpara(list,cgpara3);
       paramanager.freecgpara(list,cgpara2);
       paramanager.freecgpara(list,cgpara1);
@@ -2851,8 +2860,16 @@ implementation
       cgpara2.init;
       paramanager.getintparaloc(pd,1,cgpara1);
       paramanager.getintparaloc(pd,2,cgpara2);
-      a_loadaddr_ref_cgpara(list,vardef,dest,cgpara2);
-      a_loadaddr_ref_cgpara(list,vardef,source,cgpara1);
+      if pd.is_pushleftright then
+        begin
+          a_loadaddr_ref_cgpara(list,vardef,source,cgpara1);
+          a_loadaddr_ref_cgpara(list,vardef,dest,cgpara2);
+        end
+      else
+        begin
+          a_loadaddr_ref_cgpara(list,vardef,dest,cgpara2);
+          a_loadaddr_ref_cgpara(list,vardef,source,cgpara1);
+        end;
       paramanager.freecgpara(list,cgpara2);
       paramanager.freecgpara(list,cgpara1);
       g_call_system_proc(list,pd,nil);
@@ -2904,8 +2921,16 @@ implementation
           if is_open_array(t) then
             InternalError(201103054);
           reference_reset_symbol(href,RTTIWriter.get_rtti_label(t,initrtti),0,sizeof(pint));
-          a_loadaddr_ref_cgpara(list,voidpointertype,href,cgpara2);
-          a_loadaddr_ref_cgpara(list,t,ref,cgpara1);
+          if pd.is_pushleftright then
+            begin
+              a_loadaddr_ref_cgpara(list,t,ref,cgpara1);
+              a_loadaddr_ref_cgpara(list,voidpointertype,href,cgpara2);
+            end
+          else
+            begin
+              a_loadaddr_ref_cgpara(list,voidpointertype,href,cgpara2);
+              a_loadaddr_ref_cgpara(list,t,ref,cgpara1);
+            end;
           paramanager.freecgpara(list,cgpara1);
           paramanager.freecgpara(list,cgpara2);
           g_call_system_proc(list,pd,nil);
@@ -2944,8 +2969,16 @@ implementation
             paramanager.getintparaloc(pd,1,cgpara1);
             paramanager.getintparaloc(pd,2,cgpara2);
             reference_reset_symbol(href,RTTIWriter.get_rtti_label(t,initrtti),0,sizeof(pint));
-            a_loadaddr_ref_cgpara(list,voidpointertype,href,cgpara2);
-            a_loadaddr_ref_cgpara(list,t,ref,cgpara1);
+            if pd.is_pushleftright then
+              begin
+                a_loadaddr_ref_cgpara(list,t,ref,cgpara1);
+                a_loadaddr_ref_cgpara(list,voidpointertype,href,cgpara2);
+              end
+            else
+              begin
+                a_loadaddr_ref_cgpara(list,voidpointertype,href,cgpara2);
+                a_loadaddr_ref_cgpara(list,t,ref,cgpara1);
+              end;
             paramanager.freecgpara(list,cgpara1);
             paramanager.freecgpara(list,cgpara2);
             g_call_system_proc(list,pd,nil);
@@ -2986,8 +3019,16 @@ implementation
           paramanager.getintparaloc(pd,1,cgpara1);
           paramanager.getintparaloc(pd,2,cgpara2);
           reference_reset_symbol(href,RTTIWriter.get_rtti_label(t,initrtti),0,sizeof(pint));
-          a_loadaddr_ref_cgpara(list,voidpointertype,href,cgpara2);
-          a_loadaddr_ref_cgpara(list,t,ref,cgpara1);
+          if pd.is_pushleftright then
+            begin
+              a_loadaddr_ref_cgpara(list,t,ref,cgpara1);
+              a_loadaddr_ref_cgpara(list,voidpointertype,href,cgpara2);
+            end
+          else
+            begin
+              a_loadaddr_ref_cgpara(list,voidpointertype,href,cgpara2);
+              a_loadaddr_ref_cgpara(list,t,ref,cgpara1);
+            end;
           paramanager.freecgpara(list,cgpara1);
           paramanager.freecgpara(list,cgpara2);
           g_call_system_proc(list,pd,nil);
@@ -3019,6 +3060,14 @@ implementation
       paramanager.getintparaloc(pd,2,cgpara2);
       paramanager.getintparaloc(pd,3,cgpara3);
 
+      { if calling convention is left to right, push parameters 1 and 2 }
+      if pd.is_pushleftright then
+        begin
+          a_loadaddr_ref_cgpara(list,t,ref,cgpara1);
+          a_loadaddr_ref_cgpara(list,voidpointertype,href,cgpara2);
+        end;
+
+      { push parameter 3 }
       reference_reset_symbol(href,RTTIWriter.get_rtti_label(t,initrtti),0,sizeof(pint));
       if highloc.loc=LOC_CONSTANT then
         a_load_const_cgpara(list,ptrsinttype,highloc.value+1,cgpara3)
@@ -3037,8 +3086,12 @@ implementation
           a_load_reg_cgpara(list,ptrsinttype,lenreg,cgpara3);
         end;
 
-      a_loadaddr_ref_cgpara(list,voidpointertype,href,cgpara2);
-      a_loadaddr_ref_cgpara(list,t,ref,cgpara1);
+      { if calling convention is right to left, push parameters 2 and 1 }
+      if not pd.is_pushleftright then
+        begin
+          a_loadaddr_ref_cgpara(list,voidpointertype,href,cgpara2);
+          a_loadaddr_ref_cgpara(list,t,ref,cgpara1);
+        end;
       paramanager.freecgpara(list,cgpara1);
       paramanager.freecgpara(list,cgpara2);
       paramanager.freecgpara(list,cgpara3);
@@ -3308,12 +3361,24 @@ implementation
       paramanager.getintparaloc(pd,1,cgpara1);
       paramanager.getintparaloc(pd,2,cgpara2);
       paramanager.getintparaloc(pd,3,cgpara3);
-      { load size }
-      a_load_reg_cgpara(list,ptrsinttype,sizereg,cgpara3);
-      { load destination }
-      a_load_reg_cgpara(list,ptrarrdef,destreg,cgpara2);
-      { load source }
-      a_load_reg_cgpara(list,ptrarrdef,sourcereg,cgpara1);
+      if pd.is_pushleftright then
+        begin
+          { load source }
+          a_load_reg_cgpara(list,ptrarrdef,sourcereg,cgpara1);
+          { load destination }
+          a_load_reg_cgpara(list,ptrarrdef,destreg,cgpara2);
+          { load size }
+          a_load_reg_cgpara(list,ptrsinttype,sizereg,cgpara3);
+        end
+      else
+        begin
+          { load size }
+          a_load_reg_cgpara(list,ptrsinttype,sizereg,cgpara3);
+          { load destination }
+          a_load_reg_cgpara(list,ptrarrdef,destreg,cgpara2);
+          { load source }
+          a_load_reg_cgpara(list,ptrarrdef,sourcereg,cgpara1);
+        end;
       paramanager.freecgpara(list,cgpara3);
       paramanager.freecgpara(list,cgpara2);
       paramanager.freecgpara(list,cgpara1);

+ 53 - 20
compiler/ncgflw.pas

@@ -986,31 +986,64 @@ implementation
                 exit;
 
               { Push parameters }
-              if assigned(right) then
+              { ugly code repetition follows for left to right and right to left calling conventions }
+              { TODO: refactor this somehow }
+              if pd.is_pushleftright then
                 begin
-                  { frame tree }
-                  if assigned(third) then
-                    cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,third.location,paraloc3)
-                  else
-                    cg.a_load_const_cgpara(current_asmdata.CurrAsmList,OS_ADDR,0,paraloc3);
-                  { push address }
-                  cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,right.location,paraloc2);
+                  cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,left.location,paraloc1);
+                   if assigned(right) then
+                     begin
+                       { push address }
+                       cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,right.location,paraloc2);
+                       { frame tree }
+                       if assigned(third) then
+                         cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,third.location,paraloc3)
+                       else
+                         cg.a_load_const_cgpara(current_asmdata.CurrAsmList,OS_ADDR,0,paraloc3);
+                     end
+                   else
+                     begin
+                        { get current address }
+                        current_asmdata.getaddrlabel(a);
+                        cg.a_label(current_asmdata.CurrAsmList,a);
+                        reference_reset_symbol(href2,a,0,1);
+                        { push current address }
+                        if target_info.system <> system_powerpc_macos then
+                          cg.a_loadaddr_ref_cgpara(current_asmdata.CurrAsmList,href2,paraloc2)
+                        else
+                          cg.a_load_const_cgpara(current_asmdata.CurrAsmList,OS_ADDR,0,paraloc2);
+                        { push current frame }
+                        cg.a_load_reg_cgpara(current_asmdata.CurrAsmList,OS_ADDR,NR_FRAME_POINTER_REG,paraloc3);
+                     end;
                 end
               else
                 begin
-                   { get current address }
-                   current_asmdata.getaddrlabel(a);
-                   cg.a_label(current_asmdata.CurrAsmList,a);
-                   reference_reset_symbol(href2,a,0,1);
-                   { push current frame }
-                   cg.a_load_reg_cgpara(current_asmdata.CurrAsmList,OS_ADDR,NR_FRAME_POINTER_REG,paraloc3);
-                   { push current address }
-                   if target_info.system <> system_powerpc_macos then
-                     cg.a_loadaddr_ref_cgpara(current_asmdata.CurrAsmList,href2,paraloc2)
-                   else
-                     cg.a_load_const_cgpara(current_asmdata.CurrAsmList,OS_ADDR,0,paraloc2);
+                  if assigned(right) then
+                    begin
+                      { frame tree }
+                      if assigned(third) then
+                        cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,third.location,paraloc3)
+                      else
+                        cg.a_load_const_cgpara(current_asmdata.CurrAsmList,OS_ADDR,0,paraloc3);
+                      { push address }
+                      cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,right.location,paraloc2);
+                    end
+                  else
+                    begin
+                       { get current address }
+                       current_asmdata.getaddrlabel(a);
+                       cg.a_label(current_asmdata.CurrAsmList,a);
+                       reference_reset_symbol(href2,a,0,1);
+                       { push current frame }
+                       cg.a_load_reg_cgpara(current_asmdata.CurrAsmList,OS_ADDR,NR_FRAME_POINTER_REG,paraloc3);
+                       { push current address }
+                       if target_info.system <> system_powerpc_macos then
+                         cg.a_loadaddr_ref_cgpara(current_asmdata.CurrAsmList,href2,paraloc2)
+                       else
+                         cg.a_load_const_cgpara(current_asmdata.CurrAsmList,OS_ADDR,0,paraloc2);
+                    end;
+                  cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,left.location,paraloc1);
                 end;
-              cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,left.location,paraloc1);
               paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
               paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc2);
               paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc3);

+ 3 - 1
compiler/ncgmat.pas

@@ -304,6 +304,7 @@ implementation
          paraloc1 : tcgpara;
          opsize : tcgsize;
          opdef : tdef;
+         pd: tprocdef;
       begin
          secondpass(left);
          if codegenerror then
@@ -384,7 +385,8 @@ implementation
                   current_asmdata.getjumplabel(hl);
                   cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_INT,OC_NE,0,hdenom,hl);
                   paraloc1.init;
-                  paramanager.getintparaloc(search_system_proc('fpc_handleerror'),1,paraloc1);
+                  pd:=search_system_proc('fpc_handleerror');
+                  paramanager.getintparaloc(pd,1,paraloc1);
                   cg.a_load_const_cgpara(current_asmdata.CurrAsmList,OS_S32,aint(200),paraloc1);
                   paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
                   cg.a_call_name(current_asmdata.CurrAsmList,'FPC_HANDLEERROR',false);

+ 20 - 4
compiler/ncgmem.pas

@@ -721,8 +721,16 @@ implementation
                pd:=search_system_proc('fpc_dynarray_rangecheck');
                paramanager.getintparaloc(pd,1,paraloc1);
                paramanager.getintparaloc(pd,2,paraloc2);
-               cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,right.location,paraloc2);
-               cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,left.location,paraloc1);
+               if pd.is_pushleftright then
+                 begin
+                   cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,left.location,paraloc1);
+                   cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,right.location,paraloc2);
+                 end
+               else
+                 begin
+                   cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,right.location,paraloc2);
+                   cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,left.location,paraloc1);
+                 end;
                paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
                paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc2);
                cg.allocallcpuregisters(current_asmdata.CurrAsmList);
@@ -755,8 +763,16 @@ implementation
               pd:=search_system_proc(helpername);
               paramanager.getintparaloc(pd,1,paraloc1);
               paramanager.getintparaloc(pd,2,paraloc2);
-              cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,left.location,paraloc1);
-              cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,right.location,paraloc2);
+              if pd.is_pushleftright then
+                begin
+                  cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,left.location,paraloc1);
+                  cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,right.location,paraloc2);
+                end
+              else
+                begin
+                  cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,right.location,paraloc2);
+                  cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,left.location,paraloc1);
+                end;
 
               paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
               paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc2);

+ 14 - 4
compiler/ncgutil.pas

@@ -439,10 +439,20 @@ implementation
         paramanager.getintparaloc(pd,1,paraloc1);
         paramanager.getintparaloc(pd,2,paraloc2);
         paramanager.getintparaloc(pd,3,paraloc3);
-        cg.a_loadaddr_ref_cgpara(list,t.envbuf,paraloc3);
-        cg.a_loadaddr_ref_cgpara(list,t.jmpbuf,paraloc2);
-        { push type of exceptionframe }
-        cg.a_load_const_cgpara(list,pushexceptaddr_frametype_cgsize,1,paraloc1);
+        if pd.is_pushleftright then
+          begin
+            { push type of exceptionframe }
+            cg.a_load_const_cgpara(list,pushexceptaddr_frametype_cgsize,1,paraloc1);
+            cg.a_loadaddr_ref_cgpara(list,t.jmpbuf,paraloc2);
+            cg.a_loadaddr_ref_cgpara(list,t.envbuf,paraloc3);
+          end
+        else
+          begin
+            cg.a_loadaddr_ref_cgpara(list,t.envbuf,paraloc3);
+            cg.a_loadaddr_ref_cgpara(list,t.jmpbuf,paraloc2);
+            { push type of exceptionframe }
+            cg.a_load_const_cgpara(list,pushexceptaddr_frametype_cgsize,1,paraloc1);
+          end;
         paramanager.freecgpara(list,paraloc3);
         paramanager.freecgpara(list,paraloc2);
         paramanager.freecgpara(list,paraloc1);