mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-10-31 03:11:39 +01:00 
			
		
		
		
	 aa1be3276f
			
		
	
	
		aa1be3276f
		
	
	
	
	
		
			
			it was AT_NONE, which is invalid and should never be used
  * explicitly pass the correct value for all calls to those methods elsewhere
    in the compiler
git-svn-id: trunk@34250 -
		
	
			
		
			
				
	
	
		
			275 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			275 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
| {
 | |
|     Copyright (C) 2010 by Jonas Maebe
 | |
| 
 | |
|     This unit handles the temporary variables for the JVM
 | |
| 
 | |
|     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.
 | |
| 
 | |
|  ****************************************************************************
 | |
| }
 | |
| {
 | |
|   This unit handles the temporary variables for the JVM.
 | |
| }
 | |
| unit tgcpu;
 | |
| 
 | |
| {$i fpcdefs.inc}
 | |
| 
 | |
|   interface
 | |
| 
 | |
|     uses
 | |
|        globtype,
 | |
|        aasmdata,
 | |
|        cgutils,
 | |
|        symtype,tgobj;
 | |
| 
 | |
|     type
 | |
| 
 | |
|        { ttgjvm }
 | |
| 
 | |
|        ttgjvm = class(ttgobj)
 | |
|         protected
 | |
|          procedure getimplicitobjtemp(list: TAsmList; def: tdef; temptype: ttemptype; out ref: treference);
 | |
|          function getifspecialtemp(list: TAsmList; def: tdef; forcesize: asizeint; temptype: ttemptype; out ref: treference): boolean;
 | |
|          procedure alloctemp(list: TAsmList; size: asizeint; alignment: shortint; temptype: ttemptype; def: tdef; fini: boolean; out ref: treference); override;
 | |
|         public
 | |
|          procedure setfirsttemp(l : asizeint); override;
 | |
|          procedure getlocal(list: TAsmList; size: asizeint; alignment: shortint; def: tdef; var ref: treference); override;
 | |
|          procedure gethltemp(list: TAsmList; def: tdef; forcesize: asizeint; temptype: ttemptype; out ref: treference); override;
 | |
|          procedure gethltempmanaged(list: TAsmList; def: tdef; temptype: ttemptype; out ref: treference); override;
 | |
|        end;
 | |
| 
 | |
|   implementation
 | |
| 
 | |
|     uses
 | |
|        verbose,
 | |
|        cgbase,
 | |
|        symconst,symtable,symdef,symsym,symcpu,defutil,
 | |
|        cpubase,aasmbase,aasmcpu,
 | |
|        hlcgobj,hlcgcpu;
 | |
| 
 | |
| 
 | |
|     { ttgjvm }
 | |
| 
 | |
|     procedure ttgjvm.getimplicitobjtemp(list: TAsmList; def: tdef; temptype: ttemptype; out ref: treference);
 | |
|       var
 | |
|         sym: tsym;
 | |
|         pd: tprocdef;
 | |
|       begin
 | |
|         gettemp(list,java_jlobject.size,java_jlobject.alignment,temptype,ref);
 | |
|         list.concat(taicpu.op_sym(a_new,current_asmdata.RefAsmSymbol(tabstractrecorddef(def).jvm_full_typename(true),AT_METADATA)));
 | |
|         { the constructor doesn't return anything, so put a duplicate of the
 | |
|           self pointer on the evaluation stack for use as function result
 | |
|           after the constructor has run }
 | |
|         list.concat(taicpu.op_none(a_dup));
 | |
|         thlcgjvm(hlcg).incstack(list,2);
 | |
|         { call the constructor }
 | |
|         sym:=tsym(tabstractrecorddef(def).symtable.find('CREATE'));
 | |
|         if assigned(sym) and
 | |
|            (sym.typ=procsym) then
 | |
|           begin
 | |
|             pd:=tprocsym(sym).find_bytype_parameterless(potype_constructor);
 | |
|             if not assigned(pd) then
 | |
|               internalerror(2011032701);
 | |
|           end
 | |
|         else
 | |
|           internalerror(2011060301);
 | |
|         hlcg.a_call_name(list,pd,pd.mangledname,[],nil,false);
 | |
|         thlcgjvm(hlcg).decstack(list,1);
 | |
|         { store reference to instance }
 | |
|         thlcgjvm(hlcg).a_load_stack_ref(list,java_jlobject,ref,0);
 | |
|       end;
 | |
| 
 | |
| 
 | |
|     function ttgjvm.getifspecialtemp(list: TAsmList; def: tdef; forcesize: asizeint; temptype: ttemptype; out ref: treference): boolean;
 | |
|       var
 | |
|         eledef: tdef;
 | |
|         ndim: longint;
 | |
|         sym: tsym;
 | |
|         pd: tprocdef;
 | |
|       begin
 | |
|         result:=false;
 | |
|         case def.typ of
 | |
|           arraydef:
 | |
|             begin
 | |
|               if not is_dynamic_array(def) then
 | |
|                 begin
 | |
|                   { allocate an array of the right size }
 | |
|                   gettemp(list,java_jlobject.size,java_jlobject.alignment,temptype,ref);
 | |
|                   ndim:=0;
 | |
|                   eledef:=def;
 | |
|                   repeat
 | |
|                     if forcesize<>-1 then
 | |
|                       thlcgjvm(hlcg).a_load_const_stack(list,s32inttype,forcesize div tarraydef(eledef).elesize,R_INTREGISTER)
 | |
|                     else
 | |
|                       thlcgjvm(hlcg).a_load_const_stack(list,s32inttype,tarraydef(eledef).elecount,R_INTREGISTER);
 | |
|                     eledef:=tarraydef(eledef).elementdef;
 | |
|                     inc(ndim);
 | |
|                     forcesize:=-1;
 | |
|                   until (eledef.typ<>arraydef) or
 | |
|                         is_dynamic_array(eledef);
 | |
|                   eledef:=tarraydef(def).elementdef;
 | |
|                   thlcgjvm(hlcg).g_newarray(list,def,ndim);
 | |
|                   thlcgjvm(hlcg).a_load_stack_ref(list,java_jlobject,ref,0);
 | |
|                   result:=true;
 | |
|                 end;
 | |
|             end;
 | |
|           recorddef:
 | |
|             begin
 | |
|               getimplicitobjtemp(list,def,temptype,ref);
 | |
|               result:=true;
 | |
|             end;
 | |
|           setdef:
 | |
|             begin
 | |
|               if tsetdef(def).elementdef.typ=enumdef then
 | |
|                 begin
 | |
|                   { load enum class type }
 | |
|                   list.concat(taicpu.op_sym(a_ldc,current_asmdata.RefAsmSymbol(tcpuenumdef(tenumdef(tsetdef(def).elementdef).getbasedef).classdef.jvm_full_typename(true),AT_METADATA)));
 | |
|                   thlcgjvm(hlcg).incstack(current_asmdata.CurrAsmList,1);
 | |
|                   { call tenumset.noneOf() class method }
 | |
|                   sym:=tsym(tobjectdef(java_juenumset).symtable.find('NONEOF'));
 | |
|                   if assigned(sym) and
 | |
|                      (sym.typ=procsym) then
 | |
|                     begin
 | |
|                       if tprocsym(sym).procdeflist.Count<>1 then
 | |
|                         internalerror(2011062801);
 | |
|                       pd:=tprocdef(tprocsym(sym).procdeflist[0]);
 | |
|                       hlcg.a_call_name(list,pd,pd.mangledname,[],nil,false);
 | |
|                     end;
 | |
|                   { static calls method replaces parameter with set instance
 | |
|                     -> no change in stack height }
 | |
|                 end
 | |
|               else
 | |
|                 begin
 | |
|                   list.concat(taicpu.op_sym(a_new,current_asmdata.RefAsmSymbol(java_jubitset.jvm_full_typename(true),AT_METADATA)));
 | |
|                   { the constructor doesn't return anything, so put a duplicate of the
 | |
|                     self pointer on the evaluation stack for use as function result
 | |
|                     after the constructor has run }
 | |
|                   list.concat(taicpu.op_none(a_dup));
 | |
|                   thlcgjvm(hlcg).incstack(list,2);
 | |
|                   { call the constructor }
 | |
|                   sym:=tsym(java_jubitset.symtable.find('CREATE'));
 | |
|                   if assigned(sym) and
 | |
|                      (sym.typ=procsym) then
 | |
|                     begin
 | |
|                       pd:=tprocsym(sym).find_bytype_parameterless(potype_constructor);
 | |
|                       if not assigned(pd) then
 | |
|                         internalerror(2011062802);
 | |
|                     end
 | |
|                   else
 | |
|                     internalerror(2011062803);
 | |
|                   hlcg.a_call_name(list,pd,pd.mangledname,[],nil,false);
 | |
|                   { duplicate self pointer is removed }
 | |
|                   thlcgjvm(hlcg).decstack(list,1);
 | |
|                 end;
 | |
|               { store reference to instance }
 | |
|               gettemp(list,java_jlobject.size,java_jlobject.alignment,temptype,ref);
 | |
|               thlcgjvm(hlcg).a_load_stack_ref(list,java_jlobject,ref,0);
 | |
|               result:=true;
 | |
|             end;
 | |
|           procvardef:
 | |
|             begin
 | |
|               if not tprocvardef(def).is_addressonly then
 | |
|                 begin
 | |
|                   getimplicitobjtemp(list,tcpuprocvardef(def).classdef,temptype,ref);
 | |
|                   result:=true;
 | |
|                 end;
 | |
|             end;
 | |
|           stringdef:
 | |
|             begin
 | |
|               if is_shortstring(def) then
 | |
|                 begin
 | |
|                   gettemp(list,java_jlobject.size,java_jlobject.alignment,temptype,ref);
 | |
|                   { add the maxlen parameter (s8inttype because parameters must
 | |
|                     be sign extended) }
 | |
|                   thlcgjvm(hlcg).a_load_const_stack(list,s8inttype,shortint(tstringdef(def).len),R_INTREGISTER);
 | |
|                   { call the constructor }
 | |
|                   sym:=tsym(tobjectdef(java_shortstring).symtable.find('CREATEEMPTY'));
 | |
|                   if assigned(sym) and
 | |
|                      (sym.typ=procsym) then
 | |
|                     begin
 | |
|                       if tprocsym(sym).procdeflist.Count<>1 then
 | |
|                         internalerror(2011052404);
 | |
|                       pd:=tprocdef(tprocsym(sym).procdeflist[0]);
 | |
|                       hlcg.a_call_name(list,pd,pd.mangledname,[],nil,false);
 | |
|                     end;
 | |
|                   { static calls method replaces parameter with string instance
 | |
|                     -> no change in stack height }
 | |
|                   { store reference to instance }
 | |
|                   thlcgjvm(hlcg).a_load_stack_ref(list,java_jlobject,ref,0);
 | |
|                   result:=true;
 | |
|                 end;
 | |
|             end;
 | |
|           filedef:
 | |
|             begin
 | |
|               case tfiledef(def).filetyp of
 | |
|                 ft_text:
 | |
|                   result:=getifspecialtemp(list,search_system_type('TEXTREC').typedef,forcesize,temptype,ref);
 | |
|                 ft_typed,
 | |
|                 ft_untyped:
 | |
|                   result:=getifspecialtemp(list,search_system_type('FILEREC').typedef,forcesize,temptype,ref);
 | |
|                 else
 | |
|                   internalerror(2015091405);
 | |
|               end;
 | |
|             end;
 | |
|         end;
 | |
|       end;
 | |
| 
 | |
| 
 | |
|     procedure ttgjvm.alloctemp(list: TAsmList; size: asizeint; alignment: shortint; temptype: ttemptype; def: tdef; fini: boolean; out ref: treference);
 | |
|       begin
 | |
|         { the JVM only supports 1 slot (= 4 bytes in FPC) and 2 slot (= 8 bytes in
 | |
|           FPC) temps on the stack. double and int64 are 2 slots, the rest is one slot.
 | |
|           There are no problems with reusing the same slot for a value of a different
 | |
|           type. There are no alignment requirements either. }
 | |
|         if size<4 then
 | |
|           size:=4;
 | |
|         if not(size in [4,8]) then
 | |
|           internalerror(2010121401);
 | |
|         { don't pass on "def", since we don't care if a slot is used again for a
 | |
|           different type }
 | |
|         inherited alloctemp(list, size shr 2, 1, temptype, nil, false, ref);
 | |
|       end;
 | |
| 
 | |
| 
 | |
|     procedure ttgjvm.setfirsttemp(l: asizeint);
 | |
|       begin
 | |
|         firsttemp:=l;
 | |
|         lasttemp:=l;
 | |
|       end;
 | |
| 
 | |
| 
 | |
|     procedure ttgjvm.getlocal(list: TAsmList; size: asizeint; alignment: shortint; def: tdef; var ref: treference);
 | |
|       begin
 | |
|         if not getifspecialtemp(list,def,size,tt_persistent,ref) then
 | |
|           inherited;
 | |
|       end;
 | |
| 
 | |
| 
 | |
|     procedure ttgjvm.gethltemp(list: TAsmList; def: tdef; forcesize: asizeint; temptype: ttemptype; out ref: treference);
 | |
|       begin
 | |
|         if not getifspecialtemp(list,def,forcesize,temptype,ref) then
 | |
|           inherited;
 | |
|       end;
 | |
| 
 | |
|     procedure ttgjvm.gethltempmanaged(list: TAsmList; def: tdef; temptype: ttemptype; out ref: treference);
 | |
|       begin
 | |
|         gethltemp(list,def,def.size,temptype,ref);
 | |
|       end;
 | |
| 
 | |
| 
 | |
| begin
 | |
|   tgobjclass:=ttgjvm;
 | |
| end.
 |