mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-11-04 09:19:39 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			985 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			985 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
{
 | 
						|
    $Id$
 | 
						|
    Copyright (c) 1998-2002 by Florian Klaempfl
 | 
						|
 | 
						|
    This unit implements an abstract asmoutput class for all processor types
 | 
						|
 | 
						|
    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.
 | 
						|
 | 
						|
 ****************************************************************************
 | 
						|
}
 | 
						|
{ @abstract(This unit implements an abstract asm output class for all processor types)
 | 
						|
  This unit implements an abstract assembler output class for all processors, these
 | 
						|
  are then overriden for each assembler writer to actually write the data in these
 | 
						|
  classes to an assembler file.
 | 
						|
}
 | 
						|
 | 
						|
unit aasmbase;
 | 
						|
 | 
						|
{$i fpcdefs.inc}
 | 
						|
 | 
						|
interface
 | 
						|
 | 
						|
    uses
 | 
						|
       cutils,cclasses,
 | 
						|
       globtype,globals,systems
 | 
						|
       ;
 | 
						|
 | 
						|
    type
 | 
						|
       TAsmSection = class;
 | 
						|
       TAsmObjectData = class;
 | 
						|
 | 
						|
       TAsmsymbind=(AB_NONE,AB_EXTERNAL,AB_COMMON,AB_LOCAL,AB_GLOBAL);
 | 
						|
 | 
						|
       TAsmsymtype=(AT_NONE,AT_FUNCTION,AT_DATA,AT_SECTION);
 | 
						|
 | 
						|
       TAsmRelocationType = (RELOC_ABSOLUTE,RELOC_RELATIVE,RELOC_RVA);
 | 
						|
 | 
						|
       TAsmSectionType=(sec_none,
 | 
						|
         sec_code,sec_data,sec_rodata,sec_bss,
 | 
						|
         sec_common, { used for executable creation }
 | 
						|
         sec_custom, { custom section, no prefix }
 | 
						|
         { stabs }
 | 
						|
         sec_stab,sec_stabstr,
 | 
						|
         { win32 }
 | 
						|
         sec_idata2,sec_idata4,sec_idata5,sec_idata6,sec_idata7,sec_edata,
 | 
						|
         { C++ exception handling unwinding (uses dwarf) }
 | 
						|
         sec_eh_frame,
 | 
						|
         { dwarf }
 | 
						|
         sec_debug_frame
 | 
						|
       );
 | 
						|
 | 
						|
       TAsmSectionOption = (aso_alloconly,aso_executable);
 | 
						|
       TAsmSectionOptions = set of TAsmSectionOption;
 | 
						|
 | 
						|
       TAsmSymbol = class(TNamedIndexItem)
 | 
						|
       private
 | 
						|
         { this need to be incremented with every symbol loading into the
 | 
						|
           paasmoutput, thus in loadsym/loadref/const_symbol (PFV) }
 | 
						|
         refs       : longint;
 | 
						|
       public
 | 
						|
         defbind,
 | 
						|
         currbind   : TAsmsymbind;
 | 
						|
         typ        : TAsmsymtype;
 | 
						|
         { the next fields are filled in the binary writer }
 | 
						|
         section    : TAsmSection;
 | 
						|
         address,
 | 
						|
         size       : aint;
 | 
						|
         { Alternate symbol which can be used for 'renaming' needed for
 | 
						|
           inlining }
 | 
						|
         altsymbol  : tasmsymbol;
 | 
						|
         { pointer to objectdata that is the owner of this symbol }
 | 
						|
         owner      : tasmobjectdata;
 | 
						|
         { Is the symbol in the used list }
 | 
						|
         inusedlist : boolean;
 | 
						|
         { assembler pass label is set, used for detecting multiple labels }
 | 
						|
         pass       : byte;
 | 
						|
         ppuidx     : longint;
 | 
						|
         constructor create(const s:string;_bind:TAsmsymbind;_typ:Tasmsymtype);
 | 
						|
         procedure reset;
 | 
						|
         function  is_used:boolean;
 | 
						|
         procedure increfs;
 | 
						|
         procedure decrefs;
 | 
						|
         function getrefs: longint;
 | 
						|
         procedure setaddress(_pass:byte;sec:TAsmSection;offset,len:aint);
 | 
						|
       end;
 | 
						|
 | 
						|
       TAsmLabel = class(TAsmSymbol)
 | 
						|
         { this is set by the tai_label.Init }
 | 
						|
         is_set,
 | 
						|
         { is the label only there for getting an address (e.g. for i/o }
 | 
						|
         { checks -> true) or is it a jump target (false)               }
 | 
						|
         is_addr : boolean;
 | 
						|
         labelnr : longint;
 | 
						|
         constructor create(nr:longint);
 | 
						|
         constructor createdata(const modulename:string;nr:longint);
 | 
						|
         constructor createaddr(nr:longint);
 | 
						|
         function getname:string;override;
 | 
						|
       end;
 | 
						|
 | 
						|
       TAsmRelocation = class(TLinkedListItem)
 | 
						|
          address,
 | 
						|
          orgsize  : aint;  { original size of the symbol to relocate, required for COFF }
 | 
						|
          symbol   : TAsmSymbol;
 | 
						|
          section  : TAsmSection; { only used if symbol=nil }
 | 
						|
          typ      : TAsmRelocationType;
 | 
						|
          constructor CreateSymbol(Aaddress:aint;s:Tasmsymbol;Atyp:TAsmRelocationType);
 | 
						|
          constructor CreateSymbolSize(Aaddress:aint;s:Tasmsymbol;Aorgsize:aint;Atyp:TAsmRelocationType);
 | 
						|
          constructor CreateSection(Aaddress:aint;sec:TAsmSection;Atyp:TAsmRelocationType);
 | 
						|
       end;
 | 
						|
 | 
						|
       TAsmSection = class(TNamedIndexItem)
 | 
						|
         owner      : TAsmObjectData;
 | 
						|
         secoptions : TAsmSectionOptions;
 | 
						|
         sectype    : TAsmSectionType;
 | 
						|
         secsymidx  : longint;   { index for the section in symtab }
 | 
						|
         addralign  : longint;   { alignment of the section }
 | 
						|
         { size of the data and in the file }
 | 
						|
         dataalignbytes : longint;
 | 
						|
         data      : TDynamicArray;
 | 
						|
         datasize,
 | 
						|
         datapos   : aint;
 | 
						|
         { size and position in memory }
 | 
						|
         memsize,
 | 
						|
         mempos    : aint;
 | 
						|
         { relocation }
 | 
						|
         relocations : TLinkedList;
 | 
						|
         constructor create(const Aname:string;Atype:TAsmSectionType;Aalign:longint;Aoptions:TAsmSectionOptions);virtual;
 | 
						|
         destructor  destroy;override;
 | 
						|
         function  write(const d;l:aint):aint;
 | 
						|
         function  writestr(const s:string):aint;
 | 
						|
         procedure writealign(l:longint);
 | 
						|
         function  aligneddatasize:aint;
 | 
						|
         procedure setdatapos(var dpos:aint);
 | 
						|
         procedure alignsection;
 | 
						|
         procedure alloc(l:aint);
 | 
						|
         procedure addsymreloc(ofs:aint;p:tasmsymbol;relative:TAsmRelocationType);
 | 
						|
         procedure addsectionreloc(ofs:aint;sec:TAsmSection;relative:TAsmRelocationType);
 | 
						|
         procedure fixuprelocs;virtual;
 | 
						|
       end;
 | 
						|
       TAsmSectionClass = class of TAsmSection;
 | 
						|
 | 
						|
       TAsmObjectData = class(TLinkedListItem)
 | 
						|
       private
 | 
						|
         FName      : string{$ifndef VER1_9_4}[80]{$endif};
 | 
						|
         FCurrSec   : TAsmSection;
 | 
						|
         FSects     : TDictionary;
 | 
						|
         FCAsmSection : TAsmSectionClass;
 | 
						|
         { Symbols that will be defined in this object file }
 | 
						|
         FSymbols   : TIndexArray;
 | 
						|
         { Special info sections that are written to during object generation }
 | 
						|
         FStabsRecSize : longint;
 | 
						|
         FStabsSec,
 | 
						|
         FStabStrSec : TAsmSection;
 | 
						|
         procedure section_reset(p:tnamedindexitem;arg:pointer);
 | 
						|
         procedure section_fixuprelocs(p:tnamedindexitem;arg:pointer);
 | 
						|
       protected
 | 
						|
         property StabsRecSize:longint read FStabsRecSize write FStabsRecSize;
 | 
						|
         property StabsSec:TAsmSection read FStabsSec write FStabsSec;
 | 
						|
         property StabStrSec:TAsmSection read FStabStrSec write FStabStrSec;
 | 
						|
         property CAsmSection:TAsmSectionClass read FCAsmSection write FCAsmSection;
 | 
						|
       public
 | 
						|
         constructor create(const n:string);virtual;
 | 
						|
         destructor  destroy;override;
 | 
						|
         function  sectionname(atype:tasmsectiontype;const aname:string):string;virtual;
 | 
						|
         function  createsection(atype:tasmsectiontype;const aname:string;aalign:longint;aoptions:TAsmSectionOptions):tasmsection;virtual;
 | 
						|
         procedure setsection(asec:tasmsection);
 | 
						|
         procedure alloc(len:aint);
 | 
						|
         procedure allocalign(len:longint);
 | 
						|
         procedure allocstabs(p:pchar);
 | 
						|
         procedure allocsymbol(currpass:byte;p:tasmsymbol;len:aint);
 | 
						|
         procedure writebytes(var data;len:aint);
 | 
						|
         procedure writereloc(data,len:aint;p:tasmsymbol;relative:TAsmRelocationType);virtual;abstract;
 | 
						|
         procedure writesymbol(p:tasmsymbol);virtual;abstract;
 | 
						|
         procedure writestabs(offset:aint;p:pchar;nidx,nother,line:longint;reloc:boolean);virtual;abstract;
 | 
						|
         procedure writesymstabs(offset:aint;p:pchar;ps:tasmsymbol;nidx,nother,line:longint;reloc:boolean);virtual;abstract;
 | 
						|
         procedure beforealloc;virtual;
 | 
						|
         procedure beforewrite;virtual;
 | 
						|
         procedure afteralloc;virtual;
 | 
						|
         procedure afterwrite;virtual;
 | 
						|
         procedure resetsections;
 | 
						|
         procedure fixuprelocs;
 | 
						|
         property Name:string{$ifndef VER1_9_4}[80]{$endif} read FName;
 | 
						|
         property CurrSec:TAsmSection read FCurrSec;
 | 
						|
         property Symbols:TindexArray read FSymbols;
 | 
						|
         property Sects:TDictionary read FSects;
 | 
						|
       end;
 | 
						|
       TAsmObjectDataClass = class of TAsmObjectData;
 | 
						|
 | 
						|
       tasmsymbolidxarr = array[0..($7fffffff div sizeof(pointer))-1] of tasmsymbol;
 | 
						|
       pasmsymbolidxarr = ^tasmsymbolidxarr;
 | 
						|
 | 
						|
       TAsmLibraryData = class(TLinkedListItem)
 | 
						|
       private
 | 
						|
         nextaltnr   : longint;
 | 
						|
         nextlabelnr : longint;
 | 
						|
       public
 | 
						|
         name,
 | 
						|
         realname     : string[80];
 | 
						|
         symbolsearch : tdictionary; { contains ALL assembler symbols }
 | 
						|
         usedasmsymbollist : tsinglelist;
 | 
						|
         { ppu }
 | 
						|
         asmsymbolppuidx : longint;
 | 
						|
         asmsymbolidx : pasmsymbolidxarr; { used for translating ppu index->asmsymbol }
 | 
						|
         constructor create(const n:string);
 | 
						|
         destructor  destroy;override;
 | 
						|
         procedure Freeasmsymbolidx;
 | 
						|
         procedure DerefAsmsymbol(var s:tasmsymbol);
 | 
						|
         { asmsymbol }
 | 
						|
         function  newasmsymbol(const s : string;_bind:TAsmSymBind;_typ:TAsmsymtype) : tasmsymbol;
 | 
						|
         function  getasmsymbol(const s : string) : tasmsymbol;
 | 
						|
         function  renameasmsymbol(const sold, snew : string):tasmsymbol;
 | 
						|
         function  newasmlabel(nr:longint;is_addr,is_data:boolean) : tasmlabel;
 | 
						|
         {# create a new assembler label }
 | 
						|
         procedure getlabel(var l : tasmlabel);
 | 
						|
         { make l as a new label and flag is_addr }
 | 
						|
         procedure getaddrlabel(var l : tasmlabel);
 | 
						|
         { make l as a new label and flag is_data }
 | 
						|
         procedure getdatalabel(var l : tasmlabel);
 | 
						|
         {# return a label number }
 | 
						|
         procedure getlabelnr(var l : longint);
 | 
						|
         procedure CreateUsedAsmSymbolList;
 | 
						|
         procedure DestroyUsedAsmSymbolList;
 | 
						|
         procedure UsedAsmSymbolListInsert(p:tasmsymbol);
 | 
						|
         { generate an alternative (duplicate) symbol }
 | 
						|
         procedure GenerateAltSymbol(p:tasmsymbol);
 | 
						|
         { reset alternative symbol information }
 | 
						|
         procedure UsedAsmSymbolListResetAltSym;
 | 
						|
         procedure UsedAsmSymbolListReset;
 | 
						|
         procedure UsedAsmSymbolListCheckUndefined;
 | 
						|
       end;
 | 
						|
 | 
						|
 | 
						|
    var
 | 
						|
      objectlibrary : tasmlibrarydata;
 | 
						|
 | 
						|
 | 
						|
implementation
 | 
						|
 | 
						|
    uses
 | 
						|
      strings,
 | 
						|
      verbose;
 | 
						|
 | 
						|
    const
 | 
						|
      symbolsgrow = 100;
 | 
						|
 | 
						|
 | 
						|
{*****************************************************************************
 | 
						|
                                 TAsmSymbol
 | 
						|
*****************************************************************************}
 | 
						|
 | 
						|
    constructor tasmsymbol.create(const s:string;_bind:TAsmsymbind;_typ:Tasmsymtype);
 | 
						|
      begin;
 | 
						|
        inherited createname(s);
 | 
						|
        reset;
 | 
						|
        defbind:=_bind;
 | 
						|
        typ:=_typ;
 | 
						|
        inusedlist:=false;
 | 
						|
        pass:=255;
 | 
						|
        ppuidx:=-1;
 | 
						|
        { mainly used to remove unused labels from the codesegment }
 | 
						|
        refs:=0;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure tasmsymbol.reset;
 | 
						|
      begin
 | 
						|
        { reset section info }
 | 
						|
        section:=nil;
 | 
						|
        address:=0;
 | 
						|
        size:=0;
 | 
						|
        indexnr:=-1;
 | 
						|
        pass:=255;
 | 
						|
        currbind:=AB_EXTERNAL;
 | 
						|
        altsymbol:=nil;
 | 
						|
{        taiowner:=nil;}
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function tasmsymbol.is_used:boolean;
 | 
						|
      begin
 | 
						|
        is_used:=(refs>0);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure tasmsymbol.increfs;
 | 
						|
      begin
 | 
						|
        inc(refs);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure tasmsymbol.decrefs;
 | 
						|
      begin
 | 
						|
        dec(refs);
 | 
						|
        if refs<0 then
 | 
						|
          internalerror(200211121);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function tasmsymbol.getrefs: longint;
 | 
						|
      begin
 | 
						|
        getrefs := refs;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure tasmsymbol.setaddress(_pass:byte;sec:TAsmSection;offset,len:aint);
 | 
						|
      begin
 | 
						|
        if (_pass=pass) then
 | 
						|
         begin
 | 
						|
           Message1(asmw_e_duplicate_label,name);
 | 
						|
           exit;
 | 
						|
         end;
 | 
						|
        pass:=_pass;
 | 
						|
        section:=sec;
 | 
						|
        address:=offset;
 | 
						|
        size:=len;
 | 
						|
        { when the bind was reset to External, set it back to the default
 | 
						|
          bind it got when defined }
 | 
						|
        if (currbind=AB_EXTERNAL) and (defbind<>AB_NONE) then
 | 
						|
         currbind:=defbind;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
{*****************************************************************************
 | 
						|
                                 TAsmLabel
 | 
						|
*****************************************************************************}
 | 
						|
 | 
						|
    constructor tasmlabel.create(nr:longint);
 | 
						|
      begin;
 | 
						|
        labelnr:=nr;
 | 
						|
        inherited create(target_asm.labelprefix+tostr(labelnr),AB_LOCAL,AT_FUNCTION);
 | 
						|
        is_set:=false;
 | 
						|
        is_addr := false;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    constructor tasmlabel.createdata(const modulename:string;nr:longint);
 | 
						|
      begin;
 | 
						|
        labelnr:=nr;
 | 
						|
        inherited create('_$'+modulename+'$_L'+tostr(labelnr),AB_GLOBAL,AT_DATA);
 | 
						|
        is_set:=false;
 | 
						|
        is_addr := false;
 | 
						|
        { write it always }
 | 
						|
        increfs;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    constructor tasmlabel.createaddr(nr:longint);
 | 
						|
      begin;
 | 
						|
        self.create(nr);
 | 
						|
        is_addr := true;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function tasmlabel.getname:string;
 | 
						|
      begin
 | 
						|
        getname:=inherited getname;
 | 
						|
        increfs;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
{****************************************************************************
 | 
						|
                              TAsmRelocation
 | 
						|
****************************************************************************}
 | 
						|
 | 
						|
    constructor TAsmRelocation.CreateSymbol(Aaddress:aint;s:Tasmsymbol;Atyp:TAsmRelocationType);
 | 
						|
      begin
 | 
						|
        Address:=Aaddress;
 | 
						|
        Symbol:=s;
 | 
						|
        OrgSize:=0;
 | 
						|
        Section:=nil;
 | 
						|
        Typ:=Atyp;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    constructor TAsmRelocation.CreateSymbolSize(Aaddress:aint;s:Tasmsymbol;Aorgsize:aint;Atyp:TAsmRelocationType);
 | 
						|
      begin
 | 
						|
        Address:=Aaddress;
 | 
						|
        Symbol:=s;
 | 
						|
        OrgSize:=Aorgsize;
 | 
						|
        Section:=nil;
 | 
						|
        Typ:=Atyp;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    constructor TAsmRelocation.CreateSection(Aaddress:aint;sec:TAsmSection;Atyp:TAsmRelocationType);
 | 
						|
      begin
 | 
						|
        Address:=Aaddress;
 | 
						|
        Symbol:=nil;
 | 
						|
        OrgSize:=0;
 | 
						|
        Section:=sec;
 | 
						|
        Typ:=Atyp;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
{****************************************************************************
 | 
						|
                              TAsmSection
 | 
						|
****************************************************************************}
 | 
						|
 | 
						|
    constructor TAsmSection.create(const Aname:string;Atype:TAsmSectionType;Aalign:longint;Aoptions:TAsmSectionOptions);
 | 
						|
      begin
 | 
						|
        inherited createname(Aname);
 | 
						|
        sectype:=Atype;
 | 
						|
        name:=Aname;
 | 
						|
        secoptions:=Aoptions;
 | 
						|
        secsymidx:=0;
 | 
						|
        addralign:=Aalign;
 | 
						|
        { data }
 | 
						|
        datasize:=0;
 | 
						|
        datapos:=0;
 | 
						|
        if (aso_alloconly in aoptions) then
 | 
						|
         data:=nil
 | 
						|
        else
 | 
						|
         Data:=TDynamicArray.Create(8192);
 | 
						|
        { memory }
 | 
						|
        mempos:=0;
 | 
						|
        memsize:=0;
 | 
						|
        { relocation }
 | 
						|
        relocations:=TLinkedList.Create;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    destructor TAsmSection.destroy;
 | 
						|
      begin
 | 
						|
        if assigned(Data) then
 | 
						|
          Data.Free;
 | 
						|
        relocations.free;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function TAsmSection.write(const d;l:aint):aint;
 | 
						|
      begin
 | 
						|
        write:=datasize;
 | 
						|
        if assigned(Data) then
 | 
						|
          Data.write(d,l);
 | 
						|
        inc(datasize,l);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function TAsmSection.writestr(const s:string):aint;
 | 
						|
      begin
 | 
						|
        writestr:=datasize;
 | 
						|
        if assigned(Data) then
 | 
						|
          Data.write(s[1],length(s));
 | 
						|
        inc(datasize,length(s));
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmSection.writealign(l:longint);
 | 
						|
      var
 | 
						|
        i : longint;
 | 
						|
        empty : array[0..63] of char;
 | 
						|
      begin
 | 
						|
        { no alignment needed for 0 or 1 }
 | 
						|
        if l<=1 then
 | 
						|
         exit;
 | 
						|
        i:=datasize mod l;
 | 
						|
        if i>0 then
 | 
						|
         begin
 | 
						|
           if assigned(data) then
 | 
						|
            begin
 | 
						|
              fillchar(empty,sizeof(empty),0);
 | 
						|
              Data.write(empty,l-i);
 | 
						|
            end;
 | 
						|
           inc(datasize,l-i);
 | 
						|
         end;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function TAsmSection.aligneddatasize:aint;
 | 
						|
      begin
 | 
						|
        aligneddatasize:=align(datasize,addralign);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmSection.setdatapos(var dpos:aint);
 | 
						|
      var
 | 
						|
        alignedpos : aint;
 | 
						|
      begin
 | 
						|
        { get aligned datapos }
 | 
						|
        alignedpos:=align(dpos,addralign);
 | 
						|
        dataalignbytes:=alignedpos-dpos;
 | 
						|
        datapos:=alignedpos;
 | 
						|
        { update datapos }
 | 
						|
        dpos:=datapos+aligneddatasize;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmSection.alignsection;
 | 
						|
      begin
 | 
						|
        writealign(addralign);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmSection.alloc(l:aint);
 | 
						|
      begin
 | 
						|
        inc(datasize,l);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmSection.addsymreloc(ofs:aint;p:tasmsymbol;relative:TAsmRelocationType);
 | 
						|
      var
 | 
						|
        r : TAsmRelocation;
 | 
						|
      begin
 | 
						|
        r:=TAsmRelocation.Create;
 | 
						|
        r.address:=ofs;
 | 
						|
        r.orgsize:=0;
 | 
						|
        r.symbol:=p;
 | 
						|
        r.section:=nil;
 | 
						|
        r.typ:=relative;
 | 
						|
        relocations.concat(r);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmSection.addsectionreloc(ofs:aint;sec:TAsmSection;relative:TAsmRelocationType);
 | 
						|
      var
 | 
						|
        r : TAsmRelocation;
 | 
						|
      begin
 | 
						|
        r:=TAsmRelocation.Create;
 | 
						|
        r.address:=ofs;
 | 
						|
        r.symbol:=nil;
 | 
						|
        r.orgsize:=0;
 | 
						|
        r.section:=sec;
 | 
						|
        r.typ:=relative;
 | 
						|
        relocations.concat(r);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmSection.fixuprelocs;
 | 
						|
      begin
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
{****************************************************************************
 | 
						|
                                TAsmObjectData
 | 
						|
****************************************************************************}
 | 
						|
 | 
						|
    constructor TAsmObjectData.create(const n:string);
 | 
						|
      begin
 | 
						|
        inherited create;
 | 
						|
        FName:=n;
 | 
						|
        { sections }
 | 
						|
        FSects:=tdictionary.create;
 | 
						|
        FStabsRecSize:=1;
 | 
						|
        FStabsSec:=nil;
 | 
						|
        FStabStrSec:=nil;
 | 
						|
        { symbols }
 | 
						|
        FSymbols:=tindexarray.create(symbolsgrow);
 | 
						|
        FSymbols.noclear:=true;
 | 
						|
        { section class type for creating of new sections }
 | 
						|
        FCAsmSection:=TAsmSection;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    destructor TAsmObjectData.destroy;
 | 
						|
      begin
 | 
						|
        FSects.free;
 | 
						|
        FSymbols.free;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function TAsmObjectData.sectionname(atype:tasmsectiontype;const aname:string):string;
 | 
						|
      const
 | 
						|
        secnames : array[tasmsectiontype] of string[12] = ('',
 | 
						|
          'code','data','rodata','bss',
 | 
						|
          'common',
 | 
						|
          'note',
 | 
						|
          'stab','stabstr',
 | 
						|
          'idata2','idata4','idata5','idata6','idata7','edata',
 | 
						|
          'eh_frame',
 | 
						|
          'debug_frame'
 | 
						|
        );
 | 
						|
      begin
 | 
						|
        if aname<>'' then
 | 
						|
          result:=secnames[atype]+'.'+aname
 | 
						|
        else
 | 
						|
          result:=secnames[atype];
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function TAsmObjectData.createsection(atype:tasmsectiontype;const aname:string;aalign:longint;aoptions:TAsmSectionOptions):TAsmSection;
 | 
						|
      var
 | 
						|
        secname : string;
 | 
						|
      begin
 | 
						|
        secname:=sectionname(atype,aname);
 | 
						|
        result:=TasmSection(FSects.search(secname));
 | 
						|
        if not assigned(result) then
 | 
						|
          begin
 | 
						|
{$warning TODO make alloconly configurable}
 | 
						|
            if atype=sec_bss then
 | 
						|
              include(aoptions,aso_alloconly);
 | 
						|
            result:=CAsmSection.create(secname,atype,aalign,aoptions);
 | 
						|
            FSects.Insert(result);
 | 
						|
            result.owner:=self;
 | 
						|
          end;
 | 
						|
        FCurrSec:=result;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmObjectData.setsection(asec:tasmsection);
 | 
						|
      begin
 | 
						|
        if asec.owner<>self then
 | 
						|
          internalerror(200403041);
 | 
						|
        FCurrSec:=asec;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmObjectData.writebytes(var data;len:aint);
 | 
						|
      begin
 | 
						|
        if not assigned(currsec) then
 | 
						|
          internalerror(200402251);
 | 
						|
        currsec.write(data,len);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmObjectData.alloc(len:aint);
 | 
						|
      begin
 | 
						|
        if not assigned(currsec) then
 | 
						|
          internalerror(200402252);
 | 
						|
        currsec.alloc(len);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmObjectData.allocalign(len:longint);
 | 
						|
      var
 | 
						|
        modulo : aint;
 | 
						|
      begin
 | 
						|
        if not assigned(currsec) then
 | 
						|
          internalerror(200402253);
 | 
						|
        modulo:=currsec.datasize mod len;
 | 
						|
        if modulo > 0 then
 | 
						|
          currsec.alloc(len-modulo);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmObjectData.allocsymbol(currpass:byte;p:tasmsymbol;len:aint);
 | 
						|
      begin
 | 
						|
        p.setaddress(currpass,currsec,currsec.datasize,len);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmObjectData.allocstabs(p:pchar);
 | 
						|
      begin
 | 
						|
        if not(assigned(FStabsSec) and assigned(FStabStrSec)) then
 | 
						|
          internalerror(200402254);
 | 
						|
        FStabsSec.alloc(FStabsRecSize);
 | 
						|
        if assigned(p) and (p[0]<>#0) then
 | 
						|
          FStabStrSec.alloc(strlen(p)+1);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmObjectData.section_reset(p:tnamedindexitem;arg:pointer);
 | 
						|
      begin
 | 
						|
        with tasmsection(p) do
 | 
						|
          begin
 | 
						|
            datasize:=0;
 | 
						|
            datapos:=0;
 | 
						|
          end;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmObjectData.section_fixuprelocs(p:tnamedindexitem;arg:pointer);
 | 
						|
      begin
 | 
						|
        tasmsection(p).fixuprelocs;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmObjectData.beforealloc;
 | 
						|
      begin
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmObjectData.beforewrite;
 | 
						|
      begin
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmObjectData.afteralloc;
 | 
						|
      begin
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmObjectData.afterwrite;
 | 
						|
      begin
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmObjectData.resetsections;
 | 
						|
      begin
 | 
						|
        FSects.foreach(@section_reset,nil);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmObjectData.fixuprelocs;
 | 
						|
      begin
 | 
						|
        FSects.foreach(@section_fixuprelocs,nil);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
{****************************************************************************
 | 
						|
                                TAsmLibraryData
 | 
						|
****************************************************************************}
 | 
						|
 | 
						|
    constructor TAsmLibraryData.create(const n:string);
 | 
						|
      begin
 | 
						|
        inherited create;
 | 
						|
        realname:=n;
 | 
						|
        name:=upper(n);
 | 
						|
        { symbols }
 | 
						|
        symbolsearch:=tdictionary.create;
 | 
						|
        symbolsearch.usehash;
 | 
						|
        { labels }
 | 
						|
        nextaltnr:=1;
 | 
						|
        nextlabelnr:=1;
 | 
						|
        { ppu }
 | 
						|
        asmsymbolppuidx:=0;
 | 
						|
        asmsymbolidx:=nil;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    destructor TAsmLibraryData.destroy;
 | 
						|
      begin
 | 
						|
        symbolsearch.free;
 | 
						|
        Freeasmsymbolidx;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmLibraryData.Freeasmsymbolidx;
 | 
						|
      begin
 | 
						|
        if assigned(asmsymbolidx) then
 | 
						|
         begin
 | 
						|
           Freemem(asmsymbolidx);
 | 
						|
           asmsymbolidx:=nil;
 | 
						|
         end;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmLibraryData.DerefAsmsymbol(var s:tasmsymbol);
 | 
						|
      begin
 | 
						|
        if assigned(s) then
 | 
						|
         begin
 | 
						|
           if not assigned(asmsymbolidx) then
 | 
						|
             internalerror(200208072);
 | 
						|
           if (ptrint(pointer(s))<1) or (ptrint(pointer(s))>asmsymbolppuidx) then
 | 
						|
             internalerror(200208073);
 | 
						|
           s:=asmsymbolidx^[ptrint(pointer(s))-1];
 | 
						|
         end;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function TAsmLibraryData.newasmsymbol(const s : string;_bind:TAsmSymBind;_typ:Tasmsymtype) : tasmsymbol;
 | 
						|
      var
 | 
						|
        hp : tasmsymbol;
 | 
						|
      begin
 | 
						|
        hp:=tasmsymbol(symbolsearch.search(s));
 | 
						|
        if assigned(hp) then
 | 
						|
         begin
 | 
						|
           {$IFDEF EXTDEBUG}
 | 
						|
           if (_typ <> AT_NONE) and
 | 
						|
              (hp.typ <> _typ) and
 | 
						|
              not(cs_compilesystem in aktmoduleswitches) then
 | 
						|
             begin
 | 
						|
               //Writeln('Error symbol '+hp.name+' type is ',Ord(_typ),', should be ',Ord(hp.typ));
 | 
						|
               InternalError(2004031501);
 | 
						|
             end;
 | 
						|
           {$ENDIF}
 | 
						|
           if (_bind<>AB_EXTERNAL) then
 | 
						|
             hp.defbind:=_bind
 | 
						|
         end
 | 
						|
        else
 | 
						|
         begin
 | 
						|
           { Not found, insert it. }
 | 
						|
           hp:=tasmsymbol.create(s,_bind,_typ);
 | 
						|
           symbolsearch.insert(hp);
 | 
						|
         end;
 | 
						|
        newasmsymbol:=hp;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function TAsmLibraryData.getasmsymbol(const s : string) : tasmsymbol;
 | 
						|
      begin
 | 
						|
        getasmsymbol:=tasmsymbol(symbolsearch.search(s));
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function TAsmLibraryData.renameasmsymbol(const sold, snew : string):tasmsymbol;
 | 
						|
      begin
 | 
						|
        renameasmsymbol:=tasmsymbol(symbolsearch.rename(sold,snew));
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmLibraryData.CreateUsedAsmSymbolList;
 | 
						|
      begin
 | 
						|
        if assigned(usedasmsymbollist) then
 | 
						|
         internalerror(78455782);
 | 
						|
        usedasmsymbollist:=TSingleList.create;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmLibraryData.DestroyUsedAsmSymbolList;
 | 
						|
      begin
 | 
						|
        usedasmsymbollist.destroy;
 | 
						|
        usedasmsymbollist:=nil;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmLibraryData.UsedAsmSymbolListInsert(p:tasmsymbol);
 | 
						|
      begin
 | 
						|
        if not p.inusedlist then
 | 
						|
         usedasmsymbollist.insert(p);
 | 
						|
        p.inusedlist:=true;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmLibraryData.GenerateAltSymbol(p:tasmsymbol);
 | 
						|
      begin
 | 
						|
        if not assigned(p.altsymbol) then
 | 
						|
         begin
 | 
						|
           p.altsymbol:=tasmsymbol.create(p.name+'_'+tostr(nextaltnr),p.defbind,p.typ);
 | 
						|
           symbolsearch.insert(p.altsymbol);
 | 
						|
           { add also the original sym to the usedasmsymbollist,
 | 
						|
             that list is used to reset the altsymbol }
 | 
						|
           if not p.inusedlist then
 | 
						|
            usedasmsymbollist.insert(p);
 | 
						|
           p.inusedlist:=true;
 | 
						|
         end;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmLibraryData.UsedAsmSymbolListReset;
 | 
						|
      var
 | 
						|
        hp : tasmsymbol;
 | 
						|
      begin
 | 
						|
        hp:=tasmsymbol(usedasmsymbollist.first);
 | 
						|
        while assigned(hp) do
 | 
						|
         begin
 | 
						|
           with hp do
 | 
						|
            begin
 | 
						|
              reset;
 | 
						|
              inusedlist:=false;
 | 
						|
            end;
 | 
						|
           hp:=tasmsymbol(hp.listnext);
 | 
						|
         end;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmLibraryData.UsedAsmSymbolListResetAltSym;
 | 
						|
      var
 | 
						|
        hp : tasmsymbol;
 | 
						|
      begin
 | 
						|
        hp:=tasmsymbol(usedasmsymbollist.first);
 | 
						|
        inc(nextaltnr);
 | 
						|
        while assigned(hp) do
 | 
						|
         begin
 | 
						|
           with hp do
 | 
						|
            begin
 | 
						|
              altsymbol:=nil;
 | 
						|
              inusedlist:=false;
 | 
						|
            end;
 | 
						|
           hp:=tasmsymbol(hp.listnext);
 | 
						|
         end;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmLibraryData.UsedAsmSymbolListCheckUndefined;
 | 
						|
      var
 | 
						|
        hp : tasmsymbol;
 | 
						|
      begin
 | 
						|
        hp:=tasmsymbol(usedasmsymbollist.first);
 | 
						|
        while assigned(hp) do
 | 
						|
         begin
 | 
						|
           with hp do
 | 
						|
            begin
 | 
						|
              if is_used and
 | 
						|
                 (section=nil) and
 | 
						|
                 not(currbind in [AB_EXTERNAL,AB_COMMON]) then
 | 
						|
               Message1(asmw_e_undefined_label,name);
 | 
						|
            end;
 | 
						|
           hp:=tasmsymbol(hp.listnext);
 | 
						|
         end;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function  TAsmLibraryData.newasmlabel(nr:longint;is_addr,is_data:boolean) : tasmlabel;
 | 
						|
      var
 | 
						|
        hp : tasmlabel;
 | 
						|
      begin
 | 
						|
        if is_addr then
 | 
						|
         hp:=tasmlabel.createaddr(nr)
 | 
						|
        else if is_data then
 | 
						|
         hp:=tasmlabel.createdata(name,nr)
 | 
						|
        else
 | 
						|
         hp:=tasmlabel.create(nr);
 | 
						|
        symbolsearch.insert(hp);
 | 
						|
        newasmlabel:=hp;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmLibraryData.getlabel(var l : tasmlabel);
 | 
						|
      begin
 | 
						|
        l:=tasmlabel.create(nextlabelnr);
 | 
						|
        inc(nextlabelnr);
 | 
						|
        symbolsearch.insert(l);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmLibraryData.getdatalabel(var l : tasmlabel);
 | 
						|
      begin
 | 
						|
        l:=tasmlabel.createdata(name,nextlabelnr);
 | 
						|
        inc(nextlabelnr);
 | 
						|
        symbolsearch.insert(l);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmLibraryData.getaddrlabel(var l : tasmlabel);
 | 
						|
      begin
 | 
						|
        l:=tasmlabel.createaddr(nextlabelnr);
 | 
						|
        inc(nextlabelnr);
 | 
						|
        symbolsearch.insert(l);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmLibraryData.getlabelnr(var l : longint);
 | 
						|
      begin
 | 
						|
         l:=nextlabelnr;
 | 
						|
         inc(nextlabelnr);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
end.
 | 
						|
{
 | 
						|
  $Log$
 | 
						|
  Revision 1.25  2004-12-03 15:57:11  peter
 | 
						|
    * fix for 1.9.4 that IE'd when rebuilding fpc
 | 
						|
 | 
						|
  Revision 1.24  2004/11/01 23:30:11  peter
 | 
						|
    * support > 32bit accesses for x86_64
 | 
						|
    * rewrote array size checking to support 64bit
 | 
						|
 | 
						|
  Revision 1.23  2004/10/31 21:45:02  peter
 | 
						|
    * generic tlocation
 | 
						|
    * move tlocation to cgutils
 | 
						|
 | 
						|
  Revision 1.22  2004/10/15 09:14:16  mazen
 | 
						|
  - remove $IFDEF DELPHI and related code
 | 
						|
  - remove $IFDEF FPCPROCVAR and related code
 | 
						|
 | 
						|
  Revision 1.21  2004/07/22 10:09:10  jonas
 | 
						|
    * fixed relabeling properly now :)
 | 
						|
 | 
						|
  Revision 1.20  2004/07/22 10:07:09  jonas
 | 
						|
    * fixed relabeling (nextaltnr was never increased)
 | 
						|
    * fixed inlining of case statements at the node level
 | 
						|
 | 
						|
  Revision 1.19  2004/06/20 08:55:28  florian
 | 
						|
    * logs truncated
 | 
						|
 | 
						|
  Revision 1.18  2004/06/16 20:07:06  florian
 | 
						|
    * dwarf branch merged
 | 
						|
 | 
						|
  Revision 1.17.2.4  2004/05/11 21:04:40  peter
 | 
						|
    * ignore EXTDEBUG check for different asmsymbol type for system unit
 | 
						|
 | 
						|
  Revision 1.17.2.3  2004/04/26 21:05:09  peter
 | 
						|
    * size of classes is now stored as aint
 | 
						|
 | 
						|
  Revision 1.17.2.2  2004/04/12 19:34:45  peter
 | 
						|
    * basic framework for dwarf CFI
 | 
						|
 | 
						|
  Revision 1.17.2.1  2004/04/08 18:33:22  peter
 | 
						|
    * rewrite of TAsmSection
 | 
						|
 | 
						|
}
 |