mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-11-04 14:39:36 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			687 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			687 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
{
 | 
						|
    Copyright (c) 1998-2006 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 overridden for each assembler writer to actually write the data in these
 | 
						|
  classes to an assembler file.
 | 
						|
}
 | 
						|
 | 
						|
unit aasmdata;
 | 
						|
 | 
						|
{$i fpcdefs.inc}
 | 
						|
 | 
						|
interface
 | 
						|
 | 
						|
    uses
 | 
						|
       cutils,cclasses,
 | 
						|
       globtype,systems,
 | 
						|
       cgbase,
 | 
						|
       symtype,
 | 
						|
       aasmbase;
 | 
						|
 | 
						|
    type
 | 
						|
      { Type of AsmLists. The order is important for the layout of the
 | 
						|
        information in the .o file. The stabs for the types must be defined
 | 
						|
        before they can be referenced and therefor they need to be written
 | 
						|
        first (PFV) }
 | 
						|
      TAsmListType=(
 | 
						|
        al_start,
 | 
						|
        al_stabs,
 | 
						|
        { pure assembler routines }
 | 
						|
        al_pure_assembler,
 | 
						|
        al_procedures,
 | 
						|
        al_globals,
 | 
						|
        al_const,
 | 
						|
        al_typedconsts,
 | 
						|
        al_rotypedconsts,
 | 
						|
        al_threadvars,
 | 
						|
        al_imports,
 | 
						|
        al_exports,
 | 
						|
        al_resources,
 | 
						|
        al_rtti,
 | 
						|
        { all symbols with indirect suffix }
 | 
						|
        al_indirectglobals,
 | 
						|
        al_dwarf_frame,
 | 
						|
        al_dwarf_info,
 | 
						|
        al_dwarf_abbrev,
 | 
						|
        al_dwarf_line,
 | 
						|
        al_dwarf_aranges,
 | 
						|
        al_dwarf_ranges,
 | 
						|
        al_picdata,
 | 
						|
        al_indirectpicdata,
 | 
						|
        al_resourcestrings,
 | 
						|
        { Objective-C related sections }
 | 
						|
        al_objc_data,
 | 
						|
        { keep pool data separate, so we can generate new pool entries
 | 
						|
          while emitting other data }
 | 
						|
        al_objc_pools,
 | 
						|
        al_end
 | 
						|
      );
 | 
						|
 | 
						|
      { Type of constant 'pools'. Mostly for string types, but usable for
 | 
						|
        floating point and large set constants, too. }
 | 
						|
      
 | 
						|
      TConstPoolType = (
 | 
						|
         sp_invalid,
 | 
						|
         sp_conststr,
 | 
						|
         sp_shortstr,
 | 
						|
         sp_longstr,
 | 
						|
         sp_ansistr,
 | 
						|
         sp_widestr,
 | 
						|
         sp_unicodestr,
 | 
						|
         sp_objcclassnamerefs,
 | 
						|
         sp_varnamerefs,
 | 
						|
         sp_objcclassnames,
 | 
						|
         sp_objcvarnames,
 | 
						|
         sp_objcvartypes,
 | 
						|
         sp_objcprotocolrefs,
 | 
						|
         sp_varsets,
 | 
						|
         sp_floats,
 | 
						|
         sp_guids,
 | 
						|
         sp_paraloc
 | 
						|
      );
 | 
						|
      
 | 
						|
    const
 | 
						|
      AsmListTypeStr : array[TAsmListType] of string[24] =(
 | 
						|
        'al_begin',
 | 
						|
        'al_stabs',
 | 
						|
        'al_pure_assembler',
 | 
						|
        'al_procedures',
 | 
						|
        'al_globals',
 | 
						|
        'al_const',
 | 
						|
        'al_typedconsts',
 | 
						|
        'al_rotypedconsts',
 | 
						|
        'al_threadvars',
 | 
						|
        'al_imports',
 | 
						|
        'al_exports',
 | 
						|
        'al_resources',
 | 
						|
        'al_rtti',
 | 
						|
        'al_indirectglobals',
 | 
						|
        'al_dwarf_frame',
 | 
						|
        'al_dwarf_info',
 | 
						|
        'al_dwarf_abbrev',
 | 
						|
        'al_dwarf_line',
 | 
						|
        'al_dwarf_aranges',
 | 
						|
        'al_dwarf_ranges',
 | 
						|
        'al_picdata',
 | 
						|
        'al_indirectpicdata',
 | 
						|
        'al_resourcestrings',
 | 
						|
        'al_objc_data',
 | 
						|
        'al_objc_pools',
 | 
						|
        'al_end'
 | 
						|
      );
 | 
						|
 | 
						|
    type
 | 
						|
      TAsmList = class(tlinkedlist)
 | 
						|
         section_count : longint;
 | 
						|
         constructor create;
 | 
						|
         function  getlasttaifilepos : pfileposinfo;
 | 
						|
         { inserts another List at the begin and make this List empty }
 | 
						|
         procedure insertList(p : TLinkedList); override;
 | 
						|
         { inserts another List before the provided item and make this List empty }
 | 
						|
         procedure insertListBefore(Item:TLinkedListItem;p : TLinkedList); override;
 | 
						|
         { inserts another List after the provided item and make this List empty }
 | 
						|
         procedure insertListAfter(Item:TLinkedListItem;p : TLinkedList); override;
 | 
						|
         { concats another List at the end and make this List empty }
 | 
						|
         procedure concatList(p : TLinkedList); override;
 | 
						|
         { concats another List at the start and makes a copy
 | 
						|
           the list is ordered in reverse.
 | 
						|
         }
 | 
						|
         procedure insertListcopy(p : TLinkedList); override;
 | 
						|
         { concats another List at the end and makes a copy }
 | 
						|
         procedure concatListcopy(p : TLinkedList); override;
 | 
						|
         { removes all items from the list, the items are not freed }
 | 
						|
         procedure RemoveAll; override;
 | 
						|
      end;
 | 
						|
 | 
						|
      TAsmCFI=class
 | 
						|
      public
 | 
						|
        constructor create;virtual;
 | 
						|
        destructor destroy;override;
 | 
						|
        procedure generate_code(list:TAsmList);virtual;
 | 
						|
        procedure start_frame(list:TAsmList);virtual;
 | 
						|
        procedure end_frame(list:TAsmList);virtual;
 | 
						|
        procedure cfa_offset(list:TAsmList;reg:tregister;ofs:longint);virtual;
 | 
						|
        procedure cfa_restore(list:TAsmList;reg:tregister);virtual;
 | 
						|
        procedure cfa_def_cfa_register(list:TAsmList;reg:tregister);virtual;
 | 
						|
        procedure cfa_def_cfa_offset(list:TAsmList;ofs:longint);virtual;
 | 
						|
      end;
 | 
						|
      TAsmCFIClass=class of TAsmCFI;
 | 
						|
 | 
						|
      { TAsmData }
 | 
						|
 | 
						|
      TAsmData = class
 | 
						|
      private
 | 
						|
        { Symbols }
 | 
						|
        FAsmSymbolDict : TFPHashObjectList;
 | 
						|
        FAltSymbolList : TFPObjectList;
 | 
						|
        FNextAltNr     : longint;
 | 
						|
        FNextLabelNr   : array[TAsmLabeltype] of longint;
 | 
						|
        { Call Frame Information for stack unwinding}
 | 
						|
        FAsmCFI        : TAsmCFI;
 | 
						|
        FConstPools    : array[TConstPoolType] of THashSet;
 | 
						|
        function GetConstPools(APoolType: TConstPoolType): THashSet;
 | 
						|
      protected
 | 
						|
        function  DefineAsmSymbolByClassBase(symclass: TAsmSymbolClass; const s : TSymStr;_bind:TAsmSymBind;_typ:Tasmsymtype; def: tdef; out wasdefined: boolean) : TAsmSymbol;
 | 
						|
      public
 | 
						|
        name          : pshortstring;       { owned by tmodule }
 | 
						|
        NextVTEntryNr : longint;
 | 
						|
        { Assembler lists }
 | 
						|
        AsmLists      : array[TAsmListType] of TAsmList;
 | 
						|
        CurrAsmList   : TAsmList;
 | 
						|
        WideInits     : TLinkedList;
 | 
						|
        ResStrInits   : TLinkedList;
 | 
						|
        constructor create(n: pshortstring);
 | 
						|
        destructor  destroy;override;
 | 
						|
        { asmsymbol }
 | 
						|
        function  DefineAsmSymbolByClass(symclass: TAsmSymbolClass; const s : TSymStr;_bind:TAsmSymBind;_typ:Tasmsymtype; def: tdef) : TAsmSymbol; virtual;
 | 
						|
        function  DefineAsmSymbol(const s : TSymStr;_bind:TAsmSymBind;_typ:Tasmsymtype; def: tdef) : TAsmSymbol;
 | 
						|
        function  WeakRefAsmSymbol(const s : TSymStr;_typ:Tasmsymtype) : TAsmSymbol;
 | 
						|
        function  RefAsmSymbol(const s : TSymStr;_typ:Tasmsymtype;indirect:boolean=false) : TAsmSymbol;
 | 
						|
        function  GetAsmSymbol(const s : TSymStr) : TAsmSymbol;
 | 
						|
        { create new assembler label }
 | 
						|
        procedure getlabel(out l : TAsmLabel;alt:TAsmLabeltype);
 | 
						|
        procedure getjumplabel(out l : TAsmLabel);
 | 
						|
        procedure getglobaljumplabel(out l : TAsmLabel);
 | 
						|
        procedure getaddrlabel(out l : TAsmLabel);
 | 
						|
        { visible from outside current object }
 | 
						|
        procedure getglobaldatalabel(out l : TAsmLabel);
 | 
						|
        { visible only inside current object, but doesn't start with
 | 
						|
          target_asm.label_prefix (treated the Darwin linker as the start of a
 | 
						|
          dead-strippable data block) }
 | 
						|
        procedure getstaticdatalabel(out l : TAsmLabel);
 | 
						|
        { visible only inside the current object and does start with
 | 
						|
          target_asm.label_prefix (not treated by the Darwin linker as the start
 | 
						|
          of a dead-strippable data block, and references to such labels are
 | 
						|
          also ignored to determine whether a data block should be live) }
 | 
						|
        procedure getlocaldatalabel(out l : TAsmLabel);
 | 
						|
        { generate an alternative (duplicate) symbol }
 | 
						|
        procedure GenerateAltSymbol(p:TAsmSymbol);
 | 
						|
        procedure ResetAltSymbols;
 | 
						|
        property AsmSymbolDict:TFPHashObjectList read FAsmSymbolDict;
 | 
						|
        property AsmCFI:TAsmCFI read FAsmCFI;
 | 
						|
        { hash tables for reusing constant storage }
 | 
						|
        property ConstPools[APoolType:TConstPoolType]: THashSet read GetConstPools;
 | 
						|
      end;
 | 
						|
      TAsmDataClass = class of TAsmData;
 | 
						|
 | 
						|
      TTCInitItem = class(TLinkedListItem)
 | 
						|
        sym: tsym;
 | 
						|
        offset: aint;
 | 
						|
        datalabel: TAsmSymbol;
 | 
						|
        datadef: TDef;
 | 
						|
        constructor Create(asym: tsym; aoffset: aint; alabel: TAsmSymbol; alabeldef: tdef);
 | 
						|
      end;
 | 
						|
 | 
						|
    var
 | 
						|
      casmdata: TAsmDataClass;
 | 
						|
 | 
						|
 | 
						|
    var
 | 
						|
      CAsmCFI : TAsmCFIClass;
 | 
						|
      current_asmdata : TAsmData;
 | 
						|
 | 
						|
 | 
						|
implementation
 | 
						|
 | 
						|
    uses
 | 
						|
      verbose,
 | 
						|
      symconst,
 | 
						|
      aasmtai;
 | 
						|
 | 
						|
{$ifdef MEMDEBUG}
 | 
						|
    var
 | 
						|
      memasmsymbols,
 | 
						|
      memasmcfi,
 | 
						|
      memasmlists : TMemDebug;
 | 
						|
{$endif MEMDEBUG}
 | 
						|
 | 
						|
 | 
						|
{*****************************************************************************
 | 
						|
                                 TAsmCFI
 | 
						|
*****************************************************************************}
 | 
						|
 | 
						|
    constructor TAsmCFI.create;
 | 
						|
      begin
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    destructor TAsmCFI.destroy;
 | 
						|
      begin
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmCFI.generate_code(list:TAsmList);
 | 
						|
      begin
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmCFI.start_frame(list:TAsmList);
 | 
						|
      begin
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmCFI.end_frame(list:TAsmList);
 | 
						|
      begin
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmCFI.cfa_offset(list:TAsmList;reg:tregister;ofs:longint);
 | 
						|
      begin
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmCFI.cfa_restore(list:TAsmList;reg:tregister);
 | 
						|
      begin
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmCFI.cfa_def_cfa_register(list:TAsmList;reg:tregister);
 | 
						|
      begin
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmCFI.cfa_def_cfa_offset(list:TAsmList;ofs:longint);
 | 
						|
      begin
 | 
						|
      end;
 | 
						|
 | 
						|
{*****************************************************************************
 | 
						|
                                 TTCInitItem
 | 
						|
*****************************************************************************}
 | 
						|
 | 
						|
 | 
						|
    constructor TTCInitItem.Create(asym: tsym; aoffset: aint; alabel: TAsmSymbol; alabeldef: tdef);
 | 
						|
      begin
 | 
						|
        inherited Create;
 | 
						|
        sym:=asym;
 | 
						|
        offset:=aoffset;
 | 
						|
        datalabel:=alabel;
 | 
						|
        datadef:=alabeldef;
 | 
						|
      end;
 | 
						|
 | 
						|
{*****************************************************************************
 | 
						|
                                 TAsmList
 | 
						|
*****************************************************************************}
 | 
						|
 | 
						|
    constructor TAsmList.create;
 | 
						|
      begin
 | 
						|
        inherited create;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function TAsmList.getlasttaifilepos : pfileposinfo;
 | 
						|
      var
 | 
						|
       hp : tlinkedlistitem;
 | 
						|
      begin
 | 
						|
         getlasttaifilepos := nil;
 | 
						|
         if assigned(last) then
 | 
						|
           begin
 | 
						|
              { find the last file information record }
 | 
						|
              if not (tai(last).typ in SkipLineInfo) then
 | 
						|
                getlasttaifilepos:=@tailineinfo(last).fileinfo
 | 
						|
              else
 | 
						|
               { go through list backwards to find the first entry
 | 
						|
                 with line information
 | 
						|
               }
 | 
						|
               begin
 | 
						|
                 hp:=tai(last);
 | 
						|
                 while assigned(hp) and (tai(hp).typ in SkipLineInfo) do
 | 
						|
                    hp:=hp.Previous;
 | 
						|
                 { found entry }
 | 
						|
                 if assigned(hp) then
 | 
						|
                   getlasttaifilepos:=@tailineinfo(hp).fileinfo
 | 
						|
               end;
 | 
						|
           end;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmList.insertList(p : TLinkedList);
 | 
						|
      begin
 | 
						|
        inherited insertList(p);
 | 
						|
        inc(section_count,TAsmList(p).section_count);
 | 
						|
        TAsmList(p).section_count:=0;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmList.insertListBefore(Item : TLinkedListItem; p : TLinkedList);
 | 
						|
      begin
 | 
						|
        inherited insertListBefore(Item,p);
 | 
						|
        inc(section_count,TAsmList(p).section_count);
 | 
						|
        TAsmList(p).section_count:=0;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmList.insertListAfter(Item : TLinkedListItem; p : TLinkedList);
 | 
						|
      begin
 | 
						|
        inherited insertListAfter(Item,p);
 | 
						|
        inc(section_count,TAsmList(p).section_count);
 | 
						|
        TAsmList(p).section_count:=0;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmList.concatList(p : TLinkedList);
 | 
						|
      begin
 | 
						|
        inherited concatList(p);
 | 
						|
        inc(section_count,TAsmList(p).section_count);
 | 
						|
        TAsmList(p).section_count:=0;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmList.insertListcopy(p : TLinkedList);
 | 
						|
      begin
 | 
						|
        inherited insertListcopy(p);
 | 
						|
        inc(section_count,TAsmList(p).section_count);
 | 
						|
     end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmList.concatListcopy(p : TLinkedList);
 | 
						|
      begin
 | 
						|
        inherited concatListcopy(p);
 | 
						|
        inc(section_count,TAsmList(p).section_count);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmList.RemoveAll;
 | 
						|
      begin
 | 
						|
         inherited RemoveAll;
 | 
						|
         section_count:=0;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
{****************************************************************************
 | 
						|
                                TAsmData
 | 
						|
****************************************************************************}
 | 
						|
 | 
						|
    function TAsmData.GetConstPools(APoolType: TConstPoolType): THashSet;
 | 
						|
      begin
 | 
						|
        if FConstPools[APoolType] = nil then
 | 
						|
          case APoolType of
 | 
						|
            sp_ansistr: FConstPools[APoolType] := TTagHashSet.Create(64, True, False);
 | 
						|
          else
 | 
						|
            FConstPools[APoolType] := THashSet.Create(64, True, False);
 | 
						|
          end;
 | 
						|
        Result := FConstPools[APoolType];
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function TAsmData.DefineAsmSymbolByClassBase(symclass: TAsmSymbolClass; const s: TSymStr; _bind: TAsmSymBind; _typ: Tasmsymtype; def: tdef; out wasdefined: boolean): TAsmSymbol;
 | 
						|
      var
 | 
						|
        hp : TAsmSymbol;
 | 
						|
        namestr : TSymStr;
 | 
						|
      begin
 | 
						|
        { this difference is only necessary to determine whether we always need
 | 
						|
          indirect references or not }
 | 
						|
        if _typ in [AT_DATA_FORCEINDIRECT,AT_DATA_NOINDIRECT] then
 | 
						|
          _typ:=AT_DATA;
 | 
						|
        namestr:=s;
 | 
						|
        if _bind in asmsymbindindirect then
 | 
						|
          namestr:=namestr+suffix_indirect;
 | 
						|
        hp:=TAsmSymbol(FAsmSymbolDict.Find(namestr));
 | 
						|
        if assigned(hp) then
 | 
						|
         begin
 | 
						|
           { Redefine is allowed, but the types must be the same. The redefine
 | 
						|
             is needed for Darwin where the labels are first allocated }
 | 
						|
           wasdefined:=not(hp.bind in [AB_EXTERNAL,AB_WEAK_EXTERNAL]);
 | 
						|
           if wasdefined then
 | 
						|
             begin
 | 
						|
               if (hp.bind<>_bind) and
 | 
						|
                  (hp.typ<>_typ) then
 | 
						|
                 internalerror(200603261);
 | 
						|
             end;
 | 
						|
           hp.typ:=_typ;
 | 
						|
           { Changing bind from AB_GLOBAL to AB_LOCAL is wrong
 | 
						|
             if bind is already AB_GLOBAL or AB_EXTERNAL,
 | 
						|
             GOT might have been used, so change might be harmful. }
 | 
						|
           if (_bind<>hp.bind) and (hp.getrefs>0) then
 | 
						|
             begin
 | 
						|
{$ifdef extdebug}
 | 
						|
               { the changes that matter must become internalerrors, the rest
 | 
						|
                 should be ignored; a used cannot change anything about this,
 | 
						|
                 so printing a warning/hint is not useful }
 | 
						|
               if (_bind=AB_LOCAL) then
 | 
						|
                 Message3(asmw_w_changing_bind_type,namestr,asmsymbindname[hp.bind],asmsymbindname[_bind])
 | 
						|
               else
 | 
						|
                 Message3(asmw_h_changing_bind_type,namestr,asmsymbindname[hp.bind],asmsymbindname[_bind]);
 | 
						|
{$endif extdebug}
 | 
						|
             end;
 | 
						|
           hp.bind:=_bind;
 | 
						|
         end
 | 
						|
        else
 | 
						|
         begin
 | 
						|
           wasdefined:=false;
 | 
						|
           { Not found, insert it. }
 | 
						|
           hp:=symclass.create(AsmSymbolDict,namestr,_bind,_typ);
 | 
						|
         end;
 | 
						|
        result:=hp;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    constructor TAsmData.create(n:pshortstring);
 | 
						|
      var
 | 
						|
        alt : TAsmLabelType;
 | 
						|
        hal : TAsmListType;
 | 
						|
      begin
 | 
						|
        inherited create;
 | 
						|
        name:=n;
 | 
						|
        { symbols }
 | 
						|
        FAsmSymbolDict:=TFPHashObjectList.create(true);
 | 
						|
        FAltSymbolList:=TFPObjectList.Create(false);
 | 
						|
        { labels }
 | 
						|
        FNextAltNr:=1;
 | 
						|
        for alt:=low(TAsmLabelType) to high(TAsmLabelType) do
 | 
						|
          FNextLabelNr[alt]:=1;
 | 
						|
        { AsmLists }
 | 
						|
        CurrAsmList:=TAsmList.create;
 | 
						|
        for hal:=low(TAsmListType) to high(TAsmListType) do
 | 
						|
          AsmLists[hal]:=TAsmList.create;
 | 
						|
        WideInits :=TAsmList.create;
 | 
						|
        ResStrInits:=TAsmList.create;
 | 
						|
        { CFI }
 | 
						|
        FAsmCFI:=CAsmCFI.Create;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    destructor TAsmData.destroy;
 | 
						|
      var
 | 
						|
        hal : TAsmListType;
 | 
						|
        hp  : TConstPoolType;
 | 
						|
      begin
 | 
						|
        { Symbols }
 | 
						|
{$ifdef MEMDEBUG}
 | 
						|
        memasmsymbols.start;
 | 
						|
{$endif}
 | 
						|
        FAltSymbolList.free;
 | 
						|
        FAsmSymbolDict.free;
 | 
						|
{$ifdef MEMDEBUG}
 | 
						|
        memasmsymbols.stop;
 | 
						|
{$endif}
 | 
						|
        { CFI }
 | 
						|
{$ifdef MEMDEBUG}
 | 
						|
        memasmcfi.start;
 | 
						|
{$endif}
 | 
						|
        FAsmCFI.free;
 | 
						|
{$ifdef MEMDEBUG}
 | 
						|
        memasmcfi.stop;
 | 
						|
{$endif}
 | 
						|
        { Lists }
 | 
						|
{$ifdef MEMDEBUG}
 | 
						|
         memasmlists.start;
 | 
						|
{$endif}
 | 
						|
        ResStrInits.free;
 | 
						|
        WideInits.free;
 | 
						|
         for hal:=low(TAsmListType) to high(TAsmListType) do
 | 
						|
           AsmLists[hal].free;
 | 
						|
         CurrAsmList.free;
 | 
						|
{$ifdef MEMDEBUG}
 | 
						|
         memasmlists.stop;
 | 
						|
{$endif}
 | 
						|
         for hp := low(TConstPoolType) to high(TConstPoolType) do
 | 
						|
           FConstPools[hp].Free;
 | 
						|
      end;
 | 
						|
 | 
						|
    function TAsmData.DefineAsmSymbolByClass(symclass: TAsmSymbolClass; const s: TSymStr; _bind: TAsmSymBind; _typ: Tasmsymtype; def: tdef): TAsmSymbol;
 | 
						|
      var
 | 
						|
        wasdefined: boolean;
 | 
						|
      begin
 | 
						|
        result:=DefineAsmSymbolByClassBase(symclass,s,_bind,_typ,def,wasdefined);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function TAsmData.DefineAsmSymbol(const s: TSymStr; _bind: TAsmSymBind; _typ: Tasmsymtype; def: tdef): TAsmSymbol;
 | 
						|
      begin
 | 
						|
        result:=DefineAsmSymbolByClass(TAsmSymbol,s,_bind,_typ,def);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function TAsmData.RefAsmSymbol(const s : TSymStr;_typ:Tasmsymtype;indirect:boolean) : TAsmSymbol;
 | 
						|
      var
 | 
						|
        namestr : TSymStr;
 | 
						|
        bind : tasmsymbind;
 | 
						|
      begin
 | 
						|
        namestr:=s;
 | 
						|
        if indirect then
 | 
						|
          begin
 | 
						|
            namestr:=namestr+suffix_indirect;
 | 
						|
            bind:=AB_EXTERNAL_INDIRECT;
 | 
						|
          end
 | 
						|
        else
 | 
						|
          begin
 | 
						|
            bind:=AB_EXTERNAL;
 | 
						|
          end;
 | 
						|
        result:=TAsmSymbol(FAsmSymbolDict.Find(namestr));
 | 
						|
        if not assigned(result) then
 | 
						|
          result:=TAsmSymbol.create(AsmSymbolDict,namestr,bind,_typ)
 | 
						|
        { one normal reference removes the "weak" character of a symbol }
 | 
						|
        else if (result.bind=AB_WEAK_EXTERNAL) then
 | 
						|
          result.bind:=bind;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function TAsmData.WeakRefAsmSymbol(const s : TSymStr;_typ:Tasmsymtype) : TAsmSymbol;
 | 
						|
      begin
 | 
						|
        result:=TAsmSymbol(FAsmSymbolDict.Find(s));
 | 
						|
        if not assigned(result) then
 | 
						|
          result:=TAsmSymbol.create(AsmSymbolDict,s,AB_WEAK_EXTERNAL,_typ);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function TAsmData.GetAsmSymbol(const s : TSymStr) : TAsmSymbol;
 | 
						|
      begin
 | 
						|
        result:=TAsmSymbol(FAsmSymbolDict.Find(s));
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmData.GenerateAltSymbol(p:TAsmSymbol);
 | 
						|
      begin
 | 
						|
        if not assigned(p.altsymbol) then
 | 
						|
         begin
 | 
						|
           p.altsymbol:=p.getaltcopy(AsmSymbolDict,FNextAltNr);
 | 
						|
           FAltSymbolList.Add(p);
 | 
						|
         end;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmData.ResetAltSymbols;
 | 
						|
      var
 | 
						|
        i  : longint;
 | 
						|
      begin
 | 
						|
        for i:=0 to FAltSymbolList.Count-1 do
 | 
						|
          TAsmSymbol(FAltSymbolList[i]).altsymbol:=nil;
 | 
						|
        FAltSymbolList.Clear;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmData.getlabel(out l : TAsmLabel;alt:TAsmLabeltype);
 | 
						|
      begin
 | 
						|
        if (target_info.system in (systems_linux + systems_bsd + systems_android)) and
 | 
						|
           { the next condition was
 | 
						|
             (cs_create_smart in current_settings.moduleswitches) and
 | 
						|
             but if we create_smartlink_sections, this is useless }
 | 
						|
           (create_smartlink_library) and
 | 
						|
           (alt = alt_dbgline) then
 | 
						|
          l:=TAsmLabel.createglobal(AsmSymbolDict,name^,FNextLabelNr[alt],alt)
 | 
						|
        else
 | 
						|
          l:=TAsmLabel.createlocal(AsmSymbolDict,FNextLabelNr[alt],alt);
 | 
						|
        inc(FNextLabelNr[alt]);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmData.getjumplabel(out l : TAsmLabel);
 | 
						|
      begin
 | 
						|
        l:=TAsmLabel.createlocal(AsmSymbolDict,FNextLabelNr[alt_jump],alt_jump);
 | 
						|
        inc(FNextLabelNr[alt_jump]);
 | 
						|
      end;
 | 
						|
 | 
						|
    procedure TAsmData.getglobaljumplabel(out l : TAsmLabel);
 | 
						|
      begin
 | 
						|
        l:=TAsmLabel.createglobal(AsmSymbolDict,name^,FNextLabelNr[alt_jump],alt_jump);
 | 
						|
        inc(FNextLabelNr[alt_jump]);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmData.getglobaldatalabel(out l : TAsmLabel);
 | 
						|
      begin
 | 
						|
        l:=TAsmLabel.createglobal(AsmSymbolDict,name^,FNextLabelNr[alt_data],alt_data);
 | 
						|
        inc(FNextLabelNr[alt_data]);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmData.getstaticdatalabel(out l : TAsmLabel);
 | 
						|
      begin
 | 
						|
        l:=TAsmLabel.createstatic(AsmSymbolDict,FNextLabelNr[alt_data],alt_data);
 | 
						|
        inc(FNextLabelNr[alt_data]);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmData.getlocaldatalabel(out l: TAsmLabel);
 | 
						|
      begin
 | 
						|
        l:=TAsmLabel.createlocal(AsmSymbolDict,FNextLabelNr[alt_data],alt_data);
 | 
						|
        inc(FNextLabelNr[alt_data]);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure TAsmData.getaddrlabel(out l : TAsmLabel);
 | 
						|
      begin
 | 
						|
        l:=TAsmLabel.createlocal(AsmSymbolDict,FNextLabelNr[alt_addr],alt_addr);
 | 
						|
        inc(FNextLabelNr[alt_addr]);
 | 
						|
      end;
 | 
						|
 | 
						|
initialization
 | 
						|
{$ifdef MEMDEBUG}
 | 
						|
  memasmsymbols:=TMemDebug.create('AsmSymbols');
 | 
						|
  memasmsymbols.stop;
 | 
						|
  memasmcfi:=TMemDebug.create('AsmCFI');
 | 
						|
  memasmcfi.stop;
 | 
						|
  memasmlists:=TMemDebug.create('AsmLists');
 | 
						|
  memasmlists.stop;
 | 
						|
{$endif MEMDEBUG}
 | 
						|
  CAsmCFI:=TAsmCFI;
 | 
						|
 | 
						|
finalization
 | 
						|
{$ifdef MEMDEBUG}
 | 
						|
  memasmsymbols.free;
 | 
						|
  memasmcfi.free;
 | 
						|
  memasmlists.free;
 | 
						|
{$endif MEMDEBUG}
 | 
						|
 | 
						|
end.
 |