aggas.pas 76 KB

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