aggas.pas 71 KB

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