aggas.pas 71 KB

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