mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-10-31 10:11:27 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			1311 lines
		
	
	
		
			54 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			1311 lines
		
	
	
		
			54 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
| {
 | |
|     $Id$
 | |
|     Copyright (c) 1998-2002 by Florian Klaempfl
 | |
| 
 | |
|     Generate assembler for nodes that handle loads and assignments which
 | |
|     are the same for all (most) processors
 | |
| 
 | |
|     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 ncgld;
 | |
| 
 | |
| {$i fpcdefs.inc}
 | |
| 
 | |
| interface
 | |
| 
 | |
|     uses
 | |
|       node,nld;
 | |
| 
 | |
|     type
 | |
|        tcgloadnode = class(tloadnode)
 | |
|           procedure pass_2;override;
 | |
|        end;
 | |
| 
 | |
|        tcgassignmentnode = class(tassignmentnode)
 | |
|           procedure pass_2;override;
 | |
|        end;
 | |
| 
 | |
|        tcgarrayconstructornode = class(tarrayconstructornode)
 | |
|           procedure pass_2;override;
 | |
|        end;
 | |
| 
 | |
| 
 | |
| implementation
 | |
| 
 | |
|     uses
 | |
|       cutils,
 | |
|       systems,
 | |
|       verbose,globtype,globals,
 | |
|       symconst,symtype,symdef,symsym,defutil,paramgr,
 | |
|       ncnv,ncon,nmem,nbas,
 | |
|       aasmbase,aasmtai,
 | |
|       cgbase,pass_2,
 | |
|       procinfo,
 | |
|       cpubase,cpuinfo,
 | |
|       tgobj,ncgutil,cgobj,ncgbas;
 | |
| 
 | |
| {*****************************************************************************
 | |
|                              SecondLoad
 | |
| *****************************************************************************}
 | |
| 
 | |
|     procedure tcgloadnode.pass_2;
 | |
|       var
 | |
|         hregister : tregister;
 | |
|         supreg:Tsuperregister;
 | |
|         symtabletype : tsymtabletype;
 | |
|         href : treference;
 | |
|         newsize : tcgsize;
 | |
|         endrelocatelab,
 | |
|         norelocatelab : tasmlabel;
 | |
|         paraloc1 : tparalocation;
 | |
|       begin
 | |
|          { we don't know the size of all arrays }
 | |
|          newsize:=def_cgsize(resulttype.def);
 | |
|          location_reset(location,LOC_REFERENCE,newsize);
 | |
|          case symtableentry.typ of
 | |
|             absolutesym :
 | |
|                begin
 | |
|                   { this is only for toasm and toaddr }
 | |
|                   case tabsolutesym(symtableentry).abstyp of
 | |
|                     toaddr :
 | |
|                       begin
 | |
| {$ifdef i386}
 | |
|                         if tabsolutesym(symtableentry).absseg then
 | |
|                           location.reference.segment:=NR_FS;
 | |
| {$endif i386}
 | |
|                         location.reference.offset:=tabsolutesym(symtableentry).fieldoffset;
 | |
|                       end;
 | |
|                     toasm :
 | |
|                       location.reference.symbol:=objectlibrary.newasmsymboldata(tabsolutesym(symtableentry).mangledname);
 | |
|                     else
 | |
|                       internalerror(200310283);
 | |
|                   end;
 | |
|                end;
 | |
|             constsym:
 | |
|               begin
 | |
|                  if tconstsym(symtableentry).consttyp=constresourcestring then
 | |
|                    begin
 | |
|                       location_reset(location,LOC_CREFERENCE,OS_ADDR);
 | |
|                       location.reference.symbol:=objectlibrary.newasmsymboldata(make_mangledname('RESOURCESTRINGLIST',tconstsym(symtableentry).owner,''));
 | |
|                       location.reference.offset:=tconstsym(symtableentry).resstrindex*16+8;
 | |
|                    end
 | |
|                  else
 | |
|                    internalerror(22798);
 | |
|               end;
 | |
|             varsym :
 | |
|                begin
 | |
|                   if (tvarsym(symtableentry).varspez=vs_const) then
 | |
|                     location_reset(location,LOC_CREFERENCE,newsize);
 | |
|                   symtabletype:=symtable.symtabletype;
 | |
|                   hregister:=NR_NO;
 | |
|                   { C variable }
 | |
|                   if (vo_is_C_var in tvarsym(symtableentry).varoptions) then
 | |
|                     begin
 | |
|                        location.reference.symbol:=objectlibrary.newasmsymboldata(tvarsym(symtableentry).mangledname);
 | |
|                     end
 | |
|                   { DLL variable }
 | |
|                   else if (vo_is_dll_var in tvarsym(symtableentry).varoptions) then
 | |
|                     begin
 | |
|                        hregister:=cg.getaddressregister(exprasmlist);
 | |
|                        location.reference.symbol:=objectlibrary.newasmsymboldata(tvarsym(symtableentry).mangledname);
 | |
|                        cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,location.reference,hregister);
 | |
|                        reference_reset_base(location.reference,hregister,0);
 | |
|                     end
 | |
|                   { external variable }
 | |
|                   else if (vo_is_external in tvarsym(symtableentry).varoptions) then
 | |
|                     begin
 | |
|                        location.reference.symbol:=objectlibrary.newasmsymboldata(tvarsym(symtableentry).mangledname);
 | |
|                     end
 | |
|                   { thread variable }
 | |
|                   else if (vo_is_thread_var in tvarsym(symtableentry).varoptions) then
 | |
|                     begin
 | |
|                        {
 | |
|                          Thread var loading is optimized to first check if
 | |
|                          a relocate function is available. When the function
 | |
|                          is available it is called to retrieve the address.
 | |
|                          Otherwise the address is loaded with the symbol
 | |
| 
 | |
|                          The code needs to be in the order to first handle the
 | |
|                          call and then the address load to be sure that the
 | |
|                          register that is used for returning is the same (PFV)
 | |
|                        }
 | |
|                        objectlibrary.getlabel(norelocatelab);
 | |
|                        objectlibrary.getlabel(endrelocatelab);
 | |
|                        { make sure hregister can't allocate the register necessary for the parameter }
 | |
|                        paraloc1:=paramanager.getintparaloc(pocall_default,1);
 | |
|                        hregister:=cg.getaddressregister(exprasmlist);
 | |
|                        reference_reset_symbol(href,objectlibrary.newasmsymboldata('FPC_THREADVAR_RELOCATE'),0);
 | |
|                        cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,hregister);
 | |
|                        cg.ungetregister(exprasmlist,hregister);
 | |
|                        cg.a_cmp_const_reg_label(exprasmlist,OS_ADDR,OC_EQ,0,hregister,norelocatelab);
 | |
|                        { don't save the allocated register else the result will be destroyed later }
 | |
|                        reference_reset_symbol(href,objectlibrary.newasmsymboldata(tvarsym(symtableentry).mangledname),0);
 | |
|                        paramanager.allocparaloc(exprasmlist,paraloc1);
 | |
|                        cg.a_param_ref(exprasmlist,OS_ADDR,href,paraloc1);
 | |
|                        paramanager.freeparaloc(exprasmlist,paraloc1);
 | |
|                        cg.allocexplicitregisters(exprasmlist,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
 | |
|                        cg.a_call_reg(exprasmlist,hregister);
 | |
|                        cg.deallocexplicitregisters(exprasmlist,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
 | |
|                        cg.getexplicitregister(exprasmlist,NR_FUNCTION_RESULT_REG);
 | |
|                        cg.ungetregister(exprasmlist,NR_FUNCTION_RESULT_REG);
 | |
|                        hregister:=cg.getaddressregister(exprasmlist);
 | |
|                        cg.a_load_reg_reg(exprasmlist,OS_INT,OS_ADDR,NR_FUNCTION_RESULT_REG,hregister);
 | |
|                        cg.a_jmp_always(exprasmlist,endrelocatelab);
 | |
|                        cg.a_label(exprasmlist,norelocatelab);
 | |
|                        { no relocation needed, load the address of the variable only, the
 | |
|                          layout of a threadvar is (4 bytes pointer):
 | |
|                            0 - Threadvar index
 | |
|                            4 - Threadvar value in single threading }
 | |
|                        reference_reset_symbol(href,objectlibrary.newasmsymboldata(tvarsym(symtableentry).mangledname),POINTER_SIZE);
 | |
|                        cg.a_loadaddr_ref_reg(exprasmlist,href,hregister);
 | |
|                        cg.a_label(exprasmlist,endrelocatelab);
 | |
|                        location.reference.base:=hregister;
 | |
|                     end
 | |
|                   { nested variable }
 | |
|                   else if assigned(left) then
 | |
|                     begin
 | |
|                       if not(symtabletype in [localsymtable,parasymtable]) then
 | |
|                         internalerror(200309285);
 | |
|                       secondpass(left);
 | |
|                       if left.location.loc<>LOC_REGISTER then
 | |
|                         internalerror(200309286);
 | |
|                       hregister:=left.location.register;
 | |
|                       location.reference.base:=hregister;
 | |
|                       location.reference.offset:=tvarsym(symtableentry).localloc.reference.offset;
 | |
|                     end
 | |
|                   { normal variable }
 | |
|                   else
 | |
|                     begin
 | |
|                        {$warning fixme regvars}
 | |
|                        { in case it is a register variable: }
 | |
| {                       if tvarsym(symtableentry).localloc.loc=LOC_REGISTER then
 | |
|                          begin
 | |
|                             case getregtype(tvarsym(symtableentry).localloc.register) of
 | |
|                               R_FPUREGISTER :
 | |
|                                 begin
 | |
|                                    location_reset(location,LOC_CFPUREGISTER,def_cgsize(resulttype.def));
 | |
|                                    location.register:=tvarsym(symtableentry).localloc.register;
 | |
|                                 end;
 | |
|                               R_INTREGISTER :
 | |
|                                 begin
 | |
|                                   supreg:=getsupreg(Tvarsym(symtableentry).localloc.register);
 | |
|                                   if (supreg in general_superregisters) and
 | |
|                                      not (supreg in rg.regvar_loaded_int) then
 | |
|                                     load_regvar(exprasmlist,tvarsym(symtableentry));
 | |
|                                   location_reset(location,LOC_CREGISTER,def_cgsize(resulttype.def));
 | |
|                                   location.register:=tvarsym(symtableentry).localloc.register;
 | |
|                                   exclude(rg.unusedregsint,supreg);
 | |
|                                   hregister := location.register;
 | |
|                                 end;
 | |
|                               else
 | |
|                                 internalerror(200301172);
 | |
|                             end;
 | |
|                          end
 | |
|                        else}
 | |
|                          begin
 | |
|                            case symtabletype of
 | |
|                               localsymtable,
 | |
|                               parasymtable :
 | |
|                                 begin
 | |
|                                   if tvarsym(symtableentry).localloc.loc<>LOC_REFERENCE then
 | |
|                                     internalerror(2003091816);
 | |
|                                   location.reference.base:=tvarsym(symtableentry).localloc.reference.index;
 | |
|                                   location.reference.offset:=tvarsym(symtableentry).localloc.reference.offset;
 | |
|                                 end;
 | |
|                               globalsymtable,
 | |
|                               staticsymtable :
 | |
|                                 begin
 | |
|                                   if cs_create_pic in aktmoduleswitches then
 | |
|                                     begin
 | |
|                                       location.reference.base:=current_procinfo.got;
 | |
|                                       location.reference.symbol:=objectlibrary.newasmsymboldata(tvarsym(symtableentry).mangledname+'@GOT');
 | |
|                                     end
 | |
|                                   else
 | |
|                                     location.reference.symbol:=objectlibrary.newasmsymboldata(tvarsym(symtableentry).mangledname);
 | |
|                                 end;
 | |
|                               stt_exceptsymtable:
 | |
|                                 begin
 | |
|                                   if tvarsym(symtableentry).localloc.loc<>LOC_REFERENCE then
 | |
|                                     internalerror(2003091817);
 | |
|                                   location.reference.base:=tvarsym(symtableentry).localloc.reference.index;
 | |
|                                   location.reference.offset:=tvarsym(symtableentry).localloc.reference.offset;
 | |
|                                 end;
 | |
|                               else
 | |
|                                 internalerror(200305102);
 | |
|                            end;
 | |
|                          end;
 | |
|                     end;
 | |
| 
 | |
|                   { handle call by reference variables when they are not
 | |
|                     alreayd copied to local copies. Also ignore the reference
 | |
|                     when we need to load the self pointer for objects }
 | |
|                   if (symtabletype=parasymtable) and
 | |
|                      not(vo_has_local_copy in tvarsym(symtableentry).varoptions) and
 | |
|                      not(nf_load_self_pointer in flags) and
 | |
|                      paramanager.push_addr_param(tvarsym(symtableentry).varspez,tvarsym(symtableentry).vartype.def,tprocdef(symtable.defowner).proccalloption) then
 | |
|                     begin
 | |
|                       if hregister=NR_NO then
 | |
|                         hregister:=cg.getaddressregister(exprasmlist);
 | |
|                       { we need to load only an address }
 | |
|                       location.size:=OS_ADDR;
 | |
|                       cg.a_load_loc_reg(exprasmlist,location.size,location,hregister);
 | |
|                       if tvarsym(symtableentry).varspez=vs_const then
 | |
|                        location_reset(location,LOC_CREFERENCE,newsize)
 | |
|                       else
 | |
|                        location_reset(location,LOC_REFERENCE,newsize);
 | |
|                       location.reference.base:=hregister;
 | |
|                     end;
 | |
|                end;
 | |
|             procsym:
 | |
|                begin
 | |
|                   if not assigned(procdef) then
 | |
|                     internalerror(200312011);
 | |
|                   if assigned(left) then
 | |
|                     begin
 | |
|                       {
 | |
|                         THIS IS A TERRIBLE HACK!!!!!! WHICH WILL NOT WORK
 | |
|                         ON 64-BIT SYSTEMS: SINCE PROCSYM FOR METHODS
 | |
|                         CONSISTS OF TWO OS_ADDR, so you cannot set it
 | |
|                         to OS_64 - how to solve?? Carl
 | |
|                       }
 | |
|                       if (sizeof(aword) = 4) then
 | |
|                          location_reset(location,LOC_CREFERENCE,OS_64)
 | |
|                       else
 | |
|                          internalerror(20020520);
 | |
|                       tg.GetTemp(exprasmlist,2*POINTER_SIZE,tt_normal,location.reference);
 | |
|                       secondpass(left);
 | |
| 
 | |
|                       { load class instance address }
 | |
|                       case left.location.loc of
 | |
|                          LOC_CREGISTER,
 | |
|                          LOC_REGISTER:
 | |
|                            begin
 | |
|                               { this is not possible for objects }
 | |
|                               if is_object(left.resulttype.def) then
 | |
|                                 internalerror(200304234);
 | |
|                               hregister:=left.location.register;
 | |
|                            end;
 | |
|                          LOC_CREFERENCE,
 | |
|                          LOC_REFERENCE:
 | |
|                            begin
 | |
|                               location_release(exprasmlist,left.location);
 | |
|                               hregister:=cg.getaddressregister(exprasmlist);
 | |
|                               if is_class_or_interface(left.resulttype.def) then
 | |
|                                 cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,left.location.reference,hregister)
 | |
|                               else
 | |
|                                 cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,hregister);
 | |
|                               location_freetemp(exprasmlist,left.location);
 | |
|                            end;
 | |
|                          else
 | |
|                            internalerror(26019);
 | |
|                       end;
 | |
| 
 | |
|                       { store the class instance address }
 | |
|                       href:=location.reference;
 | |
|                       inc(href.offset,POINTER_SIZE);
 | |
|                       cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,hregister,href);
 | |
| 
 | |
|                       { virtual method ? }
 | |
|                       if (po_virtualmethod in procdef.procoptions) then
 | |
|                         begin
 | |
|                           { load vmt pointer }
 | |
|                           reference_reset_base(href,hregister,0);
 | |
|                           reference_release(exprasmlist,href);
 | |
|                           hregister:=cg.getaddressregister(exprasmlist);
 | |
|                           cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,hregister);
 | |
| 
 | |
| 
 | |
|                           reference_reset_base(href,hregister,
 | |
|                               procdef._class.vmtmethodoffset(procdef.extnumber));
 | |
|                           reference_release(exprasmlist,href);
 | |
| 
 | |
|                           { load method address }
 | |
|                           hregister:=cg.getaddressregister(exprasmlist);
 | |
|                           cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,hregister);
 | |
|                           { ... and store it }
 | |
|                           cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,hregister,location.reference);
 | |
|                           cg.ungetregister(exprasmlist,hregister);
 | |
|                         end
 | |
|                       else
 | |
|                         begin
 | |
|                           { we don't use the hregister }
 | |
|                           cg.ungetregister(exprasmlist,hregister);
 | |
|                           { load address of the function }
 | |
|                           reference_reset_symbol(href,objectlibrary.newasmsymbol(procdef.mangledname),0);
 | |
|                           hregister:=cg.getaddressregister(exprasmlist);
 | |
|                           cg.a_loadaddr_ref_reg(exprasmlist,href,hregister);
 | |
|                           cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,hregister,location.reference);
 | |
|                           cg.ungetregister(exprasmlist,hregister);
 | |
|                         end;
 | |
|                     end
 | |
|                   else
 | |
|                     begin
 | |
|                        {!!!!! Be aware, work on virtual methods too }
 | |
|                        location.reference.symbol:=objectlibrary.newasmsymbol(procdef.mangledname);
 | |
|                     end;
 | |
|                end;
 | |
|             typedconstsym :
 | |
|                begin
 | |
|                   location.reference.symbol:=objectlibrary.newasmsymboldata(ttypedconstsym(symtableentry).mangledname);
 | |
|                end;
 | |
|             else internalerror(4);
 | |
|          end;
 | |
|       end;
 | |
| 
 | |
| 
 | |
| {*****************************************************************************
 | |
|                              SecondAssignment
 | |
| *****************************************************************************}
 | |
| 
 | |
|     procedure tcgassignmentnode.pass_2;
 | |
|       var
 | |
|          otlabel,hlabel,oflabel : tasmlabel;
 | |
|          fputyp : tfloattype;
 | |
|          href : treference;
 | |
|          old_allow_multi_pass2,
 | |
|          releaseright : boolean;
 | |
|          cgsize : tcgsize;
 | |
|          r:Tregister;
 | |
| 
 | |
|       begin
 | |
|         location_reset(location,LOC_VOID,OS_NO);
 | |
| 
 | |
|         otlabel:=truelabel;
 | |
|         oflabel:=falselabel;
 | |
|         objectlibrary.getlabel(truelabel);
 | |
|         objectlibrary.getlabel(falselabel);
 | |
| 
 | |
|         {
 | |
|           in most cases we can process first the right node which contains
 | |
|           the most complex code. But not when the result is in the flags, then
 | |
|           loading the left node afterwards can destroy the flags.
 | |
| 
 | |
|           when the right node returns as LOC_JUMP then we will generate
 | |
|           the following code:
 | |
| 
 | |
|           rightnode
 | |
|           true:
 | |
|             leftnode
 | |
|             assign 1
 | |
|           false:
 | |
|             leftnode
 | |
|             assign 0
 | |
|         }
 | |
| 
 | |
|         { Try to determine which side to calculate first,  }
 | |
|         if (right.expectloc<>LOC_FLAGS) and
 | |
|            ((right.expectloc=LOC_JUMP) or
 | |
|             (right.nodetype=calln) or
 | |
|             (right.registers32>=left.registers32)) then
 | |
|          begin
 | |
|            secondpass(right);
 | |
|            { increment source reference counter, this is
 | |
|              useless for string constants}
 | |
|            if (right.resulttype.def.needs_inittable) and
 | |
|               (right.nodetype<>stringconstn) then
 | |
|             cg.g_incrrefcount(exprasmlist,right.resulttype.def,right.location.reference,false);
 | |
|            if codegenerror then
 | |
|              exit;
 | |
| 
 | |
|            { We skip the generation of the left node when it's a jump, see
 | |
|              explanation above }
 | |
|            if (right.location.loc<>LOC_JUMP) and
 | |
|               not(nf_concat_string in flags) then
 | |
|             begin
 | |
|               { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
 | |
|               { can be false                                             }
 | |
|               secondpass(left);
 | |
|               { decrement destination reference counter }
 | |
|               if (left.resulttype.def.needs_inittable) then
 | |
|                cg.g_decrrefcount(exprasmlist,left.resulttype.def,left.location.reference,false);
 | |
|               if codegenerror then
 | |
|                 exit;
 | |
|             end;
 | |
|          end
 | |
|         else
 | |
|          begin
 | |
|            { calculate left sides }
 | |
|            { don't do it yet if it's a crgister (JM) }
 | |
|            if not(nf_concat_string in flags) then
 | |
|             begin
 | |
|               secondpass(left);
 | |
|               { decrement destination reference counter }
 | |
|               if (left.resulttype.def.needs_inittable) then
 | |
|                cg.g_decrrefcount(exprasmlist,left.resulttype.def,left.location.reference,false);
 | |
|               if codegenerror then
 | |
|                exit;
 | |
|             end;
 | |
| 
 | |
|            { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
 | |
|            { can be false                                             }
 | |
|            secondpass(right);
 | |
|            { increment source reference counter, this is
 | |
|              useless for string constants}
 | |
|            if (right.resulttype.def.needs_inittable) and
 | |
|               (right.nodetype<>stringconstn) then
 | |
|             cg.g_incrrefcount(exprasmlist,right.resulttype.def,right.location.reference,false);
 | |
| 
 | |
|            if codegenerror then
 | |
|              exit;
 | |
|          end;
 | |
| 
 | |
|         releaseright:=true;
 | |
| 
 | |
|         { optimize temp to temp copies }
 | |
|         if (left.nodetype = temprefn) and
 | |
|            { we may store certain temps in registers in the future, then this }
 | |
|            { optimization will have to be adapted                             }
 | |
|            (left.location.loc = LOC_REFERENCE) and
 | |
|            (right.location.loc = LOC_REFERENCE) and
 | |
|            tg.istemp(right.location.reference) and
 | |
|            (tg.sizeoftemp(exprasmlist,right.location.reference) = tg.sizeoftemp(exprasmlist,left.location.reference)) then
 | |
|           begin
 | |
|             { in theory, we should also make sure the left temp type is   }
 | |
|             { already more or less of the same kind (ie. we must not      }
 | |
|             { assign an ansistring to a normaltemp). In practice, the     }
 | |
|             { assignment node will have already taken care of this for us }
 | |
|             tcgtemprefnode(left).changelocation(right.location.reference);
 | |
|           end
 | |
|         { shortstring assignments are handled separately }
 | |
|         else if is_shortstring(left.resulttype.def) then
 | |
|           begin
 | |
|             {
 | |
|               we can get here only in the following situations
 | |
|               for the right node:
 | |
|                - empty constant string
 | |
|                - char
 | |
|             }
 | |
| 
 | |
|             { empty constant string }
 | |
|             if (right.nodetype=stringconstn) and
 | |
|                (tstringconstnode(right).len=0) then
 | |
|               begin
 | |
|                 cg.a_load_const_ref(exprasmlist,OS_8,0,left.location.reference);
 | |
|               end
 | |
|             { char loading }
 | |
|             else if is_char(right.resulttype.def) then
 | |
|               begin
 | |
|                 if right.nodetype=ordconstn then
 | |
|                   begin
 | |
|                     if (target_info.endian = endian_little) then
 | |
|                       cg.a_load_const_ref(exprasmlist,OS_16,(tordconstnode(right).value shl 8) or 1,
 | |
|                           left.location.reference)
 | |
|                     else
 | |
|                       cg.a_load_const_ref(exprasmlist,OS_16,tordconstnode(right).value or (1 shl 8),
 | |
|                           left.location.reference);
 | |
|                   end
 | |
|                 else
 | |
|                   begin
 | |
|                     href:=left.location.reference;
 | |
|                     cg.a_load_const_ref(exprasmlist,OS_8,1,href);
 | |
|                     inc(href.offset,1);
 | |
|                     case right.location.loc of
 | |
|                       LOC_REGISTER,
 | |
|                       LOC_CREGISTER :
 | |
|                         begin
 | |
|                           r:=cg.makeregsize(right.location.register,OS_8);
 | |
|                           cg.a_load_reg_ref(exprasmlist,OS_8,OS_8,r,href);
 | |
|                         end;
 | |
|                       LOC_REFERENCE,
 | |
|                       LOC_CREFERENCE :
 | |
|                         cg.a_load_ref_ref(exprasmlist,OS_8,OS_8,right.location.reference,href);
 | |
|                       else
 | |
|                         internalerror(200205111);
 | |
|                     end;
 | |
|                   end;
 | |
|               end
 | |
|             else
 | |
|               internalerror(200204249);
 | |
|           end
 | |
|         else
 | |
|           begin
 | |
|             case right.location.loc of
 | |
|               LOC_CONSTANT :
 | |
|                 begin
 | |
|                   if right.location.size in [OS_64,OS_S64] then
 | |
|                    cg64.a_load64_const_loc(exprasmlist,
 | |
|                        right.location.valueqword,left.location)
 | |
|                   else
 | |
|                    cg.a_load_const_loc(exprasmlist,right.location.value,left.location);
 | |
|                 end;
 | |
|               LOC_REFERENCE,
 | |
|               LOC_CREFERENCE :
 | |
|                 begin
 | |
|                   case left.location.loc of
 | |
|                     LOC_CREGISTER :
 | |
|                       begin
 | |
|                         cgsize:=def_cgsize(left.resulttype.def);
 | |
|                         if cgsize in [OS_64,OS_S64] then
 | |
|                           begin
 | |
|                             cg64.a_load64_ref_reg(exprasmlist,
 | |
|                                right.location.reference,left.location.register64,false);
 | |
|                             location_release(exprasmlist,right.location);
 | |
|                           end
 | |
|                         else
 | |
|                           begin
 | |
|                             location_release(exprasmlist,right.location);
 | |
|                             cg.a_load_ref_reg(exprasmlist,cgsize,cgsize,
 | |
|                                 right.location.reference,left.location.register);
 | |
|                           end;
 | |
|                       end;
 | |
|                     LOC_CFPUREGISTER :
 | |
|                       begin
 | |
|                         cg.a_loadfpu_ref_reg(exprasmlist,
 | |
|                             def_cgsize(right.resulttype.def),
 | |
|                             right.location.reference,
 | |
|                             left.location.register);
 | |
|                       end;
 | |
|                     LOC_REFERENCE,
 | |
|                     LOC_CREFERENCE :
 | |
|                       begin
 | |
|                         cg.g_concatcopy(exprasmlist,right.location.reference,
 | |
|                                         left.location.reference,left.resulttype.def.size,true,false);
 | |
|                         { right.location is already released by concatcopy }
 | |
|                         releaseright:=false;
 | |
|                       end;
 | |
|                     else
 | |
|                       internalerror(200203284);
 | |
|                   end;
 | |
|                 end;
 | |
| {$ifdef SUPPORT_MMX}
 | |
|               LOC_CMMXREGISTER,
 | |
|               LOC_MMXREGISTER:
 | |
|                 begin
 | |
|                   if left.location.loc=LOC_CMMXREGISTER then
 | |
|                     cg.a_loadmm_reg_reg(exprasmlist,right.location.register,left.location.register)
 | |
|                   else
 | |
|                     cg.a_loadmm_reg_ref(exprasmlist,right.location.register,left.location.reference);
 | |
|                 end;
 | |
| {$endif SUPPORT_MMX}
 | |
|               LOC_REGISTER,
 | |
|               LOC_CREGISTER :
 | |
|                 begin
 | |
|                   cgsize:=def_cgsize(left.resulttype.def);
 | |
|                   if cgsize in [OS_64,OS_S64] then
 | |
|                    cg64.a_load64_reg_loc(exprasmlist,
 | |
|                      right.location.register64,left.location)
 | |
|                   else
 | |
|                    cg.a_load_reg_loc(exprasmlist,right.location.size,right.location.register,left.location);
 | |
|                 end;
 | |
|               LOC_FPUREGISTER,LOC_CFPUREGISTER :
 | |
|                 begin
 | |
|                   if (left.resulttype.def.deftype=floatdef) then
 | |
|                    fputyp:=tfloatdef(left.resulttype.def).typ
 | |
|                   else
 | |
|                    if (right.resulttype.def.deftype=floatdef) then
 | |
|                     fputyp:=tfloatdef(right.resulttype.def).typ
 | |
|                   else
 | |
|                    if (right.nodetype=typeconvn) and
 | |
|                       (ttypeconvnode(right).left.resulttype.def.deftype=floatdef) then
 | |
|                     fputyp:=tfloatdef(ttypeconvnode(right).left.resulttype.def).typ
 | |
|                   else
 | |
|                     fputyp:=s32real;
 | |
|                   cg.a_loadfpu_reg_loc(exprasmlist,
 | |
|                       tfloat2tcgsize[fputyp],
 | |
|                       right.location.register,left.location);
 | |
|                 end;
 | |
|               LOC_JUMP :
 | |
|                 begin
 | |
|                   cgsize:=def_cgsize(left.resulttype.def);
 | |
|                   objectlibrary.getlabel(hlabel);
 | |
|                   { generate the leftnode for the true case, and
 | |
|                     release the location }
 | |
|                   cg.a_label(exprasmlist,truelabel);
 | |
|                   secondpass(left);
 | |
|                   if codegenerror then
 | |
|                     exit;
 | |
|                   cg.a_load_const_loc(exprasmlist,1,left.location);
 | |
|                   location_release(exprasmlist,left.location);
 | |
|                   cg.a_jmp_always(exprasmlist,hlabel);
 | |
|                   { generate the leftnode for the false case }
 | |
|                   cg.a_label(exprasmlist,falselabel);
 | |
|                   old_allow_multi_pass2:=allow_multi_pass2;
 | |
|                   allow_multi_pass2:=true;
 | |
|                   secondpass(left);
 | |
|                   allow_multi_pass2:=old_allow_multi_pass2;
 | |
|                   if codegenerror then
 | |
|                     exit;
 | |
|                   cg.a_load_const_loc(exprasmlist,0,left.location);
 | |
|                   cg.a_label(exprasmlist,hlabel);
 | |
|                 end;
 | |
| {$ifdef cpuflags}
 | |
|               LOC_FLAGS :
 | |
|                 begin
 | |
|                   {This can be a wordbool or longbool too, no?}
 | |
|                   if left.location.loc=LOC_CREGISTER then
 | |
|                     cg.g_flags2reg(exprasmlist,def_cgsize(left.resulttype.def),right.location.resflags,left.location.register)
 | |
|                   else
 | |
|                     begin
 | |
|                       if not(left.location.loc = LOC_REFERENCE) then
 | |
|                        internalerror(200203273);
 | |
|                       cg.g_flags2ref(exprasmlist,def_cgsize(left.resulttype.def),right.location.resflags,left.location.reference);
 | |
|                     end;
 | |
|                 end;
 | |
| {$endif cpuflags}
 | |
|             end;
 | |
| 
 | |
|          end;
 | |
| 
 | |
|         if releaseright then
 | |
|           location_release(exprasmlist,right.location);
 | |
|         location_release(exprasmlist,left.location);
 | |
| 
 | |
|         truelabel:=otlabel;
 | |
|         falselabel:=oflabel;
 | |
|       end;
 | |
| 
 | |
| 
 | |
| {*****************************************************************************
 | |
|                            SecondArrayConstruct
 | |
| *****************************************************************************}
 | |
| 
 | |
|       const
 | |
|         vtInteger    = 0;
 | |
|         vtBoolean    = 1;
 | |
|         vtChar       = 2;
 | |
|         vtExtended   = 3;
 | |
|         vtString     = 4;
 | |
|         vtPointer    = 5;
 | |
|         vtPChar      = 6;
 | |
|         vtObject     = 7;
 | |
|         vtClass      = 8;
 | |
|         vtWideChar   = 9;
 | |
|         vtPWideChar  = 10;
 | |
|         vtAnsiString = 11;
 | |
|         vtCurrency   = 12;
 | |
|         vtVariant    = 13;
 | |
|         vtInterface  = 14;
 | |
|         vtWideString = 15;
 | |
|         vtInt64      = 16;
 | |
|         vtQWord      = 17;
 | |
| 
 | |
|     procedure tcgarrayconstructornode.pass_2;
 | |
|       var
 | |
|         hp    : tarrayconstructornode;
 | |
|         href  : treference;
 | |
|         lt    : tdef;
 | |
|         vaddr : boolean;
 | |
|         vtype : longint;
 | |
|         freetemp,
 | |
|         dovariant : boolean;
 | |
|         elesize : longint;
 | |
|         tmpreg  : tregister;
 | |
|         paraloc : tparalocation;
 | |
|       begin
 | |
|         dovariant:=(nf_forcevaria in flags) or tarraydef(resulttype.def).isvariant;
 | |
|         if dovariant then
 | |
|          elesize:=8
 | |
|         else
 | |
|          elesize:=tarraydef(resulttype.def).elesize;
 | |
|         location_reset(location,LOC_CREFERENCE,OS_NO);
 | |
|         fillchar(paraloc,sizeof(paraloc),0);
 | |
|         { Allocate always a temp, also if no elements are required, to
 | |
|           be sure that location is valid (PFV) }
 | |
|          if tarraydef(resulttype.def).highrange=-1 then
 | |
|            tg.GetTemp(exprasmlist,elesize,tt_normal,location.reference)
 | |
|          else
 | |
|            tg.GetTemp(exprasmlist,(tarraydef(resulttype.def).highrange+1)*elesize,tt_normal,location.reference);
 | |
|          href:=location.reference;
 | |
|         { Process nodes in array constructor }
 | |
|         hp:=self;
 | |
|         while assigned(hp) do
 | |
|          begin
 | |
|            if assigned(hp.left) then
 | |
|             begin
 | |
|               freetemp:=true;
 | |
|               secondpass(hp.left);
 | |
|               if codegenerror then
 | |
|                exit;
 | |
|               { Move flags and jump in register }
 | |
|               if hp.left.location.loc in [LOC_FLAGS,LOC_JUMP] then
 | |
|                 location_force_reg(exprasmlist,hp.left.location,def_cgsize(hp.left.resulttype.def),false);
 | |
|               if dovariant then
 | |
|                begin
 | |
|                  { find the correct vtype value }
 | |
|                  vtype:=$ff;
 | |
|                  vaddr:=false;
 | |
|                  lt:=hp.left.resulttype.def;
 | |
|                  case lt.deftype of
 | |
|                    enumdef,
 | |
|                    orddef :
 | |
|                      begin
 | |
|                        if is_64bit(lt) then
 | |
|                          begin
 | |
|                             case torddef(lt).typ of
 | |
|                                s64bit:
 | |
|                                  vtype:=vtInt64;
 | |
|                                u64bit:
 | |
|                                  vtype:=vtQWord;
 | |
|                             end;
 | |
|                             freetemp:=false;
 | |
|                             vaddr:=true;
 | |
|                          end
 | |
|                        else if (lt.deftype=enumdef) or
 | |
|                          is_integer(lt) then
 | |
|                          vtype:=vtInteger
 | |
|                        else
 | |
|                          if is_boolean(lt) then
 | |
|                            vtype:=vtBoolean
 | |
|                          else
 | |
|                            if (lt.deftype=orddef) then
 | |
|                              begin
 | |
|                                case torddef(lt).typ of
 | |
|                                  uchar:
 | |
|                                    vtype:=vtChar;
 | |
|                                  uwidechar:
 | |
|                                    vtype:=vtWideChar;
 | |
|                                end;
 | |
|                              end;
 | |
|                      end;
 | |
|                    floatdef :
 | |
|                      begin
 | |
|                        vtype:=vtExtended;
 | |
|                        freetemp:=false;
 | |
|                        vaddr:=true;
 | |
|                      end;
 | |
|                    procvardef,
 | |
|                    pointerdef :
 | |
|                      begin
 | |
|                        if is_pchar(lt) then
 | |
|                          vtype:=vtPChar
 | |
|                        else
 | |
|                          vtype:=vtPointer;
 | |
|                      end;
 | |
|                    variantdef :
 | |
|                      begin
 | |
|                         vtype:=vtVariant;
 | |
|                         vaddr:=true;
 | |
|                         freetemp:=false;
 | |
|                      end;
 | |
|                    classrefdef :
 | |
|                      vtype:=vtClass;
 | |
|                    objectdef :
 | |
|                      vtype:=vtObject;
 | |
|                    stringdef :
 | |
|                      begin
 | |
|                        if is_shortstring(lt) then
 | |
|                         begin
 | |
|                           vtype:=vtString;
 | |
|                           vaddr:=true;
 | |
|                           freetemp:=false;
 | |
|                         end
 | |
|                        else
 | |
|                         if is_ansistring(lt) then
 | |
|                          begin
 | |
|                            vtype:=vtAnsiString;
 | |
|                            freetemp:=false;
 | |
|                          end
 | |
|                        else
 | |
|                         if is_widestring(lt) then
 | |
|                          begin
 | |
|                            vtype:=vtWideString;
 | |
|                            freetemp:=false;
 | |
|                          end;
 | |
|                      end;
 | |
|                  end;
 | |
|                  if vtype=$ff then
 | |
|                    internalerror(14357);
 | |
|                  { write changing field update href to the next element }
 | |
|                  inc(href.offset,4);
 | |
|                  if vaddr then
 | |
|                   begin
 | |
|                     location_force_mem(exprasmlist,hp.left.location);
 | |
|                     location_release(exprasmlist,hp.left.location);
 | |
|                     tmpreg:=cg.getaddressregister(exprasmlist);
 | |
|                     cg.a_loadaddr_ref_reg(exprasmlist,hp.left.location.reference,tmpreg);
 | |
|                     cg.ungetregister(exprasmlist,tmpreg);
 | |
|                     cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,tmpreg,href);
 | |
|                     if freetemp then
 | |
|                       location_freetemp(exprasmlist,hp.left.location);
 | |
|                   end
 | |
|                  else
 | |
|                   begin
 | |
|                     location_release(exprasmlist,hp.left.location);
 | |
|                     cg.a_load_loc_ref(exprasmlist,OS_ADDR,hp.left.location,href);
 | |
|                   end;
 | |
|                  { update href to the vtype field and write it }
 | |
|                  dec(href.offset,4);
 | |
|                  cg.a_load_const_ref(exprasmlist, OS_INT,vtype,href);
 | |
|                  { goto next array element }
 | |
|                  inc(href.offset,8);
 | |
|                end
 | |
|               else
 | |
|               { normal array constructor of the same type }
 | |
|                begin
 | |
|                  if is_ansistring(left.resulttype.def) or
 | |
|                     is_widestring(left.resulttype.def) or
 | |
|                     (left.resulttype.def.deftype=variantdef) then
 | |
|                    freetemp:=false;
 | |
|                  case hp.left.location.loc of
 | |
|                    LOC_FPUREGISTER,
 | |
|                    LOC_CFPUREGISTER :
 | |
|                      begin
 | |
|                        location_release(exprasmlist,hp.left.location);
 | |
|                        cg.a_loadfpu_reg_ref(exprasmlist,hp.left.location.size,hp.left.location.register,href);
 | |
|                      end;
 | |
|                    LOC_REFERENCE,
 | |
|                    LOC_CREFERENCE :
 | |
|                      begin
 | |
|                        location_release(exprasmlist,hp.left.location);
 | |
|                        cg.g_concatcopy(exprasmlist,hp.left.location.reference,href,elesize,freetemp,false);
 | |
|                      end;
 | |
|                    else
 | |
|                      begin
 | |
|                        if hp.left.location.size in [OS_64,OS_S64] then
 | |
|                          begin
 | |
|                            cg64.a_load64_loc_ref(exprasmlist,hp.left.location,href);
 | |
|                            location_release(exprasmlist,hp.left.location);
 | |
|                          end
 | |
|                        else
 | |
|                          begin
 | |
|                            location_release(exprasmlist,hp.left.location);
 | |
|                            cg.a_load_loc_ref(exprasmlist,hp.left.location.size,hp.left.location,href);
 | |
|                          end;
 | |
|                      end;
 | |
|                  end;
 | |
|                  inc(href.offset,elesize);
 | |
|                end;
 | |
|             end;
 | |
|            { load next entry }
 | |
|            hp:=tarrayconstructornode(hp.right);
 | |
|          end;
 | |
|       end;
 | |
| 
 | |
| begin
 | |
|    cloadnode:=tcgloadnode;
 | |
|    cassignmentnode:=tcgassignmentnode;
 | |
|    carrayconstructornode:=tcgarrayconstructornode;
 | |
| end.
 | |
| {
 | |
|   $Log$
 | |
|   Revision 1.102  2003-12-06 01:15:22  florian
 | |
|     * reverted Peter's alloctemp patch; hopefully properly
 | |
| 
 | |
|   Revision 1.101  2003/12/03 23:13:20  peter
 | |
|     * delayed paraloc allocation, a_param_*() gets extra parameter
 | |
|       if it needs to allocate temp or real paralocation
 | |
|     * optimized/simplified int-real loading
 | |
| 
 | |
|   Revision 1.100  2003/12/01 18:44:15  peter
 | |
|     * fixed some crashes
 | |
|     * fixed varargs and register calling probs
 | |
| 
 | |
|   Revision 1.99  2003/11/23 17:39:33  peter
 | |
|     * removed obsolete nf_cargs flag
 | |
| 
 | |
|   Revision 1.98  2003/10/29 19:48:50  peter
 | |
|     * renamed mangeldname_prefix to make_mangledname and made it more
 | |
|       generic
 | |
|     * make_mangledname is now also used for internal threadvar/resstring
 | |
|       lists
 | |
|     * Add P$ in front of program modulename to prevent duplicated symbols
 | |
|       at assembler level, because the main program can have the same name
 | |
|       as a unit, see webtbs/tw1251b
 | |
| 
 | |
|   Revision 1.97  2003/10/28 15:36:01  peter
 | |
|     * absolute to object field supported, fixes tb0458
 | |
| 
 | |
|   Revision 1.96  2003/10/17 14:38:32  peter
 | |
|     * 64k registers supported
 | |
|     * fixed some memory leaks
 | |
| 
 | |
|   Revision 1.95  2003/10/14 00:30:48  florian
 | |
|     + some code for PIC support added
 | |
| 
 | |
|   Revision 1.94  2003/10/11 16:06:42  florian
 | |
|     * fixed some MMX<->SSE
 | |
|     * started to fix ppc, needs an overhaul
 | |
|     + stabs info improve for spilling, not sure if it works correctly/completly
 | |
|     - MMX_SUPPORT removed from Makefile.fpc
 | |
| 
 | |
|   Revision 1.93  2003/10/10 17:48:13  peter
 | |
|     * old trgobj moved to x86/rgcpu and renamed to trgx86fpu
 | |
|     * tregisteralloctor renamed to trgobj
 | |
|     * removed rgobj from a lot of units
 | |
|     * moved location_* and reference_* to cgobj
 | |
|     * first things for mmx register allocation
 | |
| 
 | |
|   Revision 1.92  2003/10/09 21:31:37  daniel
 | |
|     * Register allocator splitted, ans abstract now
 | |
| 
 | |
|   Revision 1.91  2003/10/07 15:17:07  peter
 | |
|     * inline supported again, LOC_REFERENCEs are used to pass the
 | |
|       parameters
 | |
|     * inlineparasymtable,inlinelocalsymtable removed
 | |
|     * exitlabel inserting fixed
 | |
| 
 | |
|   Revision 1.90  2003/10/05 21:21:52  peter
 | |
|     * c style array of const generates callparanodes
 | |
|     * varargs paraloc fixes
 | |
| 
 | |
|   Revision 1.89  2003/10/01 20:34:48  peter
 | |
|     * procinfo unit contains tprocinfo
 | |
|     * cginfo renamed to cgbase
 | |
|     * moved cgmessage to verbose
 | |
|     * fixed ppc and sparc compiles
 | |
| 
 | |
|   Revision 1.88  2003/09/29 20:58:56  peter
 | |
|     * optimized releasing of registers
 | |
| 
 | |
|   Revision 1.87  2003/09/28 21:46:18  peter
 | |
|     * fix allocation of threadvar parameter
 | |
| 
 | |
|   Revision 1.86  2003/09/28 17:55:03  peter
 | |
|     * parent framepointer changed to hidden parameter
 | |
|     * tloadparentfpnode added
 | |
| 
 | |
|   Revision 1.85  2003/09/28 13:39:38  peter
 | |
|     * optimized releasing of registers
 | |
| 
 | |
|   Revision 1.84  2003/09/25 21:27:31  peter
 | |
|     * rearranged threadvar code so the result register is the same
 | |
|       for the relocated and address loaded variables
 | |
| 
 | |
|   Revision 1.83  2003/09/23 17:56:05  peter
 | |
|     * locals and paras are allocated in the code generation
 | |
|     * tvarsym.localloc contains the location of para/local when
 | |
|       generating code for the current procedure
 | |
| 
 | |
|   Revision 1.82  2003/09/16 16:17:01  peter
 | |
|     * varspez in calls to push_addr_param
 | |
| 
 | |
|   Revision 1.81  2003/09/14 12:57:10  peter
 | |
|     * save destroyed registers when calling threadvar helper
 | |
| 
 | |
|   Revision 1.80  2003/09/10 08:31:47  marco
 | |
|    * Patch from Peter for paraloc
 | |
| 
 | |
|   Revision 1.79  2003/09/03 15:55:00  peter
 | |
|     * NEWRA branch merged
 | |
| 
 | |
|   Revision 1.78  2003/09/03 11:18:37  florian
 | |
|     * fixed arm concatcopy
 | |
|     + arm support in the common compiler sources added
 | |
|     * moved some generic cg code around
 | |
|     + tfputype added
 | |
|     * ...
 | |
| 
 | |
|   Revision 1.77.2.2  2003/08/31 15:46:26  peter
 | |
|     * more updates for tregister
 | |
| 
 | |
|   Revision 1.77.2.1  2003/08/29 17:28:59  peter
 | |
|     * next batch of updates
 | |
| 
 | |
|   Revision 1.77  2003/08/20 20:13:08  daniel
 | |
|     * Fixed the fixed trouble
 | |
| 
 | |
|   Revision 1.76  2003/08/20 20:11:24  daniel
 | |
|     * Fixed some R_NO trouble
 | |
| 
 | |
|   Revision 1.75  2003/07/20 16:26:43  jonas
 | |
|     * fix for threadvars with -dnewra
 | |
| 
 | |
|   Revision 1.74  2003/07/06 17:58:22  peter
 | |
|     * framepointer fixes for sparc
 | |
|     * parent framepointer code more generic
 | |
| 
 | |
|   Revision 1.73  2003/07/06 15:25:54  jonas
 | |
|     * newra fix for threadvars
 | |
| 
 | |
|   Revision 1.72  2003/06/15 15:13:12  jonas
 | |
|     * fixed register allocation for threadvar loads with newra
 | |
| 
 | |
|   Revision 1.71  2003/06/13 21:19:30  peter
 | |
|     * current_procdef removed, use current_procinfo.procdef instead
 | |
| 
 | |
|   Revision 1.70  2003/06/12 16:43:07  peter
 | |
|     * newra compiles for sparc
 | |
| 
 | |
|   Revision 1.69  2003/06/09 16:41:52  jonas
 | |
|     * fixed regvar optimization for call_by_reference parameters (no need
 | |
|       to load address in another register)
 | |
| 
 | |
|   Revision 1.68  2003/06/08 18:27:15  jonas
 | |
|     + ability to change the location of a ttempref node with changelocation()
 | |
|       method. Useful to use instead of copying the contents from one temp to
 | |
|       another
 | |
|     + some shortstring optimizations in tassignmentnode that avoid some
 | |
|       copying (required some shortstring optimizations to be moved from
 | |
|       resulttype to firstpass, because they work on callnodes and string
 | |
|       addnodes are only changed to callnodes in the firstpass)
 | |
|     * allow setting/changing the funcretnode of callnodes after the
 | |
|       resulttypepass has been done, funcretnode is now a property
 | |
|     (all of the above should have a quite big effect on callparatemp)
 | |
| 
 | |
|   Revision 1.67  2003/06/07 18:57:04  jonas
 | |
|     + added freeintparaloc
 | |
|     * ppc get/freeintparaloc now check whether the parameter regs are
 | |
|       properly allocated/deallocated (and get an extra list para)
 | |
|     * ppc a_call_* now internalerrors if pi_do_call is not yet set
 | |
|     * fixed lot of missing pi_do_call's
 | |
| 
 | |
|   Revision 1.66  2003/06/03 21:11:09  peter
 | |
|     * cg.a_load_* get a from and to size specifier
 | |
|     * makeregsize only accepts newregister
 | |
|     * i386 uses generic tcgnotnode,tcgunaryminus
 | |
| 
 | |
|   Revision 1.65  2003/06/03 13:01:59  daniel
 | |
|     * Register allocator finished
 | |
| 
 | |
|   Revision 1.64  2003/05/30 23:57:08  peter
 | |
|     * more sparc cleanup
 | |
|     * accumulator removed, splitted in function_return_reg (called) and
 | |
|       function_result_reg (caller)
 | |
| 
 | |
|   Revision 1.63  2003/05/30 23:54:08  jonas
 | |
|     * forgot to commit, a_load_loc_reg change
 | |
| 
 | |
|   Revision 1.62  2003/05/26 19:38:28  peter
 | |
|     * generic fpc_shorstr_concat
 | |
|     + fpc_shortstr_append_shortstr optimization
 | |
| 
 | |
|   Revision 1.61  2003/05/24 11:47:27  jonas
 | |
|     * fixed framepointer storage: it's now always stored at r1+12, which is
 | |
|       a place in the link area reserved for compiler use.
 | |
| 
 | |
|   Revision 1.60  2003/05/23 14:27:35  peter
 | |
|     * remove some unit dependencies
 | |
|     * current_procinfo changes to store more info
 | |
| 
 | |
|   Revision 1.59  2003/05/15 18:58:53  peter
 | |
|     * removed selfpointer_offset, vmtpointer_offset
 | |
|     * tvarsym.adjusted_address
 | |
|     * address in localsymtable is now in the real direction
 | |
|     * removed some obsolete globals
 | |
| 
 | |
|   Revision 1.58  2003/05/12 17:22:00  jonas
 | |
|     * fixed (last?) remaining -tvarsym(X).address to
 | |
|       tg.direction*tvarsym(X).address...
 | |
| 
 | |
|   Revision 1.57  2003/05/11 21:37:03  peter
 | |
|     * moved implicit exception frame from ncgutil to psub
 | |
|     * constructor/destructor helpers moved from cobj/ncgutil to psub
 | |
| 
 | |
|   Revision 1.56  2003/05/11 14:45:12  peter
 | |
|     * tloadnode does not support objectsymtable,withsymtable anymore
 | |
|     * withnode cleanup
 | |
|     * direct with rewritten to use temprefnode
 | |
| 
 | |
|   Revision 1.55  2003/04/29 07:29:14  michael
 | |
|   + Patch from peter to fix wrong pushing of ansistring function results in open array
 | |
| 
 | |
|   Revision 1.54  2003/04/27 11:21:33  peter
 | |
|     * aktprocdef renamed to current_procinfo.procdef
 | |
|     * procinfo renamed to current_procinfo
 | |
|     * procinfo will now be stored in current_module so it can be
 | |
|       cleaned up properly
 | |
|     * gen_main_procsym changed to create_main_proc and release_main_proc
 | |
|       to also generate a tprocinfo structure
 | |
|     * fixed unit implicit initfinal
 | |
| 
 | |
|   Revision 1.53  2003/04/27 07:29:50  peter
 | |
|     * current_procinfo.procdef cleanup, current_procdef is now always nil when parsing
 | |
|       a new procdef declaration
 | |
|     * aktprocsym removed
 | |
|     * lexlevel removed, use symtable.symtablelevel instead
 | |
|     * implicit init/final code uses the normal genentry/genexit
 | |
|     * funcret state checking updated for new funcret handling
 | |
| 
 | |
|   Revision 1.52  2003/04/25 20:59:33  peter
 | |
|     * removed funcretn,funcretsym, function result is now in varsym
 | |
|       and aliases for result and function name are added using absolutesym
 | |
|     * vs_hidden parameter for funcret passed in parameter
 | |
|     * vs_hidden fixes
 | |
|     * writenode changed to printnode and released from extdebug
 | |
|     * -vp option added to generate a tree.log with the nodetree
 | |
|     * nicer printnode for statements, callnode
 | |
| 
 | |
|   Revision 1.51  2003/04/23 20:16:04  peter
 | |
|     + added currency support based on int64
 | |
|     + is_64bit for use in cg units instead of is_64bitint
 | |
|     * removed cgmessage from n386add, replace with internalerrors
 | |
| 
 | |
|   Revision 1.50  2003/04/23 10:12:14  peter
 | |
|     * allow multi pass2 changed to global boolean instead of node flag
 | |
| 
 | |
|   Revision 1.49  2003/04/22 23:50:22  peter
 | |
|     * firstpass uses expectloc
 | |
|     * checks if there are differences between the expectloc and
 | |
|       location.loc from secondpass in EXTDEBUG
 | |
| 
 | |
|   Revision 1.48  2003/04/22 10:09:35  daniel
 | |
|     + Implemented the actual register allocator
 | |
|     + Scratch registers unavailable when new register allocator used
 | |
|     + maybe_save/maybe_restore unavailable when new register allocator used
 | |
| 
 | |
|   Revision 1.47  2003/04/06 21:11:23  olle
 | |
|     * changed newasmsymbol to newasmsymboldata for data symbols
 | |
| 
 | |
|   Revision 1.46  2003/03/28 19:16:56  peter
 | |
|     * generic constructor working for i386
 | |
|     * remove fixed self register
 | |
|     * esi added as address register for i386
 | |
| 
 | |
|   Revision 1.45  2003/02/19 22:00:14  daniel
 | |
|     * Code generator converted to new register notation
 | |
|     - Horribily outdated todo.txt removed
 | |
| 
 | |
|   Revision 1.44  2003/01/08 18:43:56  daniel
 | |
|    * Tregister changed into a record
 | |
| 
 | |
|   Revision 1.43  2003/01/05 22:44:14  peter
 | |
|     * remove a lot of code to support typen in loadn-procsym
 | |
| 
 | |
|   Revision 1.42  2002/12/20 18:13:46  peter
 | |
|     * fixes for fpu values in arrayconstructor
 | |
| 
 | |
|   Revision 1.41  2002/11/27 20:04:39  peter
 | |
|     * cdecl array of const fixes
 | |
| 
 | |
|   Revision 1.40  2002/11/25 17:43:18  peter
 | |
|     * splitted defbase in defutil,symutil,defcmp
 | |
|     * merged isconvertable and is_equal into compare_defs(_ext)
 | |
|     * made operator search faster by walking the list only once
 | |
| 
 | |
|   Revision 1.39  2002/11/22 16:22:45  jonas
 | |
|     * fixed error in my previous commit (the size of the location of the
 | |
|       funcretnode must be based on the current resulttype of the node and not
 | |
|       the resulttype defined by the function; these can be different in case
 | |
|       of "absolute" declarations)
 | |
| 
 | |
|   Revision 1.38  2002/11/18 17:31:54  peter
 | |
|     * pass proccalloption to ret_in_xxx and push_xxx functions
 | |
| 
 | |
|   Revision 1.37  2002/11/15 21:16:39  jonas
 | |
|     * proper fix for tw2110, also fixes tb0416 (funcretnode of parent
 | |
|       function was handled wrong inside nested functions/procedures)
 | |
| 
 | |
|   Revision 1.36  2002/11/15 01:58:51  peter
 | |
|     * merged changes from 1.0.7 up to 04-11
 | |
|       - -V option for generating bug report tracing
 | |
|       - more tracing for option parsing
 | |
|       - errors for cdecl and high()
 | |
|       - win32 import stabs
 | |
|       - win32 records<=8 are returned in eax:edx (turned off by default)
 | |
|       - heaptrc update
 | |
|       - more info for temp management in .s file with EXTDEBUG
 | |
| 
 | |
|   Revision 1.35  2002/10/14 19:44:13  peter
 | |
|     * (hacked) new threadvar relocate code
 | |
| 
 | |
|   Revision 1.34  2002/10/13 11:22:06  florian
 | |
|     * fixed threadvars
 | |
| 
 | |
|   Revision 1.33  2002/10/03 21:32:02  carl
 | |
|     * bugfix for 2110 (without -Or), wrong checking was done in returntype
 | |
| 
 | |
|   Revision 1.32  2002/09/30 07:00:46  florian
 | |
|     * fixes to common code to get the alpha compiler compiled applied
 | |
| 
 | |
|   Revision 1.31  2002/09/26 15:02:05  florian
 | |
|     + support of passing variants to "array of const"
 | |
| 
 | |
|   Revision 1.30  2002/09/17 18:54:02  jonas
 | |
|     * a_load_reg_reg() now has two size parameters: source and dest. This
 | |
|       allows some optimizations on architectures that don't encode the
 | |
|       register size in the register name.
 | |
| 
 | |
|   Revision 1.29  2002/09/07 15:25:03  peter
 | |
|     * old logs removed and tabs fixed
 | |
| 
 | |
|   Revision 1.28  2002/09/01 19:26:32  peter
 | |
|     * fixed register variable loading from parasymtable, the call by
 | |
|       reference code was moved wrong
 | |
| 
 | |
|   Revision 1.27  2002/09/01 12:15:40  peter
 | |
|     * fixed loading of procvar of object when the object is initialized
 | |
|       with 0
 | |
| 
 | |
|   Revision 1.26  2002/08/25 19:25:18  peter
 | |
|     * sym.insert_in_data removed
 | |
|     * symtable.insertvardata/insertconstdata added
 | |
|     * removed insert_in_data call from symtable.insert, it needs to be
 | |
|       called separatly. This allows to deref the address calculation
 | |
|     * procedures now calculate the parast addresses after the procedure
 | |
|       directives are parsed. This fixes the cdecl parast problem
 | |
|     * push_addr_param has an extra argument that specifies if cdecl is used
 | |
|       or not
 | |
| 
 | |
|   Revision 1.25  2002/08/23 16:14:48  peter
 | |
|     * tempgen cleanup
 | |
|     * tt_noreuse temp type added that will be used in genentrycode
 | |
| 
 | |
|   Revision 1.24  2002/08/17 09:23:35  florian
 | |
|     * first part of procinfo rewrite
 | |
| 
 | |
|   Revision 1.23  2002/08/14 18:13:28  jonas
 | |
|     * adapted previous fix to Peter's asmsymbol patch
 | |
| 
 | |
|   Revision 1.22  2002/08/14 18:00:42  jonas
 | |
|     * fixed tb0403
 | |
| 
 | |
|   Revision 1.21  2002/08/13 21:40:56  florian
 | |
|     * more fixes for ppc calling conventions
 | |
| 
 | |
|   Revision 1.20  2002/08/11 14:32:26  peter
 | |
|     * renamed current_library to objectlibrary
 | |
| 
 | |
|   Revision 1.19  2002/08/11 13:24:12  peter
 | |
|     * saving of asmsymbols in ppu supported
 | |
|     * asmsymbollist global is removed and moved into a new class
 | |
|       tasmlibrarydata that will hold the info of a .a file which
 | |
|       corresponds with a single module. Added librarydata to tmodule
 | |
|       to keep the library info stored for the module. In the future the
 | |
|       objectfiles will also be stored to the tasmlibrarydata class
 | |
|     * all getlabel/newasmsymbol and friends are moved to the new class
 | |
| 
 | |
|   Revision 1.18  2002/08/06 20:55:21  florian
 | |
|     * first part of ppc calling conventions fix
 | |
| 
 | |
|   Revision 1.17  2002/07/28 09:25:37  carl
 | |
|     + correct size of parameter (64-bit portability)
 | |
| 
 | |
|   Revision 1.16  2002/07/27 19:53:51  jonas
 | |
|     + generic implementation of tcg.g_flags2ref()
 | |
|     * tcg.flags2xxx() now also needs a size parameter
 | |
| 
 | |
|   Revision 1.15  2002/07/20 11:57:54  florian
 | |
|     * types.pas renamed to defbase.pas because D6 contains a types
 | |
|       unit so this would conflicts if D6 programms are compiled
 | |
|     + Willamette/SSE2 instructions to assembler added
 | |
| 
 | |
|   Revision 1.14  2002/07/16 09:17:44  florian
 | |
|     * threadvar relocation result wasn't handled properly, it could cause
 | |
|       a crash
 | |
| 
 | |
|   Revision 1.13  2002/07/11 14:41:28  florian
 | |
|     * start of the new generic parameter handling
 | |
| 
 | |
|   Revision 1.12  2002/07/07 09:52:32  florian
 | |
|     * powerpc target fixed, very simple units can be compiled
 | |
|     * some basic stuff for better callparanode handling, far from being finished
 | |
| 
 | |
|   Revision 1.11  2002/07/01 18:46:23  peter
 | |
|     * internal linker
 | |
|     * reorganized aasm layer
 | |
| 
 | |
|   Revision 1.10  2002/07/01 16:23:53  peter
 | |
|     * cg64 patch
 | |
|     * basics for currency
 | |
|     * asnode updates for class and interface (not finished)
 | |
| 
 | |
|   Revision 1.9  2002/05/20 13:30:40  carl
 | |
|   * bugfix of hdisponen (base must be set, not index)
 | |
|   * more portability fixes
 | |
| 
 | |
| }
 | 
