aggas.pas 87 KB

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