aggas.pas 69 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841
  1. {
  2. Copyright (c) 1998-2006 by the Free Pascal team
  3. This unit implements the generic part of the GNU assembler
  4. (v2.8 or later) writer
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. { Base unit for writing GNU assembler output.
  19. }
  20. unit aggas;
  21. {$i fpcdefs.inc}
  22. { $define DEBUG_AGGAS}
  23. interface
  24. uses
  25. globtype,globals,
  26. aasmbase,aasmtai,aasmdata,
  27. assemble;
  28. type
  29. TCPUInstrWriter = class;
  30. {# This is a derived class which is used to write
  31. GAS styled assembler.
  32. }
  33. { TGNUAssembler }
  34. TGNUAssembler=class(texternalassembler)
  35. protected
  36. function sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;virtual;
  37. function sectionattrs(atype:TAsmSectiontype):string;virtual;
  38. function sectionattrs_coff(atype:TAsmSectiontype):string;virtual;
  39. function sectionalignment_aix(atype:TAsmSectiontype;secalign: longint):string;
  40. procedure WriteSection(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder;secalign:longint);virtual;
  41. procedure WriteExtraHeader;virtual;
  42. procedure WriteExtraFooter;virtual;
  43. procedure WriteInstruction(hp: tai);
  44. procedure WriteWeakSymbolRef(s: tasmsymbol); virtual;
  45. procedure WriteAixStringConst(hp: tai_string);
  46. procedure WriteAixIntConst(hp: tai_const);
  47. procedure WriteUnalignedIntConst(hp: tai_const);
  48. procedure WriteDirectiveName(dir: TAsmDirective); virtual;
  49. public
  50. function MakeCmdLine: TCmdStr; override;
  51. procedure WriteTree(p:TAsmList);override;
  52. procedure WriteAsmList;override;
  53. destructor destroy; override;
  54. private
  55. setcount: longint;
  56. procedure WriteDecodedSleb128(a: int64);
  57. procedure WriteDecodedUleb128(a: qword);
  58. function NextSetLabel: string;
  59. protected
  60. InstrWriter: TCPUInstrWriter;
  61. end;
  62. {# This is the base class for writing instructions.
  63. The WriteInstruction() method must be overridden
  64. to write a single instruction to the assembler
  65. file.
  66. }
  67. TCPUInstrWriter = class
  68. constructor create(_owner: TGNUAssembler);
  69. procedure WriteInstruction(hp : tai); virtual; abstract;
  70. protected
  71. owner: TGNUAssembler;
  72. end;
  73. { TAppleGNUAssembler }
  74. TAppleGNUAssembler=class(TGNUAssembler)
  75. protected
  76. function sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;override;
  77. procedure WriteWeakSymbolRef(s: tasmsymbol); override;
  78. procedure WriteDirectiveName(dir: TAsmDirective); override;
  79. end;
  80. TAoutGNUAssembler=class(TGNUAssembler)
  81. function sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;override;
  82. end;
  83. implementation
  84. uses
  85. SysUtils,
  86. cutils,cfileutl,systems,
  87. fmodule,verbose,
  88. {$ifndef DISABLE_WIN64_SEH}
  89. itcpugas,
  90. {$endif DISABLE_WIN64_SEH}
  91. {$ifdef m68k}
  92. cpuinfo,aasmcpu,
  93. {$endif m68k}
  94. cpubase,objcasm;
  95. const
  96. line_length = 70;
  97. var
  98. symendcount : longint;
  99. {****************************************************************************}
  100. { Support routines }
  101. {****************************************************************************}
  102. const
  103. ait_const2str : array[aitconst_128bit..aitconst_64bit_unaligned] of string[20]=(
  104. #9'.fixme128'#9,#9'.quad'#9,#9'.long'#9,#9'.short'#9,#9'.byte'#9,
  105. #9'.sleb128'#9,#9'.uleb128'#9,
  106. #9'.rva'#9,#9'.secrel32'#9,#9'.quad'#9,#9'.long'#9,#9'.short'#9,#9'.short'#9,
  107. #9'.short'#9,#9'.long'#9,#9'.quad'#9
  108. );
  109. ait_solaris_const2str : array[aitconst_128bit..aitconst_64bit_unaligned] of string[20]=(
  110. #9'.fixme128'#9,#9'.8byte'#9,#9'.4byte'#9,#9'.2byte'#9,#9'.byte'#9,
  111. #9'.sleb128'#9,#9'.uleb128'#9,
  112. #9'.rva'#9,#9'.secrel32'#9,#9'.8byte'#9,#9'.4byte'#9,#9'.2byte'#9,#9'.2byte'#9,
  113. #9'.2byte'#9,#9'.4byte'#9,#9'.8byte'#9
  114. );
  115. ait_unaligned_consts = [aitconst_16bit_unaligned..aitconst_64bit_unaligned];
  116. { Sparc type of unaligned pseudo-instructions }
  117. use_ua_sparc_systems = [system_sparc_linux];
  118. ait_ua_sparc_const2str : array[aitconst_16bit_unaligned..aitconst_64bit_unaligned]
  119. of string[20]=(
  120. #9'.uahalf'#9,#9'.uaword'#9,#9'.uaxword'#9
  121. );
  122. { Generic unaligned pseudo-instructions, seems ELF specific }
  123. use_ua_elf_systems = [system_mipsel_linux,system_mipseb_linux,system_mipsel_android,system_mipsel_embedded,system_mipseb_embedded];
  124. ait_ua_elf_const2str : array[aitconst_16bit_unaligned..aitconst_64bit_unaligned]
  125. of string[20]=(
  126. #9'.2byte'#9,#9'.4byte'#9,#9'.8byte'#9
  127. );
  128. {****************************************************************************}
  129. { GNU Assembler writer }
  130. {****************************************************************************}
  131. destructor TGNUAssembler.Destroy;
  132. begin
  133. InstrWriter.free;
  134. inherited destroy;
  135. end;
  136. function TGNUAssembler.MakeCmdLine: TCmdStr;
  137. begin
  138. result := inherited MakeCmdLine;
  139. // MWE: disabled again. It generates dwarf info for the generated .s
  140. // files as well. This conflicts with the info we generate
  141. // if target_dbg.id = dbg_dwarf then
  142. // result := result + ' --gdwarf-2';
  143. end;
  144. function TGNUAssembler.NextSetLabel: string;
  145. begin
  146. inc(setcount);
  147. result := asminfo^.labelprefix+'$set$'+tostr(setcount);
  148. end;
  149. function is_smart_section(atype:TAsmSectiontype):boolean;
  150. begin
  151. { For bss we need to set some flags that are target dependent,
  152. it is easier to disable it for smartlinking. It doesn't take up
  153. filespace }
  154. result:=not(target_info.system in systems_darwin) and
  155. create_smartlink_sections and
  156. (atype<>sec_toc) and
  157. (atype<>sec_user) and
  158. { on embedded systems every byte counts, so smartlink bss too }
  159. ((atype<>sec_bss) or (target_info.system in systems_embedded));
  160. end;
  161. function TGNUAssembler.sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;
  162. const
  163. secnames : array[TAsmSectiontype] of string[length('__DATA, __datacoal_nt,coalesced')] = ('','',
  164. '.text',
  165. '.data',
  166. { why doesn't .rodata work? (FK) }
  167. { sometimes we have to create a data.rel.ro instead of .rodata, e.g. for }
  168. { vtables (and anything else containing relocations), otherwise those are }
  169. { not relocated properly on e.g. linux/ppc64. g++ generates there for a }
  170. { vtable for a class called Window: }
  171. { .section .data.rel.ro._ZTV6Window,"awG",@progbits,_ZTV6Window,comdat }
  172. { TODO: .data.ro not yet working}
  173. {$if defined(arm) or defined(powerpc)}
  174. '.rodata',
  175. {$else arm}
  176. '.data',
  177. {$endif arm}
  178. '.rodata',
  179. '.bss',
  180. '.threadvar',
  181. '.pdata',
  182. '', { stubs }
  183. '__DATA,__nl_symbol_ptr',
  184. '__DATA,__la_symbol_ptr',
  185. '__DATA,__mod_init_func',
  186. '__DATA,__mod_term_func',
  187. '.stab',
  188. '.stabstr',
  189. '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
  190. '.eh_frame',
  191. '.debug_frame','.debug_info','.debug_line','.debug_abbrev','.debug_aranges','.debug_ranges',
  192. '.fpc',
  193. '.toc',
  194. '.init',
  195. '.fini',
  196. '.objc_class',
  197. '.objc_meta_class',
  198. '.objc_cat_cls_meth',
  199. '.objc_cat_inst_meth',
  200. '.objc_protocol',
  201. '.objc_string_object',
  202. '.objc_cls_meth',
  203. '.objc_inst_meth',
  204. '.objc_cls_refs',
  205. '.objc_message_refs',
  206. '.objc_symbols',
  207. '.objc_category',
  208. '.objc_class_vars',
  209. '.objc_instance_vars',
  210. '.objc_module_info',
  211. '.objc_class_names',
  212. '.objc_meth_var_types',
  213. '.objc_meth_var_names',
  214. '.objc_selector_strs',
  215. '.objc_protocol_ext',
  216. '.objc_class_ext',
  217. '.objc_property',
  218. '.objc_image_info',
  219. '.objc_cstring_object',
  220. '.objc_sel_fixup',
  221. '__DATA,__objc_data',
  222. '__DATA,__objc_const',
  223. '.objc_superrefs',
  224. '__DATA, __datacoal_nt,coalesced',
  225. '.objc_classlist',
  226. '.objc_nlclasslist',
  227. '.objc_catlist',
  228. '.obcj_nlcatlist',
  229. '.objc_protolist',
  230. '.stack',
  231. '.heap'
  232. );
  233. secnames_pic : array[TAsmSectiontype] of string[length('__DATA, __datacoal_nt,coalesced')] = ('','',
  234. '.text',
  235. '.data.rel',
  236. '.data.rel',
  237. '.data.rel',
  238. '.bss',
  239. '.threadvar',
  240. '.pdata',
  241. '', { stubs }
  242. '__DATA,__nl_symbol_ptr',
  243. '__DATA,__la_symbol_ptr',
  244. '__DATA,__mod_init_func',
  245. '__DATA,__mod_term_func',
  246. '.stab',
  247. '.stabstr',
  248. '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
  249. '.eh_frame',
  250. '.debug_frame','.debug_info','.debug_line','.debug_abbrev','.debug_aranges','.debug_ranges',
  251. '.fpc',
  252. '.toc',
  253. '.init',
  254. '.fini',
  255. '.objc_class',
  256. '.objc_meta_class',
  257. '.objc_cat_cls_meth',
  258. '.objc_cat_inst_meth',
  259. '.objc_protocol',
  260. '.objc_string_object',
  261. '.objc_cls_meth',
  262. '.objc_inst_meth',
  263. '.objc_cls_refs',
  264. '.objc_message_refs',
  265. '.objc_symbols',
  266. '.objc_category',
  267. '.objc_class_vars',
  268. '.objc_instance_vars',
  269. '.objc_module_info',
  270. '.objc_class_names',
  271. '.objc_meth_var_types',
  272. '.objc_meth_var_names',
  273. '.objc_selector_strs',
  274. '.objc_protocol_ext',
  275. '.objc_class_ext',
  276. '.objc_property',
  277. '.objc_image_info',
  278. '.objc_cstring_object',
  279. '.objc_sel_fixup',
  280. '__DATA, __objc_data',
  281. '__DATA, __objc_const',
  282. '.objc_superrefs',
  283. '__DATA, __datacoal_nt,coalesced',
  284. '.objc_classlist',
  285. '.objc_nlclasslist',
  286. '.objc_catlist',
  287. '.obcj_nlcatlist',
  288. '.objc_protolist',
  289. '.stack',
  290. '.heap'
  291. );
  292. var
  293. sep : string[3];
  294. secname : string;
  295. begin
  296. if (cs_create_pic in current_settings.moduleswitches) and
  297. not(target_info.system in systems_darwin) then
  298. secname:=secnames_pic[atype]
  299. else
  300. secname:=secnames[atype];
  301. if (atype=sec_fpc) and (Copy(aname,1,3)='res') then
  302. begin
  303. result:=secname+'.'+aname;
  304. exit;
  305. end;
  306. if (atype=sec_threadvar) and
  307. (target_info.system in (systems_windows+systems_wince)) then
  308. secname:='.tls';
  309. { go32v2 stub only loads .text and .data sections, and allocates space for .bss.
  310. Thus, data which normally goes into .rodata and .rodata_norel sections must
  311. end up in .data section }
  312. if (atype in [sec_rodata,sec_rodata_norel]) and
  313. (target_info.system in [system_i386_go32v2,system_m68k_palmos]) then
  314. secname:='.data';
  315. { Windows correctly handles reallocations in readonly sections }
  316. if (atype=sec_rodata) and
  317. (target_info.system in systems_all_windows+systems_nativent-[system_i8086_win16]) then
  318. secname:='.rodata';
  319. { Use .rodata and .data.rel.ro for Android with PIC }
  320. if (target_info.system in systems_android) and (cs_create_pic in current_settings.moduleswitches) then
  321. begin
  322. case atype of
  323. sec_rodata:
  324. secname:='.data.rel.ro';
  325. sec_rodata_norel:
  326. secname:='.rodata';
  327. end;
  328. end;
  329. { section type user gives the user full controll on the section name }
  330. if atype=sec_user then
  331. secname:=aname;
  332. if is_smart_section(atype) and (aname<>'') then
  333. begin
  334. case aorder of
  335. secorder_begin :
  336. sep:='.b_';
  337. secorder_end :
  338. sep:='.z_';
  339. else
  340. sep:='.n_';
  341. end;
  342. result:=secname+sep+aname
  343. end
  344. else
  345. result:=secname;
  346. end;
  347. function TGNUAssembler.sectionattrs(atype:TAsmSectiontype):string;
  348. begin
  349. result:='';
  350. if (target_info.system in [system_i386_win32,system_x86_64_win64]) then
  351. begin
  352. result:=sectionattrs_coff(atype);
  353. end;
  354. end;
  355. function TGNUAssembler.sectionattrs_coff(atype:TAsmSectiontype):string;
  356. begin
  357. case atype of
  358. sec_code, sec_init, sec_fini, sec_stub:
  359. result:='x';
  360. { TODO: must be individual for each section }
  361. sec_user:
  362. result:='d';
  363. sec_data, sec_data_lazy, sec_data_nonlazy, sec_fpc,
  364. sec_idata2, sec_idata4, sec_idata5, sec_idata6, sec_idata7:
  365. result:='d';
  366. { TODO: these need a fix to become read-only }
  367. sec_rodata, sec_rodata_norel:
  368. result:='d';
  369. sec_bss:
  370. result:='b';
  371. { TODO: Somewhat questionable. FPC does not allow initialized threadvars,
  372. so no sense to mark it as containing data. But Windows allows it to
  373. contain data, and Linux even has .tdata and .tbss }
  374. sec_threadvar:
  375. result:='b';
  376. sec_pdata, sec_edata, sec_eh_frame, sec_toc:
  377. result:='r';
  378. sec_stab,sec_stabstr,
  379. sec_debug_frame,sec_debug_info,sec_debug_line,sec_debug_abbrev,sec_debug_aranges,sec_debug_ranges:
  380. result:='n';
  381. else
  382. result:=''; { defaults to data+load }
  383. end;
  384. end;
  385. function TGNUAssembler.sectionalignment_aix(atype:TAsmSectiontype;secalign: longint): string;
  386. var
  387. l: longint;
  388. begin
  389. if (secalign=0) or
  390. not(atype in [sec_code,sec_bss,sec_rodata_norel,sec_rodata,sec_data]) then
  391. begin
  392. result:='';
  393. exit;
  394. end;
  395. if not ispowerof2(secalign,l) then
  396. internalerror(2012022201);
  397. result:=tostr(l);
  398. end;
  399. procedure TGNUAssembler.WriteSection(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder;secalign:longint);
  400. var
  401. s : string;
  402. begin
  403. writer.AsmLn;
  404. case target_info.system of
  405. system_i386_OS2,
  406. system_i386_EMX: ;
  407. system_m68k_atari, { atari tos/mint GNU AS also doesn't seem to like .section (KB) }
  408. system_m68k_amiga: { amiga has old GNU AS (2.14), which blews up from .section (KB) }
  409. begin
  410. { ... but vasm is GAS compatible on amiga/atari, and supports named sections }
  411. if create_smartlink_sections then
  412. writer.AsmWrite('.section ');
  413. end;
  414. system_powerpc_darwin,
  415. system_i386_darwin,
  416. system_i386_iphonesim,
  417. system_powerpc64_darwin,
  418. system_x86_64_darwin,
  419. system_arm_darwin,
  420. system_aarch64_darwin,
  421. system_x86_64_iphonesim,
  422. system_powerpc_aix,
  423. system_powerpc64_aix:
  424. begin
  425. if (atype in [sec_stub]) then
  426. writer.AsmWrite('.section ');
  427. end
  428. else
  429. writer.AsmWrite('.section ');
  430. end;
  431. s:=sectionname(atype,aname,aorder);
  432. writer.AsmWrite(s);
  433. case atype of
  434. sec_fpc :
  435. if aname = 'resptrs' then
  436. writer.AsmWrite(', "a", @progbits');
  437. sec_stub :
  438. begin
  439. case target_info.system of
  440. { there are processor-independent shortcuts available }
  441. { for this, namely .symbol_stub and .picsymbol_stub, but }
  442. { they don't work and gcc doesn't use them either... }
  443. system_powerpc_darwin,
  444. system_powerpc64_darwin:
  445. if (cs_create_pic in current_settings.moduleswitches) then
  446. writer.AsmWriteln('__TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32')
  447. else
  448. writer.AsmWriteln('__TEXT,__symbol_stub1,symbol_stubs,pure_instructions,16');
  449. system_i386_darwin,
  450. system_i386_iphonesim:
  451. writer.AsmWriteln('__IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5');
  452. system_arm_darwin:
  453. if (cs_create_pic in current_settings.moduleswitches) then
  454. writer.AsmWriteln('__TEXT,__picsymbolstub4,symbol_stubs,none,16')
  455. else
  456. writer.AsmWriteln('__TEXT,__symbol_stub4,symbol_stubs,none,12')
  457. { darwin/(x86-64/AArch64) uses PC-based GOT addressing, no
  458. explicit symbol stubs }
  459. else
  460. internalerror(2006031101);
  461. end;
  462. end;
  463. else
  464. { GNU AS won't recognize '.text.n_something' section name as belonging
  465. to '.text' and assigns default attributes to it, which is not
  466. always correct. We have to fix it.
  467. TODO: This likely applies to all systems which smartlink without
  468. creating libraries }
  469. begin
  470. if is_smart_section(atype) and (aname<>'') then
  471. begin
  472. s:=sectionattrs(atype);
  473. if (s<>'') then
  474. writer.AsmWrite(',"'+s+'"');
  475. end;
  476. if target_info.system in systems_aix then
  477. begin
  478. s:=sectionalignment_aix(atype,secalign);
  479. if s<>'' then
  480. writer.AsmWrite(','+s);
  481. end;
  482. end;
  483. end;
  484. writer.AsmLn;
  485. LastSecType:=atype;
  486. end;
  487. procedure TGNUAssembler.WriteDecodedUleb128(a: qword);
  488. var
  489. i,len : longint;
  490. buf : array[0..63] of byte;
  491. begin
  492. len:=EncodeUleb128(a,buf);
  493. for i:=0 to len-1 do
  494. begin
  495. if (i > 0) then
  496. writer.AsmWrite(',');
  497. writer.AsmWrite(tostr(buf[i]));
  498. end;
  499. end;
  500. procedure TGNUAssembler.WriteDecodedSleb128(a: int64);
  501. var
  502. i,len : longint;
  503. buf : array[0..255] of byte;
  504. begin
  505. len:=EncodeSleb128(a,buf);
  506. for i:=0 to len-1 do
  507. begin
  508. if (i > 0) then
  509. writer.AsmWrite(',');
  510. writer.AsmWrite(tostr(buf[i]));
  511. end;
  512. end;
  513. procedure TGNUAssembler.WriteTree(p:TAsmList);
  514. function needsObject(hp : tai_symbol) : boolean;
  515. begin
  516. needsObject :=
  517. (
  518. assigned(hp.next) and
  519. (tai(hp.next).typ in [ait_const,ait_datablock,ait_realconst])
  520. ) or
  521. (hp.sym.typ in [AT_DATA,AT_METADATA]);
  522. end;
  523. procedure doalign(alignment: byte; use_op: boolean; fillop: byte; out last_align: longint;lasthp:tai);
  524. var
  525. i: longint;
  526. {$ifdef m68k}
  527. instr : string;
  528. {$endif}
  529. begin
  530. last_align:=alignment;
  531. if alignment>1 then
  532. begin
  533. if not(target_info.system in (systems_darwin+systems_aix)) then
  534. begin
  535. {$ifdef m68k}
  536. if not use_op and (lastsectype=sec_code) then
  537. begin
  538. if not ispowerof2(alignment,i) then
  539. internalerror(2014022201);
  540. { the Coldfire manual suggests the TBF instruction for
  541. alignments, but somehow QEMU does not interpret that
  542. correctly... }
  543. {if current_settings.cputype in cpu_coldfire then
  544. instr:='0x51fc'
  545. else}
  546. instr:='0x4e71';
  547. writer.AsmWrite(#9'.balignw '+tostr(alignment)+','+instr);
  548. end
  549. else
  550. begin
  551. {$endif m68k}
  552. writer.AsmWrite(#9'.balign '+tostr(alignment));
  553. if use_op then
  554. writer.AsmWrite(','+tostr(fillop))
  555. {$ifdef x86}
  556. { force NOP as alignment op code }
  557. else if (LastSecType=sec_code) and (asminfo^.id<>as_solaris_as) then
  558. writer.AsmWrite(',0x90');
  559. {$endif x86}
  560. {$ifdef m68k}
  561. end;
  562. {$endif m68k}
  563. end
  564. else
  565. begin
  566. { darwin and aix as only support .align }
  567. if not ispowerof2(alignment,i) then
  568. internalerror(2003010305);
  569. writer.AsmWrite(#9'.align '+tostr(i));
  570. last_align:=i;
  571. end;
  572. writer.AsmLn;
  573. end;
  574. end;
  575. var
  576. ch : char;
  577. lasthp,
  578. hp : tai;
  579. constdef : taiconst_type;
  580. s,t : string;
  581. i,pos,l : longint;
  582. InlineLevel : cardinal;
  583. last_align : longint;
  584. do_line : boolean;
  585. sepChar : char;
  586. replaceforbidden: boolean;
  587. begin
  588. if not assigned(p) then
  589. exit;
  590. replaceforbidden:=asminfo^.dollarsign<>'$';
  591. last_align := 2;
  592. InlineLevel:=0;
  593. { lineinfo is only needed for al_procedures (PFV) }
  594. do_line:=(cs_asm_source in current_settings.globalswitches) or
  595. ((cs_lineinfo in current_settings.moduleswitches)
  596. and (p=current_asmdata.asmlists[al_procedures]));
  597. lasthp:=nil;
  598. hp:=tai(p.first);
  599. while assigned(hp) do
  600. begin
  601. prefetch(pointer(hp.next)^);
  602. if not(hp.typ in SkipLineInfo) then
  603. begin
  604. current_filepos:=tailineinfo(hp).fileinfo;
  605. { no line info for inlined code }
  606. if do_line and (inlinelevel=0) then
  607. WriteSourceLine(hp as tailineinfo);
  608. end;
  609. case hp.typ of
  610. ait_comment :
  611. Begin
  612. writer.AsmWrite(asminfo^.comment);
  613. writer.AsmWritePChar(tai_comment(hp).str);
  614. writer.AsmLn;
  615. End;
  616. ait_regalloc :
  617. begin
  618. if (cs_asm_regalloc in current_settings.globalswitches) then
  619. begin
  620. writer.AsmWrite(#9+asminfo^.comment+'Register ');
  621. repeat
  622. writer.AsmWrite(std_regname(Tai_regalloc(hp).reg));
  623. if (hp.next=nil) or
  624. (tai(hp.next).typ<>ait_regalloc) or
  625. (tai_regalloc(hp.next).ratype<>tai_regalloc(hp).ratype) then
  626. break;
  627. hp:=tai(hp.next);
  628. writer.AsmWrite(',');
  629. until false;
  630. writer.AsmWrite(' ');
  631. writer.AsmWriteLn(regallocstr[tai_regalloc(hp).ratype]);
  632. end;
  633. end;
  634. ait_tempalloc :
  635. begin
  636. if (cs_asm_tempalloc in current_settings.globalswitches) then
  637. WriteTempalloc(tai_tempalloc(hp));
  638. end;
  639. ait_align :
  640. begin
  641. doalign(tai_align_abstract(hp).aligntype,tai_align_abstract(hp).use_op,tai_align_abstract(hp).fillop,last_align,lasthp);
  642. end;
  643. ait_section :
  644. begin
  645. if tai_section(hp).sectype<>sec_none then
  646. if replaceforbidden then
  647. WriteSection(tai_section(hp).sectype,ReplaceForbiddenAsmSymbolChars(tai_section(hp).name^),tai_section(hp).secorder,tai_section(hp).secalign)
  648. else
  649. WriteSection(tai_section(hp).sectype,tai_section(hp).name^,tai_section(hp).secorder,tai_section(hp).secalign)
  650. else
  651. begin
  652. {$ifdef EXTDEBUG}
  653. writer.AsmWrite(asminfo^.comment);
  654. writer.AsmWriteln(' sec_none');
  655. {$endif EXTDEBUG}
  656. end;
  657. end;
  658. ait_datablock :
  659. begin
  660. if (target_info.system in systems_darwin) then
  661. begin
  662. { On Mac OS X you can't have common symbols in a shared library
  663. since those are in the TEXT section and the text section is
  664. read-only in shared libraries (so it can be shared among different
  665. processes). The alternate code creates some kind of common symbols
  666. in the data segment.
  667. }
  668. if tai_datablock(hp).is_global then
  669. begin
  670. writer.AsmWrite('.globl ');
  671. writer.AsmWriteln(tai_datablock(hp).sym.name);
  672. writer.AsmWriteln('.data');
  673. writer.AsmWrite('.zerofill __DATA, __common, ');
  674. writer.AsmWrite(tai_datablock(hp).sym.name);
  675. writer.AsmWriteln(', '+tostr(tai_datablock(hp).size)+','+tostr(last_align));
  676. if not(LastSecType in [sec_data,sec_none]) then
  677. writesection(LastSecType,'',secorder_default,1 shl last_align);
  678. end
  679. else
  680. begin
  681. writer.AsmWrite(#9'.lcomm'#9);
  682. writer.AsmWrite(tai_datablock(hp).sym.name);
  683. writer.AsmWrite(','+tostr(tai_datablock(hp).size));
  684. writer.AsmWrite(','+tostr(last_align));
  685. writer.AsmLn;
  686. end;
  687. end
  688. else if target_info.system in systems_aix then
  689. begin
  690. if tai_datablock(hp).is_global then
  691. begin
  692. writer.AsmWrite(#9'.globl ');
  693. writer.AsmWriteln(ReplaceForbiddenAsmSymbolChars(tai_datablock(hp).sym.name));
  694. writer.AsmWrite(ReplaceForbiddenAsmSymbolChars(tai_datablock(hp).sym.name));
  695. writer.AsmWriteln(':');
  696. writer.AsmWrite(#9'.space ');
  697. writer.AsmWriteln(tostr(tai_datablock(hp).size));
  698. if not(LastSecType in [sec_data,sec_none]) then
  699. writesection(LastSecType,'',secorder_default,1 shl last_align);
  700. end
  701. else
  702. begin
  703. writer.AsmWrite(#9'.lcomm ');
  704. writer.AsmWrite(ReplaceForbiddenAsmSymbolChars(tai_datablock(hp).sym.name));
  705. writer.AsmWrite(',');
  706. writer.AsmWrite(tostr(tai_datablock(hp).size)+',');
  707. writer.AsmWrite('_data.bss_,');
  708. writer.AsmWriteln(tostr(last_align));
  709. end;
  710. end
  711. else
  712. begin
  713. {$ifdef USE_COMM_IN_BSS}
  714. if writingpackages then
  715. begin
  716. { The .comm is required for COMMON symbols. These are used
  717. in the shared library loading. All the symbols declared in
  718. the .so file need to resolve to the data allocated in the main
  719. program (PFV) }
  720. if tai_datablock(hp).is_global then
  721. begin
  722. writer.AsmWrite(#9'.comm'#9);
  723. if replaceforbidden then
  724. writer.AsmWrite(ReplaceForbiddenAsmSymbolChars(tai_datablock(hp).sym.name))
  725. else
  726. writer.AsmWrite(tai_datablock(hp).sym.name);
  727. writer.AsmWrite(','+tostr(tai_datablock(hp).size));
  728. writer.AsmWrite(','+tostr(last_align));
  729. writer.AsmLn;
  730. end
  731. else
  732. begin
  733. writer.AsmWrite(#9'.lcomm'#9);
  734. if replaceforbidden then
  735. writer.AsmWrite(ReplaceForbiddenAsmSymbolChars(tai_datablock(hp).sym.name));
  736. else
  737. writer.AsmWrite(tai_datablock(hp).sym.name);
  738. writer.AsmWrite(','+tostr(tai_datablock(hp).size));
  739. writer.AsmWrite(','+tostr(last_align));
  740. writer.AsmLn;
  741. end
  742. end
  743. else
  744. {$endif USE_COMM_IN_BSS}
  745. begin
  746. if Tai_datablock(hp).is_global then
  747. begin
  748. writer.AsmWrite(#9'.globl ');
  749. if replaceforbidden then
  750. writer.AsmWriteln(ReplaceForbiddenAsmSymbolChars(Tai_datablock(hp).sym.name))
  751. else
  752. writer.AsmWriteln(Tai_datablock(hp).sym.name);
  753. end;
  754. if ((target_info.system <> system_arm_linux) and (target_info.system <> system_arm_android)) then
  755. sepChar := '@'
  756. else
  757. sepChar := '%';
  758. if replaceforbidden then
  759. begin
  760. if (tf_needs_symbol_type in target_info.flags) then
  761. writer.AsmWriteln(#9'.type '+ReplaceForbiddenAsmSymbolChars(Tai_datablock(hp).sym.name)+','+sepChar+'object');
  762. if (tf_needs_symbol_size in target_info.flags) and (tai_datablock(hp).size > 0) then
  763. writer.AsmWriteln(#9'.size '+ReplaceForbiddenAsmSymbolChars(Tai_datablock(hp).sym.name)+','+tostr(Tai_datablock(hp).size));
  764. writer.AsmWrite(ReplaceForbiddenAsmSymbolChars(Tai_datablock(hp).sym.name))
  765. end
  766. else
  767. begin
  768. if (tf_needs_symbol_type in target_info.flags) then
  769. writer.AsmWriteln(#9'.type '+Tai_datablock(hp).sym.name+','+sepChar+'object');
  770. if (tf_needs_symbol_size in target_info.flags) and (tai_datablock(hp).size > 0) then
  771. writer.AsmWriteln(#9'.size '+Tai_datablock(hp).sym.name+','+tostr(Tai_datablock(hp).size));
  772. writer.AsmWrite(Tai_datablock(hp).sym.name);
  773. end;
  774. writer.AsmWriteln(':');
  775. writer.AsmWriteln(#9'.zero '+tostr(Tai_datablock(hp).size));
  776. end;
  777. end;
  778. end;
  779. ait_const:
  780. begin
  781. constdef:=tai_const(hp).consttype;
  782. case constdef of
  783. {$ifndef cpu64bitaddr}
  784. aitconst_128bit :
  785. begin
  786. internalerror(200404291);
  787. end;
  788. aitconst_64bit :
  789. begin
  790. if assigned(tai_const(hp).sym) then
  791. internalerror(200404292);
  792. if not(target_info.system in systems_aix) then
  793. begin
  794. writer.AsmWrite(ait_const2str[aitconst_32bit]);
  795. if target_info.endian = endian_little then
  796. begin
  797. writer.AsmWrite(tostr(longint(lo(tai_const(hp).value))));
  798. writer.AsmWrite(',');
  799. writer.AsmWrite(tostr(longint(hi(tai_const(hp).value))));
  800. end
  801. else
  802. begin
  803. writer.AsmWrite(tostr(longint(hi(tai_const(hp).value))));
  804. writer.AsmWrite(',');
  805. writer.AsmWrite(tostr(longint(lo(tai_const(hp).value))));
  806. end;
  807. end
  808. else
  809. WriteAixIntConst(tai_const(hp));
  810. writer.AsmLn;
  811. end;
  812. {$endif cpu64bitaddr}
  813. aitconst_got:
  814. begin
  815. if tai_const(hp).symofs<>0 then
  816. InternalError(2015091401); // No symbol offset is allowed for GOT.
  817. writer.AsmWrite(#9'.word'#9+tai_const(hp).sym.name+'(GOT)');
  818. writer.AsmLn;
  819. end;
  820. aitconst_gotoff_symbol:
  821. begin
  822. if (tai_const(hp).sym=nil) then
  823. InternalError(2014022601);
  824. case target_info.cpu of
  825. cpu_mipseb,cpu_mipsel:
  826. begin
  827. writer.AsmWrite(#9'.gpword'#9);
  828. writer.AsmWrite(tai_const(hp).sym.name);
  829. end;
  830. cpu_i386:
  831. begin
  832. writer.AsmWrite(ait_const2str[aitconst_32bit]);
  833. writer.AsmWrite(tai_const(hp).sym.name+'-_GLOBAL_OFFSET_TABLE_');
  834. end;
  835. else
  836. InternalError(2014022602);
  837. end;
  838. if (tai_const(hp).value<>0) then
  839. writer.AsmWrite(tostr_with_plus(tai_const(hp).value));
  840. writer.AsmLn;
  841. end;
  842. aitconst_uleb128bit,
  843. aitconst_sleb128bit,
  844. {$ifdef cpu64bitaddr}
  845. aitconst_128bit,
  846. aitconst_64bit,
  847. {$endif cpu64bitaddr}
  848. aitconst_32bit,
  849. aitconst_16bit,
  850. aitconst_8bit,
  851. aitconst_rva_symbol,
  852. aitconst_secrel32_symbol,
  853. aitconst_darwin_dwarf_delta32,
  854. aitconst_darwin_dwarf_delta64,
  855. aitconst_half16bit,
  856. aitconst_gs,
  857. aitconst_16bit_unaligned,
  858. aitconst_32bit_unaligned,
  859. aitconst_64bit_unaligned:
  860. begin
  861. { the AIX assembler (and for compatibility, the GNU
  862. assembler when targeting AIX) automatically aligns
  863. .short/.long/.llong to a multiple of 2/4/8 bytes. We
  864. don't want that, since this may be data inside a packed
  865. record -> use .vbyte instead (byte stream of fixed
  866. length) }
  867. if (target_info.system in systems_aix) and
  868. (constdef in [aitconst_128bit,aitconst_64bit,aitconst_32bit,aitconst_16bit]) and
  869. not assigned(tai_const(hp).sym) then
  870. begin
  871. WriteAixIntConst(tai_const(hp));
  872. end
  873. else if (target_info.system in systems_darwin) and
  874. (constdef in [aitconst_uleb128bit,aitconst_sleb128bit]) then
  875. begin
  876. writer.AsmWrite(ait_const2str[aitconst_8bit]);
  877. case tai_const(hp).consttype of
  878. aitconst_uleb128bit:
  879. WriteDecodedUleb128(qword(tai_const(hp).value));
  880. aitconst_sleb128bit:
  881. WriteDecodedSleb128(int64(tai_const(hp).value));
  882. end
  883. end
  884. else
  885. begin
  886. if (constdef in ait_unaligned_consts) and
  887. (target_info.system in use_ua_sparc_systems) then
  888. writer.AsmWrite(ait_ua_sparc_const2str[constdef])
  889. else if (constdef in ait_unaligned_consts) and
  890. (target_info.system in use_ua_elf_systems) then
  891. writer.AsmWrite(ait_ua_elf_const2str[constdef])
  892. { we can also have unaligned pointers in packed record
  893. constants, which don't get translated into
  894. unaligned tai -> always use vbyte }
  895. else if target_info.system in systems_aix then
  896. writer.AsmWrite(#9'.vbyte'#9+tostr(tai_const(hp).size)+',')
  897. else if (asminfo^.id=as_solaris_as) then
  898. writer.AsmWrite(ait_solaris_const2str[constdef])
  899. else
  900. writer.AsmWrite(ait_const2str[constdef]);
  901. l:=0;
  902. t := '';
  903. repeat
  904. if assigned(tai_const(hp).sym) then
  905. begin
  906. if assigned(tai_const(hp).endsym) then
  907. begin
  908. if (constdef in [aitconst_darwin_dwarf_delta32,aitconst_darwin_dwarf_delta64]) then
  909. begin
  910. s := NextSetLabel;
  911. t := #9'.set '+s+','+tai_const(hp).endsym.name+'-'+tai_const(hp).sym.name;
  912. end
  913. else
  914. s:=tai_const(hp).endsym.name+'-'+tai_const(hp).sym.name
  915. end
  916. else
  917. s:=tai_const(hp).sym.name;
  918. if replaceforbidden then
  919. s:=ReplaceForbiddenAsmSymbolChars(s);
  920. if tai_const(hp).value<>0 then
  921. s:=s+tostr_with_plus(tai_const(hp).value);
  922. end
  923. else
  924. {$ifdef cpu64bitaddr}
  925. s:=tostr(tai_const(hp).value);
  926. {$else cpu64bitaddr}
  927. { 64 bit constants are already handled above in this case }
  928. s:=tostr(longint(tai_const(hp).value));
  929. {$endif cpu64bitaddr}
  930. if constdef = aitconst_half16bit then
  931. s:='('+s+')/2';
  932. if constdef = aitconst_gs then
  933. s:='gs('+s+')';
  934. writer.AsmWrite(s);
  935. inc(l,length(s));
  936. { Values with symbols are written on a single line to improve
  937. reading of the .s file (PFV) }
  938. if assigned(tai_const(hp).sym) or
  939. not(LastSecType in [sec_data,sec_rodata,sec_rodata_norel]) or
  940. (l>line_length) or
  941. (hp.next=nil) or
  942. (tai(hp.next).typ<>ait_const) or
  943. (tai_const(hp.next).consttype<>constdef) or
  944. assigned(tai_const(hp.next).sym) then
  945. break;
  946. hp:=tai(hp.next);
  947. writer.AsmWrite(',');
  948. until false;
  949. if (t <> '') then
  950. begin
  951. writer.AsmLn;
  952. writer.AsmWrite(t);
  953. end;
  954. end;
  955. writer.AsmLn;
  956. end;
  957. else
  958. internalerror(200704251);
  959. end;
  960. end;
  961. ait_realconst :
  962. begin
  963. WriteRealConstAsBytes(tai_realconst(hp),#9'.byte'#9,do_line);
  964. end;
  965. ait_string :
  966. begin
  967. pos:=0;
  968. if not(target_info.system in systems_aix) then
  969. begin
  970. for i:=1 to tai_string(hp).len do
  971. begin
  972. if pos=0 then
  973. begin
  974. writer.AsmWrite(#9'.ascii'#9'"');
  975. pos:=20;
  976. end;
  977. ch:=tai_string(hp).str[i-1];
  978. case ch of
  979. #0, {This can't be done by range, because a bug in FPC}
  980. #1..#31,
  981. #128..#255 : s:='\'+tostr(ord(ch) shr 6)+tostr((ord(ch) and 63) shr 3)+tostr(ord(ch) and 7);
  982. '"' : s:='\"';
  983. '\' : s:='\\';
  984. else
  985. s:=ch;
  986. end;
  987. writer.AsmWrite(s);
  988. inc(pos,length(s));
  989. if (pos>line_length) or (i=tai_string(hp).len) then
  990. begin
  991. writer.AsmWriteLn('"');
  992. pos:=0;
  993. end;
  994. end;
  995. end
  996. else
  997. WriteAixStringConst(tai_string(hp));
  998. end;
  999. ait_label :
  1000. begin
  1001. if (tai_label(hp).labsym.is_used) then
  1002. begin
  1003. if (tai_label(hp).labsym.bind=AB_PRIVATE_EXTERN) then
  1004. begin
  1005. writer.AsmWrite(#9'.private_extern ');
  1006. writer.AsmWriteln(tai_label(hp).labsym.name);
  1007. end;
  1008. if tai_label(hp).labsym.bind in [AB_GLOBAL,AB_PRIVATE_EXTERN] then
  1009. begin
  1010. {$ifdef arm}
  1011. { do no change arm mode accidently, .globl seems to reset the mode }
  1012. if GenerateThumbCode or GenerateThumb2Code then
  1013. writer.AsmWriteln(#9'.thumb_func'#9);
  1014. {$endif arm}
  1015. writer.AsmWrite('.globl'#9);
  1016. if replaceforbidden then
  1017. writer.AsmWriteLn(ReplaceForbiddenAsmSymbolChars(tai_label(hp).labsym.name))
  1018. else
  1019. writer.AsmWriteLn(tai_label(hp).labsym.name);
  1020. end;
  1021. if replaceforbidden then
  1022. writer.AsmWrite(ReplaceForbiddenAsmSymbolChars(tai_label(hp).labsym.name))
  1023. else
  1024. writer.AsmWrite(tai_label(hp).labsym.name);
  1025. writer.AsmWriteLn(':');
  1026. end;
  1027. end;
  1028. ait_symbol :
  1029. begin
  1030. if (tai_symbol(hp).sym.bind=AB_PRIVATE_EXTERN) then
  1031. begin
  1032. writer.AsmWrite(#9'.private_extern ');
  1033. if replaceforbidden then
  1034. writer.AsmWriteln(ReplaceForbiddenAsmSymbolChars(tai_symbol(hp).sym.name))
  1035. else
  1036. writer.AsmWriteln(tai_symbol(hp).sym.name);
  1037. end;
  1038. if (target_info.system=system_powerpc64_linux) and
  1039. (tai_symbol(hp).sym.typ=AT_FUNCTION) and
  1040. (cs_profile in current_settings.moduleswitches) then
  1041. writer.AsmWriteLn('.globl _mcount');
  1042. if tai_symbol(hp).is_global then
  1043. begin
  1044. writer.AsmWrite('.globl'#9);
  1045. if replaceforbidden then
  1046. writer.AsmWriteln(ReplaceForbiddenAsmSymbolChars(tai_symbol(hp).sym.name))
  1047. else
  1048. writer.AsmWriteln(tai_symbol(hp).sym.name);
  1049. end;
  1050. if (target_info.system=system_powerpc64_linux) and
  1051. use_dotted_functions and
  1052. (tai_symbol(hp).sym.typ=AT_FUNCTION) then
  1053. begin
  1054. writer.AsmWriteLn('.section ".opd", "aw"');
  1055. writer.AsmWriteLn('.align 3');
  1056. writer.AsmWriteLn(tai_symbol(hp).sym.name + ':');
  1057. writer.AsmWriteLn('.quad .' + tai_symbol(hp).sym.name + ', .TOC.@tocbase, 0');
  1058. writer.AsmWriteLn('.previous');
  1059. writer.AsmWriteLn('.size ' + tai_symbol(hp).sym.name + ', 24');
  1060. if (tai_symbol(hp).is_global) then
  1061. writer.AsmWriteLn('.globl .' + tai_symbol(hp).sym.name);
  1062. writer.AsmWriteLn('.type .' + tai_symbol(hp).sym.name + ', @function');
  1063. { the dotted name is the name of the actual function entry }
  1064. writer.AsmWrite('.');
  1065. end
  1066. else if (target_info.system in systems_aix) and
  1067. (tai_symbol(hp).sym.typ = AT_FUNCTION) then
  1068. begin
  1069. if target_info.system=system_powerpc_aix then
  1070. begin
  1071. s:=#9'.long .';
  1072. ch:='2';
  1073. end
  1074. else
  1075. begin
  1076. s:=#9'.llong .';
  1077. ch:='3';
  1078. end;
  1079. writer.AsmWriteLn(#9'.csect '+ReplaceForbiddenAsmSymbolChars(tai_symbol(hp).sym.name)+'[DS],'+ch);
  1080. writer.AsmWriteLn(ReplaceForbiddenAsmSymbolChars(tai_symbol(hp).sym.name)+':');
  1081. writer.AsmWriteln(s+ReplaceForbiddenAsmSymbolChars(tai_symbol(hp).sym.name)+', TOC[tc0], 0');
  1082. writer.AsmWriteln(#9'.csect .text[PR]');
  1083. if (tai_symbol(hp).is_global) then
  1084. writer.AsmWriteLn('.globl .'+ReplaceForbiddenAsmSymbolChars(tai_symbol(hp).sym.name))
  1085. else
  1086. writer.AsmWriteLn('.lglobl .'+ReplaceForbiddenAsmSymbolChars(tai_symbol(hp).sym.name));
  1087. { the dotted name is the name of the actual function entry }
  1088. writer.AsmWrite('.');
  1089. end
  1090. else
  1091. begin
  1092. if ((target_info.system <> system_arm_linux) and (target_info.system <> system_arm_android)) then
  1093. sepChar := '@'
  1094. else
  1095. sepChar := '#';
  1096. if (tf_needs_symbol_type in target_info.flags) then
  1097. begin
  1098. writer.AsmWrite(#9'.type'#9 + tai_symbol(hp).sym.name);
  1099. if (needsObject(tai_symbol(hp))) then
  1100. writer.AsmWriteLn(',' + sepChar + 'object')
  1101. else
  1102. writer.AsmWriteLn(',' + sepChar + 'function');
  1103. end;
  1104. end;
  1105. if replaceforbidden then
  1106. if not(tai_symbol(hp).has_value) then
  1107. writer.AsmWriteLn(ReplaceForbiddenAsmSymbolChars(tai_symbol(hp).sym.name + ':'))
  1108. else
  1109. writer.AsmWriteLn(ReplaceForbiddenAsmSymbolChars(tai_symbol(hp).sym.name + '=' + tostr(tai_symbol(hp).value)))
  1110. else if not(tai_symbol(hp).has_value) then
  1111. writer.AsmWriteLn(tai_symbol(hp).sym.name + ':')
  1112. else
  1113. writer.AsmWriteLn(tai_symbol(hp).sym.name + '=' + tostr(tai_symbol(hp).value));
  1114. end;
  1115. ait_symbolpair:
  1116. begin
  1117. writer.AsmWrite(#9);
  1118. writer.AsmWrite(symbolpairkindstr[tai_symbolpair(hp).kind]);
  1119. writer.AsmWrite(' ');
  1120. if tai_symbolpair(hp).kind<>spk_localentry then
  1121. s:=', '
  1122. else
  1123. { the .localentry directive has to specify the size from the
  1124. start till here of the non-local entry code as second argument }
  1125. s:=', .-';
  1126. if replaceforbidden then
  1127. begin
  1128. { avoid string truncation }
  1129. writer.AsmWrite(ReplaceForbiddenAsmSymbolChars(tai_symbolpair(hp).sym^)+s);
  1130. writer.AsmWriteLn(ReplaceForbiddenAsmSymbolChars(tai_symbolpair(hp).value^));
  1131. end
  1132. else
  1133. begin
  1134. { avoid string truncation }
  1135. writer.AsmWrite(tai_symbolpair(hp).sym^+s);
  1136. writer.AsmWriteLn(tai_symbolpair(hp).value^);
  1137. end;
  1138. end;
  1139. ait_symbol_end :
  1140. begin
  1141. if tf_needs_symbol_size in target_info.flags then
  1142. begin
  1143. s:=asminfo^.labelprefix+'e'+tostr(symendcount);
  1144. inc(symendcount);
  1145. writer.AsmWriteLn(s+':');
  1146. writer.AsmWrite(#9'.size'#9);
  1147. if (target_info.system=system_powerpc64_linux) and
  1148. use_dotted_functions and
  1149. (tai_symbol_end(hp).sym.typ=AT_FUNCTION) then
  1150. writer.AsmWrite('.');
  1151. if replaceforbidden then
  1152. writer.AsmWrite(ReplaceForbiddenAsmSymbolChars(tai_symbol_end(hp).sym.name))
  1153. else
  1154. writer.AsmWrite(tai_symbol_end(hp).sym.name);
  1155. writer.AsmWrite(', '+s+' - ');
  1156. if (target_info.system=system_powerpc64_linux) and
  1157. use_dotted_functions and
  1158. (tai_symbol_end(hp).sym.typ=AT_FUNCTION) then
  1159. writer.AsmWrite('.');
  1160. if replaceforbidden then
  1161. writer.AsmWriteLn(ReplaceForbiddenAsmSymbolChars(tai_symbol_end(hp).sym.name))
  1162. else
  1163. writer.AsmWriteLn(tai_symbol_end(hp).sym.name);
  1164. end;
  1165. end;
  1166. ait_instruction :
  1167. begin
  1168. WriteInstruction(hp);
  1169. end;
  1170. ait_stab :
  1171. begin
  1172. if assigned(tai_stab(hp).str) then
  1173. begin
  1174. writer.AsmWrite(#9'.'+stabtypestr[tai_stab(hp).stabtype]+' ');
  1175. writer.AsmWritePChar(tai_stab(hp).str);
  1176. writer.AsmLn;
  1177. end;
  1178. end;
  1179. ait_force_line,
  1180. ait_function_name :
  1181. begin
  1182. {$ifdef DEBUG_AGGAS}
  1183. WriteStr(s,hp.typ);
  1184. writer.AsmWriteLn('# '+s);
  1185. {$endif DEBUG_AGGAS}
  1186. end;
  1187. ait_cutobject :
  1188. begin
  1189. {$ifdef DEBUG_AGGAS}
  1190. writer.AsmWriteLn('# ait_cutobject');
  1191. {$endif DEBUG_AGGAS}
  1192. if SmartAsm then
  1193. begin
  1194. { only reset buffer if nothing has changed }
  1195. if not(writer.ClearIfEmpty) then
  1196. begin
  1197. writer.AsmClose;
  1198. DoAssemble;
  1199. writer.AsmCreate(tai_cutobject(hp).place);
  1200. end;
  1201. { avoid empty files }
  1202. while assigned(hp.next) and (tai(hp.next).typ in [ait_cutobject,ait_section,ait_comment]) do
  1203. begin
  1204. if tai(hp.next).typ=ait_section then
  1205. LastSecType:=tai_section(hp.next).sectype;
  1206. hp:=tai(hp.next);
  1207. end;
  1208. if LastSecType<>sec_none then
  1209. WriteSection(LastSecType,'',secorder_default,last_align);
  1210. writer.MarkEmpty;
  1211. end;
  1212. end;
  1213. ait_marker :
  1214. begin
  1215. {$ifdef DEBUG_AGGAS}
  1216. WriteStr(s,tai_marker(hp).Kind);
  1217. writer.AsmWriteLn('# ait_marker, kind: '+s);
  1218. {$endif DEBUG_AGGAS}
  1219. if tai_marker(hp).kind=mark_NoLineInfoStart then
  1220. inc(InlineLevel)
  1221. else if tai_marker(hp).kind=mark_NoLineInfoEnd then
  1222. dec(InlineLevel);
  1223. end;
  1224. ait_directive :
  1225. begin
  1226. WriteDirectiveName(tai_directive(hp).directive);
  1227. if tai_directive(hp).name <>'' then
  1228. begin
  1229. if replaceforbidden then
  1230. writer.AsmWrite(ReplaceForbiddenAsmSymbolChars(tai_directive(hp).name))
  1231. else
  1232. writer.AsmWrite(tai_directive(hp).name);
  1233. end;
  1234. writer.AsmLn;
  1235. end;
  1236. ait_seh_directive :
  1237. begin
  1238. {$ifndef DISABLE_WIN64_SEH}
  1239. writer.AsmWrite(sehdirectivestr[tai_seh_directive(hp).kind]);
  1240. case tai_seh_directive(hp).datatype of
  1241. sd_none:;
  1242. sd_string:
  1243. begin
  1244. writer.AsmWrite(' '+tai_seh_directive(hp).data.name^);
  1245. if (tai_seh_directive(hp).data.flags and 1)<>0 then
  1246. writer.AsmWrite(',@except');
  1247. if (tai_seh_directive(hp).data.flags and 2)<>0 then
  1248. writer.AsmWrite(',@unwind');
  1249. end;
  1250. sd_reg:
  1251. writer.AsmWrite(' '+gas_regname(tai_seh_directive(hp).data.reg));
  1252. sd_offset:
  1253. writer.AsmWrite(' '+tostr(tai_seh_directive(hp).data.offset));
  1254. sd_regoffset:
  1255. writer.AsmWrite(' '+gas_regname(tai_seh_directive(hp).data.reg)+', '+
  1256. tostr(tai_seh_directive(hp).data.offset));
  1257. end;
  1258. writer.AsmLn;
  1259. {$endif DISABLE_WIN64_SEH}
  1260. end;
  1261. ait_varloc:
  1262. begin
  1263. if tai_varloc(hp).newlocationhi<>NR_NO then
  1264. writer.AsmWrite(strpnew('Var '+tai_varloc(hp).varsym.realname+' located in register '+
  1265. std_regname(tai_varloc(hp).newlocationhi)+':'+std_regname(tai_varloc(hp).newlocation)))
  1266. else
  1267. writer.AsmWrite(strpnew('Var '+tai_varloc(hp).varsym.realname+' located in register '+
  1268. std_regname(tai_varloc(hp).newlocation)));
  1269. writer.AsmLn;
  1270. end;
  1271. else
  1272. internalerror(2006012201);
  1273. end;
  1274. lasthp:=hp;
  1275. hp:=tai(hp.next);
  1276. end;
  1277. end;
  1278. procedure TGNUAssembler.WriteExtraHeader;
  1279. begin
  1280. end;
  1281. procedure TGNUAssembler.WriteExtraFooter;
  1282. begin
  1283. end;
  1284. procedure TGNUAssembler.WriteInstruction(hp: tai);
  1285. begin
  1286. InstrWriter.WriteInstruction(hp);
  1287. end;
  1288. procedure TGNUAssembler.WriteWeakSymbolRef(s: tasmsymbol);
  1289. begin
  1290. writer.AsmWriteLn(#9'.weak '+s.name);
  1291. end;
  1292. procedure TGNUAssembler.WriteAixStringConst(hp: tai_string);
  1293. type
  1294. tterminationkind = (term_none,term_string,term_nostring);
  1295. var
  1296. i: longint;
  1297. pos: longint;
  1298. s: string;
  1299. ch: char;
  1300. instring: boolean;
  1301. procedure newstatement(terminationkind: tterminationkind);
  1302. begin
  1303. case terminationkind of
  1304. term_none: ;
  1305. term_string:
  1306. writer.AsmWriteLn('"');
  1307. term_nostring:
  1308. writer.AsmLn;
  1309. end;
  1310. writer.AsmWrite(#9'.byte'#9);
  1311. pos:=20;
  1312. instring:=false;
  1313. end;
  1314. begin
  1315. pos:=0;
  1316. instring:=false;
  1317. for i:=1 to hp.len do
  1318. begin
  1319. if pos=0 then
  1320. newstatement(term_none);
  1321. ch:=hp.str[i-1];
  1322. case ch of
  1323. #0..#31,
  1324. #127..#255 :
  1325. begin
  1326. if instring then
  1327. newstatement(term_string);
  1328. if pos=20 then
  1329. s:=tostr(ord(ch))
  1330. else
  1331. s:=', '+tostr(ord(ch))
  1332. end;
  1333. '"' :
  1334. if instring then
  1335. s:='""'
  1336. else
  1337. begin
  1338. if pos<>20 then
  1339. newstatement(term_nostring);
  1340. s:='"""';
  1341. instring:=true;
  1342. end;
  1343. else
  1344. if not instring then
  1345. begin
  1346. if (pos<>20) then
  1347. newstatement(term_nostring);
  1348. s:='"'+ch;
  1349. instring:=true;
  1350. end
  1351. else
  1352. s:=ch;
  1353. end;
  1354. writer.AsmWrite(s);
  1355. inc(pos,length(s));
  1356. if (pos>line_length) or (i=tai_string(hp).len) then
  1357. begin
  1358. if instring then
  1359. writer.AsmWriteLn('"')
  1360. else
  1361. writer.AsmLn;
  1362. pos:=0;
  1363. end;
  1364. end;
  1365. end;
  1366. procedure TGNUAssembler.WriteAixIntConst(hp: tai_const);
  1367. var
  1368. pos, size: longint;
  1369. begin
  1370. { only big endian AIX supported for now }
  1371. if target_info.endian<>endian_big then
  1372. internalerror(2012010401);
  1373. { limitation: can only write 4 bytes at a time }
  1374. pos:=0;
  1375. size:=tai_const(hp).size;
  1376. while pos<(size-4) do
  1377. begin
  1378. writer.AsmWrite(#9'.vbyte'#9'4, ');
  1379. writer.AsmWriteln(tostr(longint(tai_const(hp).value shr ((size-pos-4)*8))));
  1380. inc(pos,4);
  1381. end;
  1382. writer.AsmWrite(#9'.vbyte'#9);
  1383. writer.AsmWrite(tostr(size-pos));
  1384. writer.AsmWrite(', ');
  1385. case size-pos of
  1386. 1: writer.AsmWrite(tostr(byte(tai_const(hp).value)));
  1387. 2: writer.AsmWrite(tostr(word(tai_const(hp).value)));
  1388. 4: writer.AsmWrite(tostr(longint(tai_const(hp).value)));
  1389. else
  1390. internalerror(2012010402);
  1391. end;
  1392. end;
  1393. procedure TGNUAssembler.WriteUnalignedIntConst(hp: tai_const);
  1394. var
  1395. pos, size: longint;
  1396. begin
  1397. size:=tai_const(hp).size;
  1398. writer.AsmWrite(#9'.byte'#9);
  1399. if target_info.endian=endian_big then
  1400. begin
  1401. pos:=size-1;
  1402. while pos>=0 do
  1403. begin
  1404. writer.AsmWrite(tostr((tai_const(hp).value shr (pos*8)) and $ff));
  1405. dec(pos);
  1406. if pos>=0 then
  1407. writer.AsmWrite(', ')
  1408. else
  1409. writer.AsmLn;
  1410. end;
  1411. end
  1412. else
  1413. begin
  1414. pos:=0;
  1415. while pos<size do
  1416. begin
  1417. writer.AsmWriteln(tostr((tai_const(hp).value shr (pos*8)) and $ff));
  1418. inc(pos);
  1419. if pos<=size then
  1420. writer.AsmWrite(', ')
  1421. else
  1422. writer.AsmLn;
  1423. end;
  1424. end;
  1425. writer.AsmLn;
  1426. end;
  1427. procedure TGNUAssembler.WriteDirectiveName(dir: TAsmDirective);
  1428. begin
  1429. { TODO: implement asd_cpu for GAS => usually .arch or .cpu, but the CPU
  1430. name has to be translated as well }
  1431. if dir=asd_cpu then
  1432. writer.AsmWrite(asminfo^.comment+' CPU ')
  1433. else
  1434. writer.AsmWrite('.'+directivestr[dir]+' ');
  1435. end;
  1436. procedure TGNUAssembler.WriteAsmList;
  1437. var
  1438. n : string;
  1439. hal : tasmlisttype;
  1440. i: longint;
  1441. begin
  1442. {$ifdef EXTDEBUG}
  1443. if current_module.mainsource<>'' then
  1444. Comment(V_Debug,'Start writing gas-styled assembler output for '+current_module.mainsource);
  1445. {$endif}
  1446. if current_module.mainsource<>'' then
  1447. n:=ExtractFileName(current_module.mainsource)
  1448. else
  1449. n:=InputFileName;
  1450. { gcc does not add it either for Darwin. Grep for
  1451. TARGET_ASM_FILE_START_FILE_DIRECTIVE in gcc/config/*.h
  1452. }
  1453. if not(target_info.system in systems_darwin) then
  1454. writer.AsmWriteLn(#9'.file "'+FixFileName(n)+'"');
  1455. WriteExtraHeader;
  1456. writer.MarkEmpty;
  1457. symendcount:=0;
  1458. for hal:=low(TasmlistType) to high(TasmlistType) do
  1459. begin
  1460. if not (current_asmdata.asmlists[hal].empty) then
  1461. begin
  1462. writer.AsmWriteLn(asminfo^.comment+'Begin asmlist '+AsmlistTypeStr[hal]);
  1463. writetree(current_asmdata.asmlists[hal]);
  1464. writer.AsmWriteLn(asminfo^.comment+'End asmlist '+AsmlistTypeStr[hal]);
  1465. end;
  1466. end;
  1467. { add weak symbol markers }
  1468. for i:=0 to current_asmdata.asmsymboldict.count-1 do
  1469. if (tasmsymbol(current_asmdata.asmsymboldict[i]).bind=AB_WEAK_EXTERNAL) then
  1470. WriteWeakSymbolRef(tasmsymbol(current_asmdata.asmsymboldict[i]));
  1471. if create_smartlink_sections and
  1472. (target_info.system in systems_darwin) then
  1473. writer.AsmWriteLn(#9'.subsections_via_symbols');
  1474. { "no executable stack" marker }
  1475. { TODO: used by OpenBSD/NetBSD as well? }
  1476. if (target_info.system in (systems_linux + systems_android + systems_freebsd + systems_dragonfly)) and
  1477. not(cs_executable_stack in current_settings.moduleswitches) then
  1478. begin
  1479. writer.AsmWriteLn('.section .note.GNU-stack,"",%progbits');
  1480. end;
  1481. writer.AsmLn;
  1482. WriteExtraFooter;
  1483. {$ifdef EXTDEBUG}
  1484. if current_module.mainsource<>'' then
  1485. Comment(V_Debug,'Done writing gas-styled assembler output for '+current_module.mainsource);
  1486. {$endif EXTDEBUG}
  1487. end;
  1488. {****************************************************************************}
  1489. { Apple/GNU Assembler writer }
  1490. {****************************************************************************}
  1491. function TAppleGNUAssembler.sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;
  1492. begin
  1493. if (target_info.system in systems_darwin) then
  1494. case atype of
  1495. sec_user:
  1496. begin
  1497. result:='.section '+aname;
  1498. exit;
  1499. end;
  1500. sec_bss:
  1501. { all bss (lcomm) symbols are automatically put in the right }
  1502. { place by using the lcomm assembler directive }
  1503. atype := sec_none;
  1504. sec_debug_frame,
  1505. sec_eh_frame:
  1506. begin
  1507. result := '.section __DWARF,__debug_info,regular,debug';
  1508. exit;
  1509. end;
  1510. sec_debug_line:
  1511. begin
  1512. result := '.section __DWARF,__debug_line,regular,debug';
  1513. exit;
  1514. end;
  1515. sec_debug_info:
  1516. begin
  1517. result := '.section __DWARF,__debug_info,regular,debug';
  1518. exit;
  1519. end;
  1520. sec_debug_abbrev:
  1521. begin
  1522. result := '.section __DWARF,__debug_abbrev,regular,debug';
  1523. exit;
  1524. end;
  1525. sec_debug_aranges:
  1526. begin
  1527. result := '.section __DWARF,__debug_aranges,regular,debug';
  1528. exit;
  1529. end;
  1530. sec_debug_ranges:
  1531. begin
  1532. result := '.section __DWARF,__debug_ranges,regular,debug';
  1533. exit;
  1534. end;
  1535. sec_rodata:
  1536. begin
  1537. result := '.const_data';
  1538. exit;
  1539. end;
  1540. sec_rodata_norel:
  1541. begin
  1542. result := '.const';
  1543. exit;
  1544. end;
  1545. sec_fpc:
  1546. begin
  1547. result := '.section __TEXT, .fpc, regular, no_dead_strip';
  1548. exit;
  1549. end;
  1550. sec_code:
  1551. begin
  1552. if (aname='fpc_geteipasebx') or
  1553. (aname='fpc_geteipasecx') then
  1554. begin
  1555. result:='.section __TEXT,__textcoal_nt,coalesced,pure_instructions'#10'.weak_definition '+aname+
  1556. #10'.private_extern '+aname;
  1557. exit;
  1558. end;
  1559. end;
  1560. sec_data_nonlazy:
  1561. begin
  1562. result:='.section __DATA, __nl_symbol_ptr,non_lazy_symbol_pointers';
  1563. exit;
  1564. end;
  1565. sec_data_lazy:
  1566. begin
  1567. result:='.section __DATA, __la_symbol_ptr,lazy_symbol_pointers';
  1568. exit;
  1569. end;
  1570. sec_init_func:
  1571. begin
  1572. result:='.section __DATA, __mod_init_func, mod_init_funcs';
  1573. exit;
  1574. end;
  1575. sec_term_func:
  1576. begin
  1577. result:='.section __DATA, __mod_term_func, mod_term_funcs';
  1578. exit;
  1579. end;
  1580. low(TObjCAsmSectionType)..high(TObjCAsmSectionType):
  1581. begin
  1582. result:='.section '+objc_section_name(atype);
  1583. exit
  1584. end;
  1585. end;
  1586. result := inherited sectionname(atype,aname,aorder);
  1587. end;
  1588. procedure TAppleGNUAssembler.WriteWeakSymbolRef(s: tasmsymbol);
  1589. begin
  1590. writer.AsmWriteLn(#9'.weak_reference '+s.name);
  1591. end;
  1592. procedure TAppleGNUAssembler.WriteDirectiveName(dir: TAsmDirective);
  1593. begin
  1594. case dir of
  1595. asd_weak_reference:
  1596. writer.AsmWrite('.weak_reference ');
  1597. asd_weak_definition:
  1598. writer.AsmWrite('.weak_definition ');
  1599. else
  1600. inherited;
  1601. end;
  1602. end;
  1603. {****************************************************************************}
  1604. { a.out/GNU Assembler writer }
  1605. {****************************************************************************}
  1606. function TAoutGNUAssembler.sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;
  1607. const
  1608. (* Translation table - replace unsupported section types with basic ones. *)
  1609. SecXTable: array[TAsmSectionType] of TAsmSectionType = (
  1610. sec_none,
  1611. sec_none,
  1612. sec_code,
  1613. sec_data,
  1614. sec_data (* sec_rodata *),
  1615. sec_data (* sec_rodata_norel *),
  1616. sec_bss,
  1617. sec_data (* sec_threadvar *),
  1618. { used for wince exception handling }
  1619. sec_code (* sec_pdata *),
  1620. { used for darwin import stubs }
  1621. sec_code (* sec_stub *),
  1622. sec_data,(* sec_data_nonlazy *)
  1623. sec_data,(* sec_data_lazy *)
  1624. sec_data,(* sec_init_func *)
  1625. sec_data,(* sec_term_func *)
  1626. { stabs }
  1627. sec_stab,sec_stabstr,
  1628. { win32 }
  1629. sec_data (* sec_idata2 *),
  1630. sec_data (* sec_idata4 *),
  1631. sec_data (* sec_idata5 *),
  1632. sec_data (* sec_idata6 *),
  1633. sec_data (* sec_idata7 *),
  1634. sec_data (* sec_edata *),
  1635. { C++ exception handling unwinding (uses dwarf) }
  1636. sec_eh_frame,
  1637. { dwarf }
  1638. sec_debug_frame,
  1639. sec_debug_info,
  1640. sec_debug_line,
  1641. sec_debug_abbrev,
  1642. sec_debug_aranges,
  1643. sec_debug_ranges,
  1644. { ELF resources (+ references to stabs debug information sections) }
  1645. sec_code (* sec_fpc *),
  1646. { Table of contents section }
  1647. sec_code (* sec_toc *),
  1648. sec_code (* sec_init *),
  1649. sec_code (* sec_fini *),
  1650. sec_none (* sec_objc_class *),
  1651. sec_none (* sec_objc_meta_class *),
  1652. sec_none (* sec_objc_cat_cls_meth *),
  1653. sec_none (* sec_objc_cat_inst_meth *),
  1654. sec_none (* sec_objc_protocol *),
  1655. sec_none (* sec_objc_string_object *),
  1656. sec_none (* sec_objc_cls_meth *),
  1657. sec_none (* sec_objc_inst_meth *),
  1658. sec_none (* sec_objc_cls_refs *),
  1659. sec_none (* sec_objc_message_refs *),
  1660. sec_none (* sec_objc_symbols *),
  1661. sec_none (* sec_objc_category *),
  1662. sec_none (* sec_objc_class_vars *),
  1663. sec_none (* sec_objc_instance_vars *),
  1664. sec_none (* sec_objc_module_info *),
  1665. sec_none (* sec_objc_class_names *),
  1666. sec_none (* sec_objc_meth_var_types *),
  1667. sec_none (* sec_objc_meth_var_names *),
  1668. sec_none (* sec_objc_selector_strs *),
  1669. sec_none (* sec_objc_protocol_ext *),
  1670. sec_none (* sec_objc_class_ext *),
  1671. sec_none (* sec_objc_property *),
  1672. sec_none (* sec_objc_image_info *),
  1673. sec_none (* sec_objc_cstring_object *),
  1674. sec_none (* sec_objc_sel_fixup *),
  1675. sec_none (* sec_objc_data *),
  1676. sec_none (* sec_objc_const *),
  1677. sec_none (* sec_objc_sup_refs *),
  1678. sec_none (* sec_data_coalesced *),
  1679. sec_none (* sec_objc_classlist *),
  1680. sec_none (* sec_objc_nlclasslist *),
  1681. sec_none (* sec_objc_catlist *),
  1682. sec_none (* sec_objc_nlcatlist *),
  1683. sec_none (* sec_objc_protlist *),
  1684. sec_none (* sec_stack *),
  1685. sec_none (* sec_heap *)
  1686. );
  1687. begin
  1688. Result := inherited SectionName (SecXTable [AType], AName, AOrder);
  1689. end;
  1690. {****************************************************************************}
  1691. { Abstract Instruction Writer }
  1692. {****************************************************************************}
  1693. constructor TCPUInstrWriter.create(_owner: TGNUAssembler);
  1694. begin
  1695. inherited create;
  1696. owner := _owner;
  1697. end;
  1698. end.