aggas.pas 87 KB

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