Browse Source

+ limited thlcg.gen_load_cgpara_loc() implementation (only loc_reference
support), passed through to original ncgutils version in thlcg2ll
+ thlcgobj.location_force_mem() implementation
* order parameters for jvm similar to those for i386 without fixed_stack,
so we don't need temporary paralocations
* converted most of ncgcal to thlcg
* disabled special handling for virtual methods for jvm in ncgcal, as all
invocations are name-based there
+ njvmcal with special jvm callnode support:
o always move the function result into a memory temp
o when freeing an unused function result, use a_pop(2) and adjust
the internal evaluation stack height counter
o after the call instruction, adjust the evaluation stack height counter
by subtracting the number of the pushed parameter slots, adjusted for
the slots taken up by the function result

git-svn-id: branches/jvmbackend@18325 -

Jonas Maebe 14 years ago
parent
commit
9a9ea1f257
7 changed files with 222 additions and 18 deletions
  1. 1 0
      .gitattributes
  2. 6 0
      compiler/hlcg2ll.pas
  3. 80 1
      compiler/hlcgobj.pas
  4. 2 1
      compiler/jvm/cpunode.pas
  5. 107 0
      compiler/jvm/njvmcal.pas
  6. 8 6
      compiler/ncal.pas
  7. 18 10
      compiler/ncgcal.pas

+ 1 - 0
.gitattributes

@@ -218,6 +218,7 @@ compiler/jvm/cputarg.pas svneol=native#text/plain
 compiler/jvm/hlcgcpu.pas svneol=native#text/plain
 compiler/jvm/hlcgcpu.pas svneol=native#text/plain
 compiler/jvm/itcpujas.pas svneol=native#text/plain
 compiler/jvm/itcpujas.pas svneol=native#text/plain
 compiler/jvm/jvmreg.dat svneol=native#text/plain
 compiler/jvm/jvmreg.dat svneol=native#text/plain
+compiler/jvm/njvmcal.pas svneol=native#text/plain
 compiler/jvm/rgcpu.pas svneol=native#text/plain
 compiler/jvm/rgcpu.pas svneol=native#text/plain
 compiler/jvm/rjvmcon.inc svneol=native#text/plain
 compiler/jvm/rjvmcon.inc svneol=native#text/plain
 compiler/jvm/rjvmnor.inc svneol=native#text/plain
 compiler/jvm/rjvmnor.inc svneol=native#text/plain

+ 6 - 0
compiler/hlcg2ll.pas

@@ -395,6 +395,7 @@ unit hlcg2ll;
           procedure maketojumpbool(list:TAsmList; p : tnode);override;
           procedure maketojumpbool(list:TAsmList; p : tnode);override;
 
 
           procedure gen_load_loc_cgpara(list: TAsmList; vardef: tdef; const l: tlocation; const cgpara: tcgpara); override;
           procedure gen_load_loc_cgpara(list: TAsmList; vardef: tdef; const l: tlocation; const cgpara: tcgpara); override;
+          procedure gen_load_cgpara_loc(list: TAsmList; vardef: tdef; const para: TCGPara; var destloc: tlocation; reusepara: boolean); override;
        end;
        end;
 
 
 
 
@@ -1167,4 +1168,9 @@ procedure thlcg2ll.a_loadaddr_ref_reg(list: TAsmList; fromsize, tosize: tdef; co
       ncgutil.gen_load_loc_cgpara(list,vardef,l,cgpara);
       ncgutil.gen_load_loc_cgpara(list,vardef,l,cgpara);
     end;
     end;
 
 
+  procedure thlcg2ll.gen_load_cgpara_loc(list: TAsmList; vardef: tdef; const para: TCGPara; var destloc: tlocation; reusepara: boolean);
+    begin
+      ncgutil.gen_load_cgpara_loc(list, vardef, para, destloc, reusepara);
+    end;
+
 end.
 end.

+ 80 - 1
compiler/hlcgobj.pas

@@ -417,7 +417,7 @@ unit hlcgobj;
 
 
           procedure location_force_reg(list:TAsmList;var l:tlocation;src_size,dst_size:tdef;maybeconst:boolean);virtual;
           procedure location_force_reg(list:TAsmList;var l:tlocation;src_size,dst_size:tdef;maybeconst:boolean);virtual;
           procedure location_force_fpureg(list:TAsmList;var l: tlocation;size: tdef;maybeconst:boolean);virtual;abstract;
           procedure location_force_fpureg(list:TAsmList;var l: tlocation;size: tdef;maybeconst:boolean);virtual;abstract;
-          procedure location_force_mem(list:TAsmList;var l:tlocation;size:tdef);virtual;abstract;
+          procedure location_force_mem(list:TAsmList;var l:tlocation;size:tdef);virtual;
 //          procedure location_force_mmregscalar(list:TAsmList;var l: tlocation;size:tdef;maybeconst:boolean);virtual;abstract;
 //          procedure location_force_mmregscalar(list:TAsmList;var l: tlocation;size:tdef;maybeconst:boolean);virtual;abstract;
 //          procedure location_force_mmreg(list:TAsmList;var l: tlocation;size:tdef;maybeconst:boolean);virtual;abstract;
 //          procedure location_force_mmreg(list:TAsmList;var l: tlocation;size:tdef;maybeconst:boolean);virtual;abstract;
 
 
@@ -437,6 +437,9 @@ unit hlcgobj;
           { load a tlocation into a cgpara }
           { load a tlocation into a cgpara }
           procedure gen_load_loc_cgpara(list: TAsmList; vardef: tdef; const l: tlocation; const cgpara: tcgpara);virtual;
           procedure gen_load_loc_cgpara(list: TAsmList; vardef: tdef; const l: tlocation; const cgpara: tcgpara);virtual;
 
 
+          { load a cgpara into a tlocation }
+          procedure gen_load_cgpara_loc(list: TAsmList; vardef: tdef; const para: TCGPara; var destloc: tlocation; reusepara: boolean);virtual;
+
           { load the function return value into the ABI-defined function return location }
           { load the function return value into the ABI-defined function return location }
           procedure gen_load_return_value(list:TAsmList);virtual;
           procedure gen_load_return_value(list:TAsmList);virtual;
 
 
@@ -1640,6 +1643,57 @@ implementation
         location_freetemp(list,oldloc);
         location_freetemp(list,oldloc);
     end;
     end;
 
 
+  procedure thlcgobj.location_force_mem(list: TAsmList; var l: tlocation; size: tdef);
+    var
+      r : treference;
+    begin
+      case l.loc of
+        LOC_FPUREGISTER,
+        LOC_CFPUREGISTER :
+          begin
+            tg.GetTemp(list,TCGSize2Size[l.size],TCGSize2Size[l.size],tt_normal,r);
+            hlcg.a_loadfpu_reg_ref(list,size,size,l.register,r);
+            location_reset_ref(l,LOC_REFERENCE,l.size,0);
+            l.reference:=r;
+          end;
+(*
+        LOC_MMREGISTER,
+        LOC_CMMREGISTER:
+          begin
+            tg.GetTemp(list,TCGSize2Size[l.size],TCGSize2Size[l.size],tt_normal,r);
+            cg.a_loadmm_reg_ref(list,l.size,l.size,l.register,r,mms_movescalar);
+            location_reset_ref(l,LOC_REFERENCE,l.size,0);
+            l.reference:=r;
+          end;
+*)
+        LOC_CONSTANT,
+        LOC_REGISTER,
+        LOC_CREGISTER :
+          begin
+            tg.GetTemp(list,TCGSize2Size[l.size],TCGSize2Size[l.size],tt_normal,r);
+            hlcg.a_load_loc_ref(list,size,size,l,r);
+            location_reset_ref(l,LOC_REFERENCE,l.size,0);
+            l.reference:=r;
+          end;
+(*
+        LOC_SUBSETREG,
+        LOC_CSUBSETREG,
+        LOC_SUBSETREF,
+        LOC_CSUBSETREF:
+          begin
+            tg.GetTemp(list,TCGSize2Size[l.size],TCGSize2Size[l.size],tt_normal,r);
+            cg.a_load_loc_ref(list,l.size,l,r);
+            location_reset_ref(l,LOC_REFERENCE,l.size,0);
+            l.reference:=r;
+          end;
+*)
+        LOC_CREFERENCE,
+        LOC_REFERENCE : ;
+        else
+          internalerror(2011010304);
+      end;
+    end;
+
   procedure thlcgobj.gen_proc_symbol(list: TAsmList);
   procedure thlcgobj.gen_proc_symbol(list: TAsmList);
     var
     var
       item,
       item,
@@ -1825,6 +1879,31 @@ implementation
       end;
       end;
     end;
     end;
 
 
+  procedure thlcgobj.gen_load_cgpara_loc(list: TAsmList; vardef: tdef; const para: TCGPara; var destloc: tlocation; reusepara: boolean);
+    var
+      href     : treference;
+    begin
+      para.check_simple_location;
+      { skip e.g. empty records }
+      if (para.location^.loc = LOC_VOID) then
+        exit;
+      case destloc.loc of
+        LOC_REFERENCE :
+          begin
+            { If the parameter location is reused we don't need to copy
+              anything }
+            if not reusepara then
+              begin
+                reference_reset_base(href,para.location^.reference.index,para.location^.reference.offset,para.alignment);
+                a_load_ref_ref(list,para.def,para.def,href,destloc.reference);
+              end;
+          end;
+        { TODO other possible locations }
+        else
+          internalerror(2011010308);
+      end;
+    end;
+
   procedure thlcgobj.gen_load_return_value(list: TAsmList);
   procedure thlcgobj.gen_load_return_value(list: TAsmList);
     var
     var
       ressym : tabstractnormalvarsym;
       ressym : tabstractnormalvarsym;

+ 2 - 1
compiler/jvm/cpunode.pas

@@ -31,7 +31,8 @@ implementation
 
 
   uses
   uses
     ncgbas,ncgflw,ncgcnv,ncgld,ncgmem,ncgcon,ncgset,
     ncgbas,ncgflw,ncgcnv,ncgld,ncgmem,ncgcon,ncgset,
-    ncgadd, ncgcal,ncgmat,ncginl
+    ncgadd, ncgcal,ncgmat,ncginl,
+    njvmcal
 {    ncpuadd,ncpucall,ncpumat,ncpuinln,ncpucnv,ncpuset, }
 {    ncpuadd,ncpucall,ncpumat,ncpuinln,ncpucnv,ncpuset, }
     { this not really a node }
     { this not really a node }
 {    rgcpu},tgcpu;
 {    rgcpu},tgcpu;

+ 107 - 0
compiler/jvm/njvmcal.pas

@@ -0,0 +1,107 @@
+{
+    Copyright (c) 2011 by Jonas Maebe
+
+    JVM-specific code for call nodes
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit njvmcal;
+
+{$i fpcdefs.inc}
+
+interface
+
+    uses
+      symdef,
+      ncgcal;
+
+    type
+
+       { tjvmcallnode }
+
+       tjvmcallnode = class(tcgcallnode)
+        protected
+         procedure set_result_location(realresdef: tstoreddef); override;
+         procedure release_unused_return_value_cpu;override;
+         procedure extra_post_call_code; override;
+       end;
+
+
+implementation
+
+    uses
+      verbose,globtype,
+      symtype,defutil,ncal,
+      cgbase,cgutils,tgobj,
+      cpubase,aasmdata,aasmcpu,
+      hlcgobj,hlcgcpu;
+
+
+{*****************************************************************************
+                             TJVMCALLNODE
+*****************************************************************************}
+
+    procedure tjvmcallnode.set_result_location(realresdef: tstoreddef);
+      begin
+        location_reset_ref(location,LOC_REFERENCE,def_cgsize(realresdef),1);
+        tg.gettemp(current_asmdata.CurrAsmList,realresdef.size,1,tt_normal,location.reference);
+      end;
+
+
+    procedure tjvmcallnode.release_unused_return_value_cpu;
+      begin
+        case resultdef.size of
+          0:
+            ;
+          1..4:
+            begin
+              current_asmdata.CurrAsmList.concat(taicpu.op_none(a_pop));
+              thlcgjvm(hlcg).decstack(1);
+            end;
+          8:
+            begin
+              current_asmdata.CurrAsmList.concat(taicpu.op_none(a_pop2));
+              thlcgjvm(hlcg).decstack(2);
+            end
+          else
+            internalerror(2011010305);
+        end;
+      end;
+
+
+    procedure tjvmcallnode.extra_post_call_code;
+      var
+        totalremovesize: longint;
+        realresdef: tdef;
+      begin
+        if not assigned(typedef) then
+          realresdef:=tstoreddef(resultdef)
+        else
+          realresdef:=tstoreddef(typedef);
+        totalremovesize:=pushedparasize-realresdef.size;
+        { remove parameters from internal evaluation stack counter (in case of
+          e.g. no parameters and a result, it can also increase) }
+        if totalremovesize>0 then
+          thlcgjvm(hlcg).decstack(totalremovesize shr 2)
+        else if totalremovesize<0 then
+          thlcgjvm(hlcg).incstack((-totalremovesize) shr 2);
+      end;
+
+
+begin
+  ccallnode:=tjvmcallnode;
+end.

+ 8 - 6
compiler/ncal.pas

@@ -3155,18 +3155,20 @@ implementation
                               That means the for pushes the para with the
                               That means the for pushes the para with the
                               highest offset (see para3) needs to be pushed first
                               highest offset (see para3) needs to be pushed first
                             }
                             }
-{$ifdef i386}
-                            { the i386 code generator expects all reference }
-                            { parameter to be in this order so it can use   }
-                            { pushes in case of no fixed stack              }
+{$if defined(i386)}
+                            { the i386 and jvm code generators expect all reference }
+                            { parameters to be in this order so they can use   }
+                            { pushes in case of no fixed stack                 }
                             if (not paramanager.use_fixed_stack and
                             if (not paramanager.use_fixed_stack and
                                 (hpcurr.parasym.paraloc[callerside].location^.reference.offset>
                                 (hpcurr.parasym.paraloc[callerside].location^.reference.offset>
                                  hp.parasym.paraloc[callerside].location^.reference.offset)) or
                                  hp.parasym.paraloc[callerside].location^.reference.offset)) or
                                (paramanager.use_fixed_stack and
                                (paramanager.use_fixed_stack and
                                 (node_complexity(hpcurr)<node_complexity(hp))) then
                                 (node_complexity(hpcurr)<node_complexity(hp))) then
-{$else i386}
+{$elseif defined(jvm)}
+                            if (hpcurr.parasym.paraloc[callerside].location^.reference.offset<hp.parasym.paraloc[callerside].location^.reference.offset) then
+{$else jvm}
                             if (node_complexity(hpcurr)<node_complexity(hp)) then
                             if (node_complexity(hpcurr)<node_complexity(hp)) then
-{$endif i386}
+{$endif jvm}
                               break;
                               break;
                           end;
                           end;
                         LOC_MMREGISTER,
                         LOC_MMREGISTER,

+ 18 - 10
compiler/ncgcal.pas

@@ -43,6 +43,8 @@ interface
           procedure secondcallparan;override;
           procedure secondcallparan;override;
        end;
        end;
 
 
+       { tcgcallnode }
+
        tcgcallnode = class(tcallnode)
        tcgcallnode = class(tcallnode)
        private
        private
 
 
@@ -181,7 +183,7 @@ implementation
                        href,third.location,'FPC_DECREF_ARRAY');
                        href,third.location,'FPC_DECREF_ARRAY');
                    end
                    end
                  else
                  else
-                   cg.g_decrrefcount(current_asmdata.CurrAsmList,left.resultdef,href);
+                   hlcg.g_decrrefcount(current_asmdata.CurrAsmList,left.resultdef,href);
                end;
                end;
 
 
              paramanager.createtempparaloc(current_asmdata.CurrAsmList,aktcallnode.procdefinition.proccalloption,parasym,not followed_by_stack_tainting_call_cached,tempcgpara);
              paramanager.createtempparaloc(current_asmdata.CurrAsmList,aktcallnode.procdefinition.proccalloption,parasym,not followed_by_stack_tainting_call_cached,tempcgpara);
@@ -217,7 +219,7 @@ implementation
                   { allow passing of a constant to a const formaldef }
                   { allow passing of a constant to a const formaldef }
                   if (parasym.varspez=vs_const) and
                   if (parasym.varspez=vs_const) and
                      (left.location.loc in [LOC_CONSTANT,LOC_REGISTER]) then
                      (left.location.loc in [LOC_CONSTANT,LOC_REGISTER]) then
-                    location_force_mem(current_asmdata.CurrAsmList,left.location);
+                    hlcg.location_force_mem(current_asmdata.CurrAsmList,left.location,left.resultdef);
                   push_addr_para;
                   push_addr_para;
                end
                end
              { Normal parameter }
              { Normal parameter }
@@ -245,13 +247,13 @@ implementation
                           if (left.location.reference.index<>NR_NO) or
                           if (left.location.reference.index<>NR_NO) or
                              (left.location.reference.offset<>0) then
                              (left.location.reference.offset<>0) then
                             internalerror(200410107);
                             internalerror(200410107);
-                          cg.a_load_reg_cgpara(current_asmdata.CurrAsmList,OS_ADDR,left.location.reference.base,tempcgpara)
+                          hlcg.a_load_reg_cgpara(current_asmdata.CurrAsmList,voidpointertype,left.location.reference.base,tempcgpara)
                         end
                         end
                       else
                       else
                         begin
                         begin
                           { Force to be in memory }
                           { Force to be in memory }
                           if not(left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
                           if not(left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
-                            location_force_mem(current_asmdata.CurrAsmList,left.location);
+                            hlcg.location_force_mem(current_asmdata.CurrAsmList,left.location,left.resultdef);
                           push_addr_para;
                           push_addr_para;
                         end;
                         end;
                    end
                    end
@@ -371,7 +373,7 @@ implementation
             if (cnf_return_value_used in callnodeflags) or
             if (cnf_return_value_used in callnodeflags) or
                assigned(funcretnode) then
                assigned(funcretnode) then
               begin
               begin
-                gen_load_cgpara_loc(current_asmdata.CurrAsmList,realresdef,retloc,location,false);
+                hlcg.gen_load_cgpara_loc(current_asmdata.CurrAsmList,realresdef,retloc,location,false);
 {$ifdef arm}
 {$ifdef arm}
                 if (resultdef.typ=floatdef) and
                 if (resultdef.typ=floatdef) and
                    (location.loc=LOC_REGISTER) and
                    (location.loc=LOC_REGISTER) and
@@ -412,9 +414,9 @@ implementation
                 begin
                 begin
                   case funcretnode.location.loc of
                   case funcretnode.location.loc of
                     LOC_REGISTER:
                     LOC_REGISTER:
-                      cg.a_load_ref_reg(current_asmdata.CurrAsmList,location.size,location.size,location.reference,funcretnode.location.register);
+                      hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,resultdef,resultdef,location.reference,funcretnode.location.register);
                     LOC_REFERENCE:
                     LOC_REFERENCE:
-                      cg.g_concatcopy(current_asmdata.CurrAsmList,location.reference,funcretnode.location.reference,resultdef.size);
+                      hlcg.g_concatcopy(current_asmdata.CurrAsmList,resultdef,location.reference,funcretnode.location.reference);
                     else
                     else
                       internalerror(200802121);
                       internalerror(200802121);
                   end;
                   end;
@@ -439,7 +441,7 @@ implementation
               LOC_REFERENCE :
               LOC_REFERENCE :
                 begin
                 begin
                   if is_managed_type(resultdef) then
                   if is_managed_type(resultdef) then
-                     cg.g_finalize(current_asmdata.CurrAsmList,resultdef,location.reference);
+                     hlcg.g_finalize(current_asmdata.CurrAsmList,resultdef,location.reference);
                    tg.ungetiftemp(current_asmdata.CurrAsmList,location.reference);
                    tg.ungetiftemp(current_asmdata.CurrAsmList,location.reference);
                 end;
                 end;
               else
               else
@@ -719,6 +721,8 @@ implementation
              name_to_call:='';
              name_to_call:='';
              if assigned(fobjcforcedprocname) then
              if assigned(fobjcforcedprocname) then
                name_to_call:=fobjcforcedprocname^;
                name_to_call:=fobjcforcedprocname^;
+             { in the JVM, virtual method calls are also name-based }
+{$ifndef jvm}
              { When methodpointer is typen we don't need (and can't) load
              { When methodpointer is typen we don't need (and can't) load
                a pointer. We can directly call the correct procdef (PFV) }
                a pointer. We can directly call the correct procdef (PFV) }
              if (name_to_call='') and
              if (name_to_call='') and
@@ -788,6 +792,7 @@ implementation
                  extra_post_call_code;
                  extra_post_call_code;
                end
                end
              else
              else
+{$endif jvm}
                begin
                begin
                   { Load parameters that are in temporary registers in the
                   { Load parameters that are in temporary registers in the
                     correct parameter register }
                     correct parameter register }
@@ -814,9 +819,12 @@ implementation
                         extra_interrupt_code;
                         extra_interrupt_code;
                       extra_call_code;
                       extra_call_code;
                       if (name_to_call='') then
                       if (name_to_call='') then
-                        cg.a_call_name(current_asmdata.CurrAsmList,tprocdef(procdefinition).mangledname(false),po_weakexternal in procdefinition.procoptions)
+                        if cnf_inherited in callnodeflags then
+                          hlcg.a_call_name_inherited(current_asmdata.CurrAsmList,tprocdef(procdefinition),tprocdef(procdefinition).mangledname(false))
+                        else
+                          hlcg.a_call_name(current_asmdata.CurrAsmList,tprocdef(procdefinition),tprocdef(procdefinition).mangledname(false),po_weakexternal in procdefinition.procoptions)
                       else
                       else
-                        cg.a_call_name(current_asmdata.CurrAsmList,name_to_call,po_weakexternal in procdefinition.procoptions);
+                        hlcg.a_call_name(current_asmdata.CurrAsmList,tprocdef(procdefinition),name_to_call,po_weakexternal in procdefinition.procoptions);
                       extra_post_call_code;
                       extra_post_call_code;
                     end;
                     end;
                end;
                end;