aasmbase.pas 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. This unit implements an abstract asmoutput class for all processor types
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. { @abstract(This unit implements an abstract asm output class for all processor types)
  18. This unit implements an abstract assembler output class for all processors, these
  19. are then overriden for each assembler writer to actually write the data in these
  20. classes to an assembler file.
  21. }
  22. unit aasmbase;
  23. {$i fpcdefs.inc}
  24. interface
  25. uses
  26. cutils,cclasses,
  27. globtype,globals,systems
  28. ;
  29. type
  30. TAsmSection = class;
  31. TAsmObjectData = class;
  32. TAsmsymbind=(AB_NONE,AB_EXTERNAL,AB_COMMON,AB_LOCAL,AB_GLOBAL);
  33. TAsmsymtype=(AT_NONE,AT_FUNCTION,AT_DATA,AT_SECTION,AT_LABEL);
  34. TAsmRelocationType = (RELOC_ABSOLUTE,RELOC_RELATIVE,RELOC_RVA);
  35. TAsmSectionType=(sec_none,
  36. sec_code,sec_data,sec_rodata,sec_bss,sec_threadvar,
  37. sec_common, { used for executable creation }
  38. sec_custom, { custom section, no prefix }
  39. sec_stub, { used for darwin import stubs }
  40. { stabs }
  41. sec_stab,sec_stabstr,
  42. { win32 }
  43. sec_idata2,sec_idata4,sec_idata5,sec_idata6,sec_idata7,sec_edata,
  44. { C++ exception handling unwinding (uses dwarf) }
  45. sec_eh_frame,
  46. { dwarf }
  47. sec_debug_frame,
  48. { ELF resources }
  49. sec_fpc
  50. {$IFDEF POWERPC64}
  51. ,
  52. { PPC64/Linux Table of contents section }
  53. sec_toc
  54. {$ENDIF POWERPC64}
  55. );
  56. TAsmSectionOption = (aso_alloconly,aso_executable);
  57. TAsmSectionOptions = set of TAsmSectionOption;
  58. TAsmSymbol = class(TNamedIndexItem)
  59. private
  60. { this need to be incremented with every symbol loading into the
  61. paasmoutput, thus in loadsym/loadref/const_symbol (PFV) }
  62. refs : longint;
  63. public
  64. defbind,
  65. currbind : TAsmsymbind;
  66. typ : TAsmsymtype;
  67. { the next fields are filled in the binary writer }
  68. section : TAsmSection;
  69. address,
  70. size : aint;
  71. { Alternate symbol which can be used for 'renaming' needed for
  72. inlining }
  73. altsymbol : tasmsymbol;
  74. { pointer to objectdata that is the owner of this symbol }
  75. owner : tasmobjectdata;
  76. { Is the symbol in the used list }
  77. inusedlist : boolean;
  78. { assembler pass label is set, used for detecting multiple labels }
  79. pass : byte;
  80. ppuidx : longint;
  81. constructor create(const s:string;_bind:TAsmsymbind;_typ:Tasmsymtype);
  82. procedure reset;
  83. function is_used:boolean;
  84. procedure increfs;
  85. procedure decrefs;
  86. function getrefs: longint;
  87. procedure setaddress(_pass:byte;sec:TAsmSection;offset,len:aint);
  88. end;
  89. { is the label only there for getting an address (e.g. for i/o
  90. checks -> alt_addr) or is it a jump target (alt_jump), for debug
  91. info alt_dbgline and alt_dbgfile }
  92. TAsmLabelType = (alt_jump,alt_addr,alt_data,alt_dbgline,alt_dbgfile,alt_dbgtype);
  93. TAsmLabel = class(TAsmSymbol)
  94. labelnr : longint;
  95. labeltype : TAsmLabelType;
  96. is_set : boolean;
  97. constructor createlocal(nr:longint;ltyp:TAsmLabelType);
  98. constructor createglobal(const modulename:string;nr:longint;ltyp:TAsmLabelType);
  99. function getname:string;override;
  100. end;
  101. TAsmRelocation = class(TLinkedListItem)
  102. address,
  103. orgsize : aint; { original size of the symbol to relocate, required for COFF }
  104. symbol : TAsmSymbol;
  105. section : TAsmSection; { only used if symbol=nil }
  106. typ : TAsmRelocationType;
  107. constructor CreateSymbol(Aaddress:aint;s:Tasmsymbol;Atyp:TAsmRelocationType);
  108. constructor CreateSymbolSize(Aaddress:aint;s:Tasmsymbol;Aorgsize:aint;Atyp:TAsmRelocationType);
  109. constructor CreateSection(Aaddress:aint;sec:TAsmSection;Atyp:TAsmRelocationType);
  110. end;
  111. TAsmSection = class(TNamedIndexItem)
  112. owner : TAsmObjectData;
  113. secoptions : TAsmSectionOptions;
  114. sectype : TAsmSectionType;
  115. secsymidx : longint; { index for the section in symtab }
  116. addralign : longint; { alignment of the section }
  117. { size of the data and in the file }
  118. dataalignbytes : longint;
  119. data : TDynamicArray;
  120. datasize,
  121. datapos : aint;
  122. { size and position in memory }
  123. memsize,
  124. mempos : aint;
  125. { relocation }
  126. relocations : TLinkedList;
  127. constructor create(const Aname:string;Atype:TAsmSectionType;Aalign:longint;Aoptions:TAsmSectionOptions);virtual;
  128. destructor destroy;override;
  129. function write(const d;l:aint):aint;
  130. function writestr(const s:string):aint;
  131. procedure writealign(l:longint);
  132. function aligneddatasize:aint;
  133. procedure setdatapos(var dpos:aint);
  134. procedure alignsection;
  135. procedure alloc(l:aint);
  136. procedure addsymreloc(ofs:aint;p:tasmsymbol;relative:TAsmRelocationType);
  137. procedure addsectionreloc(ofs:aint;sec:TAsmSection;relative:TAsmRelocationType);
  138. procedure fixuprelocs;virtual;
  139. end;
  140. TAsmSectionClass = class of TAsmSection;
  141. TAsmObjectData = class(TLinkedListItem)
  142. private
  143. FName : string[80];
  144. FCurrSec : TAsmSection;
  145. { Sections will be stored in order in SectsIndex, this is at least
  146. required for stabs debuginfo. The SectsDict is only used for lookups (PFV) }
  147. FSectsDict : TDictionary;
  148. FSectsIndex : TIndexArray;
  149. FCAsmSection : TAsmSectionClass;
  150. { Symbols that will be defined in this object file }
  151. FSymbols : TIndexArray;
  152. { Special info sections that are written to during object generation }
  153. FStabsRecSize : longint;
  154. FStabsSec,
  155. FStabStrSec : TAsmSection;
  156. procedure section_reset(p:tnamedindexitem;arg:pointer);
  157. procedure section_fixuprelocs(p:tnamedindexitem;arg:pointer);
  158. protected
  159. property StabsRecSize:longint read FStabsRecSize write FStabsRecSize;
  160. property StabsSec:TAsmSection read FStabsSec write FStabsSec;
  161. property StabStrSec:TAsmSection read FStabStrSec write FStabStrSec;
  162. property CAsmSection:TAsmSectionClass read FCAsmSection write FCAsmSection;
  163. public
  164. constructor create(const n:string);virtual;
  165. destructor destroy;override;
  166. function sectionname(atype:tasmsectiontype;const aname:string):string;virtual;
  167. function createsection(atype:tasmsectiontype;const aname:string;aalign:longint;aoptions:TAsmSectionOptions):tasmsection;virtual;
  168. procedure setsection(asec:tasmsection);
  169. procedure alloc(len:aint);
  170. procedure allocalign(len:longint);
  171. procedure allocstab(p:pchar);
  172. procedure allocsymbol(currpass:byte;p:tasmsymbol;len:aint);
  173. procedure writebytes(var data;len:aint);
  174. procedure writereloc(data,len:aint;p:tasmsymbol;relative:TAsmRelocationType);virtual;abstract;
  175. procedure writesymbol(p:tasmsymbol);virtual;abstract;
  176. procedure writestab(offset:aint;ps:tasmsymbol;nidx,nother,line:longint;p:pchar);virtual;abstract;
  177. procedure beforealloc;virtual;
  178. procedure beforewrite;virtual;
  179. procedure afteralloc;virtual;
  180. procedure afterwrite;virtual;
  181. procedure resetsections;
  182. procedure fixuprelocs;
  183. property Name:string[80] read FName;
  184. property CurrSec:TAsmSection read FCurrSec;
  185. property Symbols:TindexArray read FSymbols;
  186. property Sects:TIndexArray read FSectsIndex;
  187. end;
  188. TAsmObjectDataClass = class of TAsmObjectData;
  189. tasmsymbolidxarr = array[0..($7fffffff div sizeof(pointer))-1] of tasmsymbol;
  190. pasmsymbolidxarr = ^tasmsymbolidxarr;
  191. TAsmLibraryData = class(TLinkedListItem)
  192. private
  193. nextaltnr : longint;
  194. nextlabelnr : array[Tasmlabeltype] of longint;
  195. public
  196. name,
  197. realname : string[80];
  198. symbolsearch : tdictionary; { contains ALL assembler symbols }
  199. usedasmsymbollist : tsinglelist;
  200. { ppu }
  201. asmsymbolppuidx : longint;
  202. asmsymbolidx : pasmsymbolidxarr; { used for translating ppu index->asmsymbol }
  203. constructor create(const n:string);
  204. destructor destroy;override;
  205. procedure Freeasmsymbolidx;
  206. procedure DerefAsmsymbol(var s:tasmsymbol);
  207. { asmsymbol }
  208. function newasmsymbol(const s : string;_bind:TAsmSymBind;_typ:TAsmsymtype) : tasmsymbol;
  209. function getasmsymbol(const s : string) : tasmsymbol;
  210. function renameasmsymbol(const sold, snew : string):tasmsymbol;
  211. function newasmlabel(nr:longint;alt:tasmlabeltype;is_global:boolean) : tasmlabel;
  212. {# create a new assembler label }
  213. procedure getlabel(var l : tasmlabel;alt:tasmlabeltype);
  214. {# create a new assembler label for jumps }
  215. procedure getjumplabel(var l : tasmlabel);
  216. { make l as a new label and flag is_addr }
  217. procedure getaddrlabel(var l : tasmlabel);
  218. { make l as a new label and flag is_data }
  219. procedure getdatalabel(var l : tasmlabel);
  220. {# return a label number }
  221. procedure CreateUsedAsmSymbolList;
  222. procedure DestroyUsedAsmSymbolList;
  223. procedure UsedAsmSymbolListInsert(p:tasmsymbol);
  224. { generate an alternative (duplicate) symbol }
  225. procedure GenerateAltSymbol(p:tasmsymbol);
  226. { reset alternative symbol information }
  227. procedure UsedAsmSymbolListResetAltSym;
  228. procedure UsedAsmSymbolListReset;
  229. procedure UsedAsmSymbolListCheckUndefined;
  230. end;
  231. const
  232. { alt_jump,alt_addr,alt_data,alt_dbgline,alt_dbgfile }
  233. asmlabeltypeprefix : array[tasmlabeltype] of char = ('j','a','d','l','f','t');
  234. var
  235. objectlibrary : tasmlibrarydata;
  236. implementation
  237. uses
  238. strings,
  239. verbose;
  240. const
  241. sectsgrow = 100;
  242. symbolsgrow = 100;
  243. {*****************************************************************************
  244. TAsmSymbol
  245. *****************************************************************************}
  246. constructor tasmsymbol.create(const s:string;_bind:TAsmsymbind;_typ:Tasmsymtype);
  247. begin;
  248. inherited createname(s);
  249. reset;
  250. defbind:=_bind;
  251. typ:=_typ;
  252. inusedlist:=false;
  253. pass:=255;
  254. ppuidx:=-1;
  255. { mainly used to remove unused labels from the al_procedures }
  256. refs:=0;
  257. end;
  258. procedure tasmsymbol.reset;
  259. begin
  260. { reset section info }
  261. section:=nil;
  262. address:=0;
  263. size:=0;
  264. indexnr:=-1;
  265. pass:=255;
  266. currbind:=AB_EXTERNAL;
  267. altsymbol:=nil;
  268. { taiowner:=nil;}
  269. end;
  270. function tasmsymbol.is_used:boolean;
  271. begin
  272. is_used:=(refs>0);
  273. end;
  274. procedure tasmsymbol.increfs;
  275. begin
  276. inc(refs);
  277. end;
  278. procedure tasmsymbol.decrefs;
  279. begin
  280. dec(refs);
  281. if refs<0 then
  282. internalerror(200211121);
  283. end;
  284. function tasmsymbol.getrefs: longint;
  285. begin
  286. getrefs := refs;
  287. end;
  288. procedure tasmsymbol.setaddress(_pass:byte;sec:TAsmSection;offset,len:aint);
  289. begin
  290. if (_pass=pass) then
  291. begin
  292. Message1(asmw_e_duplicate_label,name);
  293. exit;
  294. end;
  295. pass:=_pass;
  296. section:=sec;
  297. address:=offset;
  298. size:=len;
  299. { when the bind was reset to External, set it back to the default
  300. bind it got when defined }
  301. if (currbind=AB_EXTERNAL) and (defbind<>AB_NONE) then
  302. currbind:=defbind;
  303. end;
  304. {*****************************************************************************
  305. TAsmLabel
  306. *****************************************************************************}
  307. constructor tasmlabel.createlocal(nr:longint;ltyp:TAsmLabelType);
  308. begin;
  309. inherited create(target_asm.labelprefix+asmlabeltypeprefix[ltyp]+tostr(nr),AB_LOCAL,AT_LABEL);
  310. labelnr:=nr;
  311. labeltype:=ltyp;
  312. is_set:=false;
  313. end;
  314. constructor tasmlabel.createglobal(const modulename:string;nr:longint;ltyp:TAsmLabelType);
  315. begin;
  316. inherited create('_$'+modulename+'$_L'+asmlabeltypeprefix[ltyp]+tostr(nr),AB_GLOBAL,AT_DATA);
  317. labelnr:=nr;
  318. labeltype:=ltyp;
  319. is_set:=false;
  320. { write it always }
  321. increfs;
  322. end;
  323. function tasmlabel.getname:string;
  324. begin
  325. getname:=inherited getname;
  326. increfs;
  327. end;
  328. {****************************************************************************
  329. TAsmRelocation
  330. ****************************************************************************}
  331. constructor TAsmRelocation.CreateSymbol(Aaddress:aint;s:Tasmsymbol;Atyp:TAsmRelocationType);
  332. begin
  333. Address:=Aaddress;
  334. Symbol:=s;
  335. OrgSize:=0;
  336. Section:=nil;
  337. Typ:=Atyp;
  338. end;
  339. constructor TAsmRelocation.CreateSymbolSize(Aaddress:aint;s:Tasmsymbol;Aorgsize:aint;Atyp:TAsmRelocationType);
  340. begin
  341. Address:=Aaddress;
  342. Symbol:=s;
  343. OrgSize:=Aorgsize;
  344. Section:=nil;
  345. Typ:=Atyp;
  346. end;
  347. constructor TAsmRelocation.CreateSection(Aaddress:aint;sec:TAsmSection;Atyp:TAsmRelocationType);
  348. begin
  349. Address:=Aaddress;
  350. Symbol:=nil;
  351. OrgSize:=0;
  352. Section:=sec;
  353. Typ:=Atyp;
  354. end;
  355. {****************************************************************************
  356. TAsmSection
  357. ****************************************************************************}
  358. constructor TAsmSection.create(const Aname:string;Atype:TAsmSectionType;Aalign:longint;Aoptions:TAsmSectionOptions);
  359. begin
  360. inherited createname(Aname);
  361. sectype:=Atype;
  362. name:=Aname;
  363. secoptions:=Aoptions;
  364. secsymidx:=0;
  365. addralign:=Aalign;
  366. { data }
  367. datasize:=0;
  368. datapos:=0;
  369. if (aso_alloconly in aoptions) then
  370. data:=nil
  371. else
  372. Data:=TDynamicArray.Create(8192);
  373. { memory }
  374. mempos:=0;
  375. memsize:=0;
  376. { relocation }
  377. relocations:=TLinkedList.Create;
  378. end;
  379. destructor TAsmSection.destroy;
  380. begin
  381. if assigned(Data) then
  382. Data.Free;
  383. relocations.free;
  384. end;
  385. function TAsmSection.write(const d;l:aint):aint;
  386. begin
  387. write:=datasize;
  388. if assigned(Data) then
  389. Data.write(d,l);
  390. inc(datasize,l);
  391. end;
  392. function TAsmSection.writestr(const s:string):aint;
  393. begin
  394. writestr:=datasize;
  395. if assigned(Data) then
  396. Data.write(s[1],length(s));
  397. inc(datasize,length(s));
  398. end;
  399. procedure TAsmSection.writealign(l:longint);
  400. var
  401. i : longint;
  402. empty : array[0..63] of char;
  403. begin
  404. { no alignment needed for 0 or 1 }
  405. if l<=1 then
  406. exit;
  407. i:=datasize mod l;
  408. if i>0 then
  409. begin
  410. if assigned(data) then
  411. begin
  412. fillchar(empty,sizeof(empty),0);
  413. Data.write(empty,l-i);
  414. end;
  415. inc(datasize,l-i);
  416. end;
  417. end;
  418. function TAsmSection.aligneddatasize:aint;
  419. begin
  420. aligneddatasize:=align(datasize,addralign);
  421. end;
  422. procedure TAsmSection.setdatapos(var dpos:aint);
  423. var
  424. alignedpos : aint;
  425. begin
  426. { get aligned datapos }
  427. alignedpos:=align(dpos,addralign);
  428. dataalignbytes:=alignedpos-dpos;
  429. datapos:=alignedpos;
  430. { update datapos }
  431. dpos:=datapos+aligneddatasize;
  432. end;
  433. procedure TAsmSection.alignsection;
  434. begin
  435. writealign(addralign);
  436. end;
  437. procedure TAsmSection.alloc(l:aint);
  438. begin
  439. inc(datasize,l);
  440. end;
  441. procedure TAsmSection.addsymreloc(ofs:aint;p:tasmsymbol;relative:TAsmRelocationType);
  442. var
  443. r : TAsmRelocation;
  444. begin
  445. r:=TAsmRelocation.Create;
  446. r.address:=ofs;
  447. r.orgsize:=0;
  448. r.symbol:=p;
  449. r.section:=nil;
  450. r.typ:=relative;
  451. relocations.concat(r);
  452. end;
  453. procedure TAsmSection.addsectionreloc(ofs:aint;sec:TAsmSection;relative:TAsmRelocationType);
  454. var
  455. r : TAsmRelocation;
  456. begin
  457. r:=TAsmRelocation.Create;
  458. r.address:=ofs;
  459. r.symbol:=nil;
  460. r.orgsize:=0;
  461. r.section:=sec;
  462. r.typ:=relative;
  463. relocations.concat(r);
  464. end;
  465. procedure TAsmSection.fixuprelocs;
  466. begin
  467. end;
  468. {****************************************************************************
  469. TAsmObjectData
  470. ****************************************************************************}
  471. constructor TAsmObjectData.create(const n:string);
  472. begin
  473. inherited create;
  474. FName:=n;
  475. { sections, the SectsIndex owns the items, the FSectsDict
  476. is only used for lookups }
  477. FSectsDict:=tdictionary.create;
  478. FSectsDict.noclear:=true;
  479. FSectsIndex:=tindexarray.create(sectsgrow);
  480. FStabsRecSize:=1;
  481. FStabsSec:=nil;
  482. FStabStrSec:=nil;
  483. { symbols }
  484. FSymbols:=tindexarray.create(symbolsgrow);
  485. FSymbols.noclear:=true;
  486. { section class type for creating of new sections }
  487. FCAsmSection:=TAsmSection;
  488. end;
  489. destructor TAsmObjectData.destroy;
  490. begin
  491. FSectsDict.free;
  492. FSectsIndex.free;
  493. FSymbols.free;
  494. end;
  495. function TAsmObjectData.sectionname(atype:tasmsectiontype;const aname:string):string;
  496. const
  497. secnames : array[tasmsectiontype] of string[12] = ('',
  498. 'code','data','rodata','bss','threadvar',
  499. 'common',
  500. 'note',
  501. 'text',
  502. 'stab','stabstr',
  503. 'idata2','idata4','idata5','idata6','idata7','edata',
  504. 'eh_frame',
  505. 'debug_frame',
  506. 'fpc'
  507. {$IFDEF POWERPC64}
  508. , 'toc'
  509. {$ENDIF POWERPC64}
  510. );
  511. begin
  512. if aname<>'' then
  513. result:=secnames[atype]+'.'+aname
  514. else
  515. result:=secnames[atype];
  516. end;
  517. function TAsmObjectData.createsection(atype:tasmsectiontype;const aname:string;aalign:longint;aoptions:TAsmSectionOptions):TAsmSection;
  518. var
  519. secname : string;
  520. begin
  521. secname:=sectionname(atype,aname);
  522. result:=TasmSection(FSectsDict.search(secname));
  523. if not assigned(result) then
  524. begin
  525. {$warning TODO make alloconly configurable}
  526. if atype=sec_bss then
  527. include(aoptions,aso_alloconly);
  528. result:=CAsmSection.create(secname,atype,aalign,aoptions);
  529. FSectsDict.Insert(result);
  530. FSectsIndex.Insert(result);
  531. result.owner:=self;
  532. end;
  533. FCurrSec:=result;
  534. end;
  535. procedure TAsmObjectData.setsection(asec:tasmsection);
  536. begin
  537. if asec.owner<>self then
  538. internalerror(200403041);
  539. FCurrSec:=asec;
  540. end;
  541. procedure TAsmObjectData.writebytes(var data;len:aint);
  542. begin
  543. if not assigned(currsec) then
  544. internalerror(200402251);
  545. currsec.write(data,len);
  546. end;
  547. procedure TAsmObjectData.alloc(len:aint);
  548. begin
  549. if not assigned(currsec) then
  550. internalerror(200402252);
  551. currsec.alloc(len);
  552. end;
  553. procedure TAsmObjectData.allocalign(len:longint);
  554. var
  555. modulo : aint;
  556. begin
  557. if not assigned(currsec) then
  558. internalerror(200402253);
  559. modulo:=currsec.datasize mod len;
  560. if modulo > 0 then
  561. currsec.alloc(len-modulo);
  562. end;
  563. procedure TAsmObjectData.allocsymbol(currpass:byte;p:tasmsymbol;len:aint);
  564. begin
  565. p.setaddress(currpass,currsec,currsec.datasize,len);
  566. end;
  567. procedure TAsmObjectData.allocstab(p:pchar);
  568. begin
  569. if not(assigned(FStabsSec) and assigned(FStabStrSec)) then
  570. internalerror(200402254);
  571. FStabsSec.alloc(FStabsRecSize);
  572. if assigned(p) and (p[0]<>#0) then
  573. FStabStrSec.alloc(strlen(p)+1);
  574. end;
  575. procedure TAsmObjectData.section_reset(p:tnamedindexitem;arg:pointer);
  576. begin
  577. with tasmsection(p) do
  578. begin
  579. datasize:=0;
  580. datapos:=0;
  581. end;
  582. end;
  583. procedure TAsmObjectData.section_fixuprelocs(p:tnamedindexitem;arg:pointer);
  584. begin
  585. tasmsection(p).fixuprelocs;
  586. end;
  587. procedure TAsmObjectData.beforealloc;
  588. begin
  589. end;
  590. procedure TAsmObjectData.beforewrite;
  591. begin
  592. end;
  593. procedure TAsmObjectData.afteralloc;
  594. begin
  595. end;
  596. procedure TAsmObjectData.afterwrite;
  597. begin
  598. end;
  599. procedure TAsmObjectData.resetsections;
  600. begin
  601. FSectsDict.foreach(@section_reset,nil);
  602. end;
  603. procedure TAsmObjectData.fixuprelocs;
  604. begin
  605. FSectsDict.foreach(@section_fixuprelocs,nil);
  606. end;
  607. {****************************************************************************
  608. TAsmLibraryData
  609. ****************************************************************************}
  610. constructor TAsmLibraryData.create(const n:string);
  611. var
  612. alt : TAsmLabelType;
  613. begin
  614. inherited create;
  615. realname:=n;
  616. name:=upper(n);
  617. { symbols }
  618. symbolsearch:=tdictionary.create;
  619. symbolsearch.usehash;
  620. { labels }
  621. nextaltnr:=1;
  622. for alt:=low(TAsmLabelType) to high(TAsmLabelType) do
  623. nextlabelnr[alt]:=1;
  624. { ppu }
  625. asmsymbolppuidx:=0;
  626. asmsymbolidx:=nil;
  627. end;
  628. destructor TAsmLibraryData.destroy;
  629. begin
  630. symbolsearch.free;
  631. Freeasmsymbolidx;
  632. end;
  633. procedure TAsmLibraryData.Freeasmsymbolidx;
  634. begin
  635. if assigned(asmsymbolidx) then
  636. begin
  637. Freemem(asmsymbolidx);
  638. asmsymbolidx:=nil;
  639. end;
  640. end;
  641. procedure TAsmLibraryData.DerefAsmsymbol(var s:tasmsymbol);
  642. begin
  643. if assigned(s) then
  644. begin
  645. if not assigned(asmsymbolidx) then
  646. internalerror(200208072);
  647. if (ptrint(pointer(s))<1) or (ptrint(pointer(s))>asmsymbolppuidx) then
  648. internalerror(200208073);
  649. s:=asmsymbolidx^[ptrint(pointer(s))-1];
  650. end;
  651. end;
  652. function TAsmLibraryData.newasmsymbol(const s : string;_bind:TAsmSymBind;_typ:Tasmsymtype) : tasmsymbol;
  653. var
  654. hp : tasmsymbol;
  655. begin
  656. hp:=tasmsymbol(symbolsearch.search(s));
  657. if assigned(hp) then
  658. begin
  659. {$IFDEF EXTDEBUG}
  660. if (_typ <> AT_NONE) and
  661. (hp.typ <> _typ) and
  662. not(cs_compilesystem in aktmoduleswitches) and
  663. (target_info.system <> system_powerpc_darwin) then
  664. begin
  665. //Writeln('Error symbol '+hp.name+' type is ',Ord(_typ),', should be ',Ord(hp.typ));
  666. InternalError(2004031501);
  667. end;
  668. {$ENDIF}
  669. if (_bind<>AB_EXTERNAL) then
  670. hp.defbind:=_bind
  671. end
  672. else
  673. begin
  674. { Not found, insert it. }
  675. hp:=tasmsymbol.create(s,_bind,_typ);
  676. symbolsearch.insert(hp);
  677. end;
  678. newasmsymbol:=hp;
  679. end;
  680. function TAsmLibraryData.getasmsymbol(const s : string) : tasmsymbol;
  681. begin
  682. getasmsymbol:=tasmsymbol(symbolsearch.search(s));
  683. end;
  684. function TAsmLibraryData.renameasmsymbol(const sold, snew : string):tasmsymbol;
  685. begin
  686. renameasmsymbol:=tasmsymbol(symbolsearch.rename(sold,snew));
  687. end;
  688. procedure TAsmLibraryData.CreateUsedAsmSymbolList;
  689. begin
  690. if assigned(usedasmsymbollist) then
  691. internalerror(78455782);
  692. usedasmsymbollist:=TSingleList.create;
  693. end;
  694. procedure TAsmLibraryData.DestroyUsedAsmSymbolList;
  695. begin
  696. usedasmsymbollist.destroy;
  697. usedasmsymbollist:=nil;
  698. end;
  699. procedure TAsmLibraryData.UsedAsmSymbolListInsert(p:tasmsymbol);
  700. begin
  701. if not p.inusedlist then
  702. usedasmsymbollist.insert(p);
  703. p.inusedlist:=true;
  704. end;
  705. procedure TAsmLibraryData.GenerateAltSymbol(p:tasmsymbol);
  706. begin
  707. if not assigned(p.altsymbol) then
  708. begin
  709. p.altsymbol:=tasmsymbol.create(p.name+'_'+tostr(nextaltnr),p.defbind,p.typ);
  710. symbolsearch.insert(p.altsymbol);
  711. { add also the original sym to the usedasmsymbollist,
  712. that list is used to reset the altsymbol }
  713. if not p.inusedlist then
  714. usedasmsymbollist.insert(p);
  715. p.inusedlist:=true;
  716. end;
  717. end;
  718. procedure TAsmLibraryData.UsedAsmSymbolListReset;
  719. var
  720. hp : tasmsymbol;
  721. begin
  722. hp:=tasmsymbol(usedasmsymbollist.first);
  723. while assigned(hp) do
  724. begin
  725. with hp do
  726. begin
  727. reset;
  728. inusedlist:=false;
  729. end;
  730. hp:=tasmsymbol(hp.listnext);
  731. end;
  732. end;
  733. procedure TAsmLibraryData.UsedAsmSymbolListResetAltSym;
  734. var
  735. hp : tasmsymbol;
  736. begin
  737. hp:=tasmsymbol(usedasmsymbollist.first);
  738. inc(nextaltnr);
  739. while assigned(hp) do
  740. begin
  741. with hp do
  742. begin
  743. altsymbol:=nil;
  744. inusedlist:=false;
  745. end;
  746. hp:=tasmsymbol(hp.listnext);
  747. end;
  748. end;
  749. procedure TAsmLibraryData.UsedAsmSymbolListCheckUndefined;
  750. var
  751. hp : tasmsymbol;
  752. begin
  753. hp:=tasmsymbol(usedasmsymbollist.first);
  754. while assigned(hp) do
  755. begin
  756. with hp do
  757. begin
  758. if is_used and
  759. (section=nil) and
  760. not(currbind in [AB_EXTERNAL,AB_COMMON]) then
  761. Message1(asmw_e_undefined_label,name);
  762. end;
  763. hp:=tasmsymbol(hp.listnext);
  764. end;
  765. end;
  766. function TAsmLibraryData.newasmlabel(nr:longint;alt:tasmlabeltype;is_global:boolean) : tasmlabel;
  767. var
  768. hp : tasmlabel;
  769. begin
  770. if is_global then
  771. hp:=tasmlabel.createglobal(name,nr,alt)
  772. else
  773. hp:=tasmlabel.createlocal(nr,alt);
  774. symbolsearch.insert(hp);
  775. newasmlabel:=hp;
  776. end;
  777. procedure TAsmLibraryData.getlabel(var l : tasmlabel;alt:tasmlabeltype);
  778. begin
  779. l:=tasmlabel.createlocal(nextlabelnr[alt],alt);
  780. inc(nextlabelnr[alt]);
  781. symbolsearch.insert(l);
  782. end;
  783. procedure TAsmLibraryData.getjumplabel(var l : tasmlabel);
  784. begin
  785. l:=tasmlabel.createlocal(nextlabelnr[alt_jump],alt_jump);
  786. inc(nextlabelnr[alt_jump]);
  787. symbolsearch.insert(l);
  788. end;
  789. procedure TAsmLibraryData.getdatalabel(var l : tasmlabel);
  790. begin
  791. l:=tasmlabel.createglobal(name,nextlabelnr[alt_data],alt_data);
  792. inc(nextlabelnr[alt_data]);
  793. symbolsearch.insert(l);
  794. end;
  795. procedure TAsmLibraryData.getaddrlabel(var l : tasmlabel);
  796. begin
  797. l:=tasmlabel.createlocal(nextlabelnr[alt_addr],alt_addr);
  798. inc(nextlabelnr[alt_addr]);
  799. symbolsearch.insert(l);
  800. end;
  801. end.