aasmdata.pas 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  1. {
  2. Copyright (c) 1998-2006 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 overridden for each assembler writer to actually write the data in these
  20. classes to an assembler file.
  21. }
  22. unit aasmdata;
  23. {$i fpcdefs.inc}
  24. interface
  25. uses
  26. cutils,cclasses,
  27. globtype,globals,systems,
  28. cpuinfo,cpubase,
  29. cgbase,cgutils,
  30. symtype,
  31. aasmbase,ogbase;
  32. type
  33. { Type of AsmLists. The order is important for the layout of the
  34. information in the .o file. The stabs for the types must be defined
  35. before they can be referenced and therefor they need to be written
  36. first (PFV) }
  37. TAsmListType=(
  38. al_start,
  39. al_stabs,
  40. al_procedures,
  41. al_globals,
  42. al_const,
  43. al_typedconsts,
  44. al_rotypedconsts,
  45. al_threadvars,
  46. al_imports,
  47. al_exports,
  48. al_resources,
  49. al_rtti,
  50. al_dwarf_frame,
  51. al_dwarf_info,
  52. al_dwarf_abbrev,
  53. al_dwarf_line,
  54. al_picdata,
  55. al_resourcestrings,
  56. { Objective-C related sections }
  57. al_objc_data,
  58. { keep pool data separate, so we can generate new pool entries
  59. while emitting other data }
  60. al_objc_pools,
  61. al_end
  62. );
  63. { Type of constant 'pools'. Currently contains only string types,
  64. but may be extended with reals, sets, etc. }
  65. TConstPoolType = (
  66. sp_invalid,
  67. sp_conststr,
  68. sp_shortstr,
  69. sp_longstr,
  70. sp_ansistr,
  71. sp_widestr,
  72. sp_unicodestr,
  73. sp_objcclassnamerefs,
  74. sp_varnamerefs,
  75. sp_objcclassnames,
  76. sp_objcvarnames,
  77. sp_objcvartypes,
  78. sp_objcprotocolrefs
  79. );
  80. const
  81. AsmListTypeStr : array[TAsmListType] of string[24] =(
  82. 'al_begin',
  83. 'al_stabs',
  84. 'al_procedures',
  85. 'al_globals',
  86. 'al_const',
  87. 'al_typedconsts',
  88. 'al_rotypedconsts',
  89. 'al_threadvars',
  90. 'al_imports',
  91. 'al_exports',
  92. 'al_resources',
  93. 'al_rtti',
  94. 'al_dwarf_frame',
  95. 'al_dwarf_info',
  96. 'al_dwarf_abbrev',
  97. 'al_dwarf_line',
  98. 'al_picdata',
  99. 'al_resourcestrings',
  100. 'al_objc_data',
  101. 'al_objc_pools',
  102. 'al_end'
  103. );
  104. type
  105. TAsmList = class(tlinkedlist)
  106. constructor create;
  107. function empty : boolean;
  108. function getlasttaifilepos : pfileposinfo;
  109. end;
  110. TAsmCFI=class
  111. public
  112. constructor create;virtual;
  113. destructor destroy;override;
  114. procedure generate_code(list:TAsmList);virtual;
  115. procedure start_frame(list:TAsmList);virtual;
  116. procedure end_frame(list:TAsmList);virtual;
  117. procedure cfa_offset(list:TAsmList;reg:tregister;ofs:longint);virtual;
  118. procedure cfa_restore(list:TAsmList;reg:tregister);virtual;
  119. procedure cfa_def_cfa_register(list:TAsmList;reg:tregister);virtual;
  120. procedure cfa_def_cfa_offset(list:TAsmList;ofs:longint);virtual;
  121. end;
  122. TAsmCFIClass=class of TAsmCFI;
  123. TAsmData = class
  124. private
  125. { Symbols }
  126. FAsmSymbolDict : TFPHashObjectList;
  127. FAltSymbolList : TFPObjectList;
  128. FNextAltNr : longint;
  129. FNextLabelNr : array[TAsmLabeltype] of longint;
  130. { Call Frame Information for stack unwinding}
  131. FAsmCFI : TAsmCFI;
  132. public
  133. name,
  134. realname : string[80];
  135. NextVTEntryNr : longint;
  136. { Assembler lists }
  137. AsmLists : array[TAsmListType] of TAsmList;
  138. CurrAsmList : TAsmList;
  139. WideInits : TLinkedList;
  140. { hash tables for reusing constant storage }
  141. ConstPools : array[TConstPoolType] of THashSet;
  142. constructor create(const n:string);
  143. destructor destroy;override;
  144. { asmsymbol }
  145. function DefineAsmSymbol(const s : string;_bind:TAsmSymBind;_typ:Tasmsymtype) : TAsmSymbol;
  146. function WeakRefAsmSymbol(const s : string) : TAsmSymbol;
  147. function RefAsmSymbol(const s : string) : TAsmSymbol;
  148. function GetAsmSymbol(const s : string) : TAsmSymbol;
  149. { create new assembler label }
  150. procedure getlabel(out l : TAsmLabel;alt:TAsmLabeltype);
  151. procedure getjumplabel(out l : TAsmLabel);
  152. procedure getglobaljumplabel(out l : TAsmLabel);
  153. procedure getaddrlabel(out l : TAsmLabel);
  154. procedure getdatalabel(out l : TAsmLabel);
  155. { generate an alternative (duplicate) symbol }
  156. procedure GenerateAltSymbol(p:TAsmSymbol);
  157. procedure ResetAltSymbols;
  158. property AsmSymbolDict:TFPHashObjectList read FAsmSymbolDict;
  159. property AsmCFI:TAsmCFI read FAsmCFI;
  160. end;
  161. TTCInitItem = class(TLinkedListItem)
  162. sym: tsym;
  163. offset: aint;
  164. datalabel: TAsmLabel;
  165. constructor Create(asym: tsym; aoffset: aint; alabel: TAsmLabel);
  166. end;
  167. var
  168. CAsmCFI : TAsmCFIClass;
  169. current_asmdata : TAsmData;
  170. implementation
  171. uses
  172. verbose,
  173. aasmtai;
  174. {$ifdef MEMDEBUG}
  175. var
  176. memasmsymbols,
  177. memasmcfi,
  178. memasmlists : TMemDebug;
  179. {$endif MEMDEBUG}
  180. {*****************************************************************************
  181. TAsmCFI
  182. *****************************************************************************}
  183. constructor TAsmCFI.create;
  184. begin
  185. end;
  186. destructor TAsmCFI.destroy;
  187. begin
  188. end;
  189. procedure TAsmCFI.generate_code(list:TAsmList);
  190. begin
  191. end;
  192. procedure TAsmCFI.start_frame(list:TAsmList);
  193. begin
  194. end;
  195. procedure TAsmCFI.end_frame(list:TAsmList);
  196. begin
  197. end;
  198. procedure TAsmCFI.cfa_offset(list:TAsmList;reg:tregister;ofs:longint);
  199. begin
  200. end;
  201. procedure TAsmCFI.cfa_restore(list:TAsmList;reg:tregister);
  202. begin
  203. end;
  204. procedure TAsmCFI.cfa_def_cfa_register(list:TAsmList;reg:tregister);
  205. begin
  206. end;
  207. procedure TAsmCFI.cfa_def_cfa_offset(list:TAsmList;ofs:longint);
  208. begin
  209. end;
  210. {*****************************************************************************
  211. TTCInitItem
  212. *****************************************************************************}
  213. constructor TTCInitItem.Create(asym: tsym; aoffset: aint; alabel: TAsmLabel);
  214. begin
  215. inherited Create;
  216. sym:=asym;
  217. offset:=aoffset;
  218. datalabel:=alabel;
  219. end;
  220. {*****************************************************************************
  221. TAsmList
  222. *****************************************************************************}
  223. constructor TAsmList.create;
  224. begin
  225. inherited create;
  226. { make sure the optimizer won't remove the first tai of this list}
  227. insert(tai_marker.create(mark_BlockStart));
  228. end;
  229. function TAsmList.empty : boolean;
  230. begin
  231. { there is always a mark_BlockStart available,
  232. see TAsmList.create }
  233. result:=(count<=1);
  234. end;
  235. function TAsmList.getlasttaifilepos : pfileposinfo;
  236. var
  237. hp : tlinkedlistitem;
  238. begin
  239. getlasttaifilepos := nil;
  240. if assigned(last) then
  241. begin
  242. { find the last file information record }
  243. if not (tai(last).typ in SkipLineInfo) then
  244. getlasttaifilepos:=@tailineinfo(last).fileinfo
  245. else
  246. { go through list backwards to find the first entry
  247. with line information
  248. }
  249. begin
  250. hp:=tai(last);
  251. while assigned(hp) and (tai(hp).typ in SkipLineInfo) do
  252. hp:=hp.Previous;
  253. { found entry }
  254. if assigned(hp) then
  255. getlasttaifilepos:=@tailineinfo(hp).fileinfo
  256. end;
  257. end;
  258. end;
  259. {****************************************************************************
  260. TAsmData
  261. ****************************************************************************}
  262. constructor TAsmData.create(const n:string);
  263. var
  264. alt : TAsmLabelType;
  265. hal : TAsmListType;
  266. begin
  267. inherited create;
  268. realname:=n;
  269. name:=upper(n);
  270. { symbols }
  271. FAsmSymbolDict:=TFPHashObjectList.create(true);
  272. FAltSymbolList:=TFPObjectList.Create(false);
  273. { labels }
  274. FNextAltNr:=1;
  275. for alt:=low(TAsmLabelType) to high(TAsmLabelType) do
  276. FNextLabelNr[alt]:=1;
  277. { AsmLists }
  278. CurrAsmList:=TAsmList.create;
  279. for hal:=low(TAsmListType) to high(TAsmListType) do
  280. AsmLists[hal]:=TAsmList.create;
  281. WideInits :=TLinkedList.create;
  282. { CFI }
  283. FAsmCFI:=CAsmCFI.Create;
  284. end;
  285. destructor TAsmData.destroy;
  286. var
  287. hal : TAsmListType;
  288. hp : TConstPoolType;
  289. begin
  290. { Symbols }
  291. {$ifdef MEMDEBUG}
  292. memasmsymbols.start;
  293. {$endif}
  294. FAltSymbolList.free;
  295. FAsmSymbolDict.free;
  296. {$ifdef MEMDEBUG}
  297. memasmsymbols.stop;
  298. {$endif}
  299. { CFI }
  300. {$ifdef MEMDEBUG}
  301. memasmcfi.start;
  302. {$endif}
  303. FAsmCFI.free;
  304. {$ifdef MEMDEBUG}
  305. memasmcfi.stop;
  306. {$endif}
  307. { Lists }
  308. {$ifdef MEMDEBUG}
  309. memasmlists.start;
  310. {$endif}
  311. WideInits.free;
  312. for hal:=low(TAsmListType) to high(TAsmListType) do
  313. AsmLists[hal].free;
  314. CurrAsmList.free;
  315. {$ifdef MEMDEBUG}
  316. memasmlists.stop;
  317. {$endif}
  318. for hp := low(TConstPoolType) to high(TConstPoolType) do
  319. ConstPools[hp].Free;
  320. end;
  321. function TAsmData.DefineAsmSymbol(const s : string;_bind:TAsmSymBind;_typ:Tasmsymtype) : TAsmSymbol;
  322. var
  323. hp : TAsmSymbol;
  324. begin
  325. hp:=TAsmSymbol(FAsmSymbolDict.Find(s));
  326. if assigned(hp) then
  327. begin
  328. { Redefine is allowed, but the types must be the same. The redefine
  329. is needed for Darwin where the labels are first allocated }
  330. if (hp.bind<>AB_EXTERNAL) then
  331. begin
  332. if (hp.bind<>_bind) and
  333. (hp.typ<>_typ) then
  334. internalerror(200603261);
  335. end;
  336. hp.typ:=_typ;
  337. hp.bind:=_bind;
  338. end
  339. else
  340. begin
  341. { Not found, insert it. }
  342. hp:=TAsmSymbol.create(AsmSymbolDict,s,_bind,_typ);
  343. end;
  344. result:=hp;
  345. end;
  346. function TAsmData.RefAsmSymbol(const s : string) : TAsmSymbol;
  347. begin
  348. result:=TAsmSymbol(FAsmSymbolDict.Find(s));
  349. if not assigned(result) then
  350. result:=TAsmSymbol.create(AsmSymbolDict,s,AB_EXTERNAL,AT_NONE)
  351. { one normal reference removes the "weak" character of a symbol }
  352. else if (result.bind=AB_WEAK_EXTERNAL) then
  353. result.bind:=AB_EXTERNAL;
  354. end;
  355. function TAsmData.WeakRefAsmSymbol(const s : string) : TAsmSymbol;
  356. begin
  357. result:=TAsmSymbol(FAsmSymbolDict.Find(s));
  358. if not assigned(result) then
  359. result:=TAsmSymbol.create(AsmSymbolDict,s,AB_WEAK_EXTERNAL,AT_NONE);
  360. end;
  361. function TAsmData.GetAsmSymbol(const s : string) : TAsmSymbol;
  362. begin
  363. result:=TAsmSymbol(FAsmSymbolDict.Find(s));
  364. end;
  365. procedure TAsmData.GenerateAltSymbol(p:TAsmSymbol);
  366. begin
  367. if not assigned(p.altsymbol) then
  368. begin
  369. p.altsymbol:=p.getaltcopy(AsmSymbolDict,FNextAltNr);
  370. FAltSymbolList.Add(p);
  371. end;
  372. end;
  373. procedure TAsmData.ResetAltSymbols;
  374. var
  375. i : longint;
  376. begin
  377. for i:=0 to FAltSymbolList.Count-1 do
  378. TAsmSymbol(FAltSymbolList[i]).altsymbol:=nil;
  379. FAltSymbolList.Clear;
  380. end;
  381. procedure TAsmData.getlabel(out l : TAsmLabel;alt:TAsmLabeltype);
  382. begin
  383. if (target_info.system in systems_linux) and
  384. (cs_link_smart in current_settings.globalswitches) and
  385. (alt = alt_dbgline) then
  386. l:=TAsmLabel.createglobal(AsmSymbolDict,name,FNextLabelNr[alt],alt)
  387. else
  388. l:=TAsmLabel.createlocal(AsmSymbolDict,FNextLabelNr[alt],alt);
  389. inc(FNextLabelNr[alt]);
  390. end;
  391. procedure TAsmData.getjumplabel(out l : TAsmLabel);
  392. begin
  393. l:=TAsmLabel.createlocal(AsmSymbolDict,FNextLabelNr[alt_jump],alt_jump);
  394. inc(FNextLabelNr[alt_jump]);
  395. end;
  396. procedure TAsmData.getglobaljumplabel(out l : TAsmLabel);
  397. begin
  398. l:=TAsmLabel.createglobal(AsmSymbolDict,name,FNextLabelNr[alt_jump],alt_jump);
  399. inc(FNextLabelNr[alt_jump]);
  400. end;
  401. procedure TAsmData.getdatalabel(out l : TAsmLabel);
  402. begin
  403. l:=TAsmLabel.createglobal(AsmSymbolDict,name,FNextLabelNr[alt_data],alt_data);
  404. inc(FNextLabelNr[alt_data]);
  405. end;
  406. procedure TAsmData.getaddrlabel(out l : TAsmLabel);
  407. begin
  408. l:=TAsmLabel.createlocal(AsmSymbolDict,FNextLabelNr[alt_addr],alt_addr);
  409. inc(FNextLabelNr[alt_addr]);
  410. end;
  411. initialization
  412. {$ifdef MEMDEBUG}
  413. memasmsymbols:=TMemDebug.create('AsmSymbols');
  414. memasmsymbols.stop;
  415. memasmcfi:=TMemDebug.create('AsmCFI');
  416. memasmcfi.stop;
  417. memasmlists:=TMemDebug.create('AsmLists');
  418. memasmlists.stop;
  419. {$endif MEMDEBUG}
  420. CAsmCFI:=TAsmCFI;
  421. finalization
  422. {$ifdef MEMDEBUG}
  423. memasmsymbols.free;
  424. memasmcfi.free;
  425. memasmlists.free;
  426. {$endif MEMDEBUG}
  427. end.