mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-11-04 09:59:44 +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
 | 
						|
 | 
						|
}
 |