aggas.pas 77 KB

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