aggas.pas 78 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086
  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_win32,
  465. system_x86_64_win64,
  466. system_i386_wince,
  467. system_arm_wince,
  468. system_aarch64_win64:
  469. begin
  470. { according to the GNU AS guide AS for COFF does not support the
  471. progbits }
  472. writer.AsmWrite('.section ');
  473. usesectionflags:=true;
  474. end;
  475. system_powerpc_darwin,
  476. system_i386_darwin,
  477. system_i386_iphonesim,
  478. system_powerpc64_darwin,
  479. system_x86_64_darwin,
  480. system_arm_darwin,
  481. system_aarch64_darwin,
  482. system_x86_64_iphonesim,
  483. system_powerpc_aix,
  484. system_powerpc64_aix:
  485. begin
  486. if (atype in [sec_stub]) then
  487. writer.AsmWrite('.section ');
  488. end
  489. else
  490. begin
  491. writer.AsmWrite('.section ');
  492. { sectionname may rename those sections, so we do not write flags/progbits for them,
  493. the assembler will ignore them/spite out a warning anyways }
  494. if not(atype in [sec_data,sec_rodata,sec_rodata_norel]) then
  495. begin
  496. usesectionflags:=true;
  497. usesectionprogbits:=true;
  498. end;
  499. end
  500. end;
  501. s:=sectionname(atype,aname,aorder);
  502. writer.AsmWrite(s);
  503. { flags explicitly defined? }
  504. if (usesectionflags or usesectionprogbits) and
  505. ((secflags<>[]) or
  506. (secprogbits<>SPB_None)) then
  507. begin
  508. if usesectionflags then
  509. begin
  510. s:=',"'+sectionflags(secflags);
  511. writer.AsmWrite(s+'"');
  512. end;
  513. if usesectionprogbits then
  514. begin
  515. case secprogbits of
  516. SPB_PROGBITS:
  517. writer.AsmWrite(',%progbits');
  518. SPB_NOBITS:
  519. writer.AsmWrite(',%nobits');
  520. SPB_NOTE:
  521. writer.AsmWrite(',%note');
  522. SPB_None:
  523. ;
  524. else
  525. InternalError(2019100801);
  526. end;
  527. end;
  528. end
  529. else
  530. case atype of
  531. sec_fpc :
  532. if aname = 'resptrs' then
  533. writer.AsmWrite(', "a", @progbits');
  534. sec_stub :
  535. begin
  536. case target_info.system of
  537. { there are processor-independent shortcuts available }
  538. { for this, namely .symbol_stub and .picsymbol_stub, but }
  539. { they don't work and gcc doesn't use them either... }
  540. system_powerpc_darwin,
  541. system_powerpc64_darwin:
  542. if (cs_create_pic in current_settings.moduleswitches) then
  543. writer.AsmWriteln('__TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32')
  544. else
  545. writer.AsmWriteln('__TEXT,__symbol_stub1,symbol_stubs,pure_instructions,16');
  546. system_i386_darwin,
  547. system_i386_iphonesim:
  548. writer.AsmWriteln('__IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5');
  549. system_arm_darwin:
  550. if (cs_create_pic in current_settings.moduleswitches) then
  551. writer.AsmWriteln('__TEXT,__picsymbolstub4,symbol_stubs,none,16')
  552. else
  553. writer.AsmWriteln('__TEXT,__symbol_stub4,symbol_stubs,none,12')
  554. { darwin/(x86-64/AArch64) uses PC-based GOT addressing, no
  555. explicit symbol stubs }
  556. else
  557. internalerror(2006031101);
  558. end;
  559. end;
  560. else
  561. { GNU AS won't recognize '.text.n_something' section name as belonging
  562. to '.text' and assigns default attributes to it, which is not
  563. always correct. We have to fix it.
  564. TODO: This likely applies to all systems which smartlink without
  565. creating libraries }
  566. begin
  567. if is_smart_section(atype) and (aname<>'') then
  568. begin
  569. s:=sectionattrs(atype);
  570. if (s<>'') then
  571. writer.AsmWrite(',"'+s+'"');
  572. end;
  573. if target_info.system in systems_aix then
  574. begin
  575. s:=sectionalignment_aix(atype,secalign);
  576. if s<>'' then
  577. writer.AsmWrite(','+s);
  578. end;
  579. end;
  580. end;
  581. writer.AsmLn;
  582. LastSecType:=atype;
  583. end;
  584. procedure TGNUAssembler.WriteDecodedUleb128(a: qword);
  585. var
  586. i,len : longint;
  587. buf : array[0..63] of byte;
  588. begin
  589. len:=EncodeUleb128(a,buf,0);
  590. for i:=0 to len-1 do
  591. begin
  592. if (i > 0) then
  593. writer.AsmWrite(',');
  594. writer.AsmWrite(tostr(buf[i]));
  595. end;
  596. end;
  597. procedure TGNUAssembler.WriteCFI(hp: tai_cfi_base);
  598. begin
  599. writer.AsmWrite(cfi2str[hp.cfityp]);
  600. case hp.cfityp of
  601. cfi_startproc,
  602. cfi_endproc:
  603. ;
  604. cfi_undefined,
  605. cfi_restore,
  606. cfi_def_cfa_register:
  607. begin
  608. writer.AsmWrite(' ');
  609. writer.AsmWrite(gas_regname(tai_cfi_op_reg(hp).reg1));
  610. end;
  611. cfi_def_cfa_offset:
  612. begin
  613. writer.AsmWrite(' ');
  614. writer.AsmWrite(tostr(tai_cfi_op_val(hp).val1));
  615. end;
  616. cfi_offset:
  617. begin
  618. writer.AsmWrite(' ');
  619. writer.AsmWrite(gas_regname(tai_cfi_op_reg_val(hp).reg1));
  620. writer.AsmWrite(',');
  621. writer.AsmWrite(tostr(tai_cfi_op_reg_val(hp).val));
  622. end;
  623. else
  624. internalerror(2019030203);
  625. end;
  626. writer.AsmLn;
  627. end;
  628. procedure TGNUAssembler.WriteDecodedSleb128(a: int64);
  629. var
  630. i,len : longint;
  631. buf : array[0..255] of byte;
  632. begin
  633. len:=EncodeSleb128(a,buf,0);
  634. for i:=0 to len-1 do
  635. begin
  636. if (i > 0) then
  637. writer.AsmWrite(',');
  638. writer.AsmWrite(tostr(buf[i]));
  639. end;
  640. end;
  641. procedure TGNUAssembler.WriteTree(p:TAsmList);
  642. function needsObject(hp : tai_symbol) : boolean;
  643. begin
  644. needsObject :=
  645. (
  646. assigned(hp.next) and
  647. (tai(hp.next).typ in [ait_const,ait_datablock,ait_realconst])
  648. ) or
  649. (hp.sym.typ in [AT_DATA,AT_METADATA]);
  650. end;
  651. procedure doalign(alignment: byte; use_op: boolean; fillop: byte; maxbytes: byte; out last_align: longint;lasthp:tai);
  652. var
  653. i: longint;
  654. alignment64 : int64;
  655. {$ifdef m68k}
  656. instr : string;
  657. {$endif}
  658. begin
  659. last_align:=alignment;
  660. if alignment>1 then
  661. begin
  662. if not(target_info.system in (systems_darwin+systems_aix)) then
  663. begin
  664. {$ifdef m68k}
  665. if not use_op and (lastsectype=sec_code) then
  666. begin
  667. if not ispowerof2(alignment,i) then
  668. internalerror(2014022201);
  669. { the Coldfire manual suggests the TBF instruction for
  670. alignments, but somehow QEMU does not interpret that
  671. correctly... }
  672. {if current_settings.cputype in cpu_coldfire then
  673. instr:='0x51fc'
  674. else}
  675. instr:='0x4e71';
  676. writer.AsmWrite(#9'.balignw '+tostr(alignment)+','+instr);
  677. end
  678. else
  679. begin
  680. {$endif m68k}
  681. alignment64:=alignment;
  682. if (maxbytes<>alignment) and ispowerof2(alignment64,i) then
  683. begin
  684. if use_op then
  685. begin
  686. writer.AsmWrite(#9'.p2align '+tostr(i)+','+tostr(fillop)+','+tostr(maxbytes));
  687. writer.AsmLn;
  688. writer.AsmWrite(#9'.p2align '+tostr(i-1)+','+tostr(fillop));
  689. end
  690. else
  691. begin
  692. writer.AsmWrite(#9'.p2align '+tostr(i)+',,'+tostr(maxbytes));
  693. writer.AsmLn;
  694. writer.AsmWrite(#9'.p2align '+tostr(i-1));
  695. end
  696. end
  697. else
  698. begin
  699. writer.AsmWrite(#9'.balign '+tostr(alignment));
  700. if use_op then
  701. writer.AsmWrite(','+tostr(fillop))
  702. {$ifdef x86}
  703. { force NOP as alignment op code }
  704. else if (LastSecType=sec_code) and (asminfo^.id<>as_solaris_as) then
  705. writer.AsmWrite(',0x90');
  706. {$endif x86}
  707. end;
  708. {$ifdef m68k}
  709. end;
  710. {$endif m68k}
  711. end
  712. else
  713. begin
  714. { darwin and aix as only support .align }
  715. if not ispowerof2(alignment,i) then
  716. internalerror(2003010305);
  717. writer.AsmWrite(#9'.align '+tostr(i));
  718. last_align:=i;
  719. end;
  720. writer.AsmLn;
  721. end;
  722. end;
  723. var
  724. ch : char;
  725. lasthp,
  726. hp : tai;
  727. constdef : taiconst_type;
  728. s,t : string;
  729. i,pos,l : longint;
  730. InlineLevel : cardinal;
  731. last_align : longint;
  732. do_line : boolean;
  733. sepChar : char;
  734. replaceforbidden: boolean;
  735. begin
  736. if not assigned(p) then
  737. exit;
  738. replaceforbidden:=asminfo^.dollarsign<>'$';
  739. last_align := 2;
  740. InlineLevel:=0;
  741. { lineinfo is only needed for al_procedures (PFV) }
  742. do_line:=(cs_asm_source in current_settings.globalswitches) or
  743. ((cs_lineinfo in current_settings.moduleswitches)
  744. and (p=current_asmdata.asmlists[al_procedures]));
  745. lasthp:=nil;
  746. hp:=tai(p.first);
  747. while assigned(hp) do
  748. begin
  749. prefetch(pointer(hp.next)^);
  750. if not(hp.typ in SkipLineInfo) then
  751. begin
  752. current_filepos:=tailineinfo(hp).fileinfo;
  753. { no line info for inlined code }
  754. if do_line and (inlinelevel=0) then
  755. WriteSourceLine(hp as tailineinfo);
  756. end;
  757. case hp.typ of
  758. ait_comment :
  759. Begin
  760. writer.AsmWrite(asminfo^.comment);
  761. writer.AsmWritePChar(tai_comment(hp).str);
  762. writer.AsmLn;
  763. End;
  764. ait_regalloc :
  765. begin
  766. if (cs_asm_regalloc in current_settings.globalswitches) then
  767. begin
  768. writer.AsmWrite(#9+asminfo^.comment+'Register ');
  769. repeat
  770. writer.AsmWrite(std_regname(Tai_regalloc(hp).reg));
  771. if (hp.next=nil) or
  772. (tai(hp.next).typ<>ait_regalloc) or
  773. (tai_regalloc(hp.next).ratype<>tai_regalloc(hp).ratype) then
  774. break;
  775. hp:=tai(hp.next);
  776. writer.AsmWrite(',');
  777. until false;
  778. writer.AsmWrite(' ');
  779. writer.AsmWriteLn(regallocstr[tai_regalloc(hp).ratype]);
  780. end;
  781. end;
  782. ait_tempalloc :
  783. begin
  784. if (cs_asm_tempalloc in current_settings.globalswitches) then
  785. WriteTempalloc(tai_tempalloc(hp));
  786. end;
  787. ait_align :
  788. begin
  789. 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);
  790. end;
  791. ait_section :
  792. begin
  793. if tai_section(hp).sectype<>sec_none then
  794. if replaceforbidden then
  795. WriteSection(tai_section(hp).sectype,ApplyAsmSymbolRestrictions(tai_section(hp).name^),tai_section(hp).secorder,
  796. tai_section(hp).secalign,tai_section(hp).secflags,tai_section(hp).secprogbits)
  797. else
  798. WriteSection(tai_section(hp).sectype,tai_section(hp).name^,tai_section(hp).secorder,
  799. tai_section(hp).secalign,tai_section(hp).secflags,tai_section(hp).secprogbits)
  800. else
  801. begin
  802. {$ifdef EXTDEBUG}
  803. writer.AsmWrite(asminfo^.comment);
  804. writer.AsmWriteln(' sec_none');
  805. {$endif EXTDEBUG}
  806. end;
  807. end;
  808. ait_datablock :
  809. begin
  810. if (target_info.system in systems_darwin) then
  811. begin
  812. { On Mac OS X you can't have common symbols in a shared library
  813. since those are in the TEXT section and the text section is
  814. read-only in shared libraries (so it can be shared among different
  815. processes). The alternate code creates some kind of common symbols
  816. in the data segment.
  817. }
  818. if tai_datablock(hp).is_global then
  819. begin
  820. if tai_datablock(hp).sym.bind=AB_PRIVATE_EXTERN then
  821. WriteHiddenSymbol(tai_datablock(hp).sym);
  822. writer.AsmWrite('.globl ');
  823. writer.AsmWriteln(tai_datablock(hp).sym.name);
  824. writer.AsmWriteln('.data');
  825. writer.AsmWrite('.zerofill __DATA, __common, ');
  826. writer.AsmWrite(tai_datablock(hp).sym.name);
  827. writer.AsmWriteln(', '+tostr(tai_datablock(hp).size)+','+tostr(last_align));
  828. if not(LastSecType in [sec_data,sec_none]) then
  829. writesection(LastSecType,'',secorder_default,1 shl last_align);
  830. end
  831. else
  832. begin
  833. writer.AsmWrite(#9'.lcomm'#9);
  834. writer.AsmWrite(tai_datablock(hp).sym.name);
  835. writer.AsmWrite(','+tostr(tai_datablock(hp).size));
  836. writer.AsmWrite(','+tostr(last_align));
  837. writer.AsmLn;
  838. end;
  839. end
  840. else if target_info.system in systems_aix then
  841. begin
  842. if tai_datablock(hp).is_global then
  843. begin
  844. writer.AsmWrite(#9'.globl ');
  845. writer.AsmWriteln(ApplyAsmSymbolRestrictions(tai_datablock(hp).sym.name));
  846. writer.AsmWrite(ApplyAsmSymbolRestrictions(tai_datablock(hp).sym.name));
  847. writer.AsmWriteln(':');
  848. writer.AsmWrite(#9'.space ');
  849. writer.AsmWriteln(tostr(tai_datablock(hp).size));
  850. if not(LastSecType in [sec_data,sec_none]) then
  851. writesection(LastSecType,'',secorder_default,1 shl last_align);
  852. end
  853. else
  854. begin
  855. writer.AsmWrite(#9'.lcomm ');
  856. writer.AsmWrite(ApplyAsmSymbolRestrictions(tai_datablock(hp).sym.name));
  857. writer.AsmWrite(',');
  858. writer.AsmWrite(tostr(tai_datablock(hp).size)+',');
  859. writer.AsmWrite('_data.bss_,');
  860. writer.AsmWriteln(tostr(last_align));
  861. end;
  862. end
  863. else
  864. begin
  865. {$ifdef USE_COMM_IN_BSS}
  866. if writingpackages then
  867. begin
  868. { The .comm is required for COMMON symbols. These are used
  869. in the shared library loading. All the symbols declared in
  870. the .so file need to resolve to the data allocated in the main
  871. program (PFV) }
  872. if tai_datablock(hp).is_global then
  873. begin
  874. writer.AsmWrite(#9'.comm'#9);
  875. if replaceforbidden then
  876. writer.AsmWrite(ApplyAsmSymbolRestrictions(tai_datablock(hp).sym.name))
  877. else
  878. writer.AsmWrite(tai_datablock(hp).sym.name);
  879. writer.AsmWrite(','+tostr(tai_datablock(hp).size));
  880. writer.AsmWrite(','+tostr(last_align));
  881. writer.AsmLn;
  882. end
  883. else
  884. begin
  885. writer.AsmWrite(#9'.lcomm'#9);
  886. if replaceforbidden then
  887. writer.AsmWrite(ApplyAsmSymbolRestrictions(tai_datablock(hp).sym.name));
  888. else
  889. writer.AsmWrite(tai_datablock(hp).sym.name);
  890. writer.AsmWrite(','+tostr(tai_datablock(hp).size));
  891. writer.AsmWrite(','+tostr(last_align));
  892. writer.AsmLn;
  893. end
  894. end
  895. else
  896. {$endif USE_COMM_IN_BSS}
  897. begin
  898. if Tai_datablock(hp).is_global then
  899. begin
  900. if (tai_datablock(hp).sym.bind=AB_PRIVATE_EXTERN) then
  901. WriteHiddenSymbol(tai_datablock(hp).sym);
  902. writer.AsmWrite(#9'.globl ');
  903. if replaceforbidden then
  904. writer.AsmWriteln(ApplyAsmSymbolRestrictions(Tai_datablock(hp).sym.name))
  905. else
  906. writer.AsmWriteln(Tai_datablock(hp).sym.name);
  907. end;
  908. if ((target_info.system <> system_arm_linux) and (target_info.system <> system_arm_android)) then
  909. sepChar := '@'
  910. else
  911. sepChar := '%';
  912. if replaceforbidden then
  913. begin
  914. if (tf_needs_symbol_type in target_info.flags) then
  915. writer.AsmWriteln(#9'.type '+ApplyAsmSymbolRestrictions(Tai_datablock(hp).sym.name)+','+sepChar+'object');
  916. if (tf_needs_symbol_size in target_info.flags) and (tai_datablock(hp).size > 0) then
  917. writer.AsmWriteln(#9'.size '+ApplyAsmSymbolRestrictions(Tai_datablock(hp).sym.name)+','+tostr(Tai_datablock(hp).size));
  918. writer.AsmWrite(ApplyAsmSymbolRestrictions(Tai_datablock(hp).sym.name))
  919. end
  920. else
  921. begin
  922. if (tf_needs_symbol_type in target_info.flags) then
  923. writer.AsmWriteln(#9'.type '+Tai_datablock(hp).sym.name+','+sepChar+'object');
  924. if (tf_needs_symbol_size in target_info.flags) and (tai_datablock(hp).size > 0) then
  925. writer.AsmWriteln(#9'.size '+Tai_datablock(hp).sym.name+','+tostr(Tai_datablock(hp).size));
  926. writer.AsmWrite(Tai_datablock(hp).sym.name);
  927. end;
  928. writer.AsmWriteln(':');
  929. writer.AsmWriteln(#9'.zero '+tostr(Tai_datablock(hp).size));
  930. end;
  931. end;
  932. end;
  933. ait_const:
  934. begin
  935. constdef:=tai_const(hp).consttype;
  936. case constdef of
  937. {$ifndef cpu64bitaddr}
  938. aitconst_128bit :
  939. begin
  940. internalerror(200404291);
  941. end;
  942. aitconst_64bit :
  943. begin
  944. if assigned(tai_const(hp).sym) then
  945. internalerror(200404292);
  946. if not(target_info.system in systems_aix) then
  947. begin
  948. writer.AsmWrite(ait_const2str[aitconst_32bit]);
  949. if target_info.endian = endian_little then
  950. begin
  951. writer.AsmWrite(tostr(longint(lo(tai_const(hp).value))));
  952. writer.AsmWrite(',');
  953. writer.AsmWrite(tostr(longint(hi(tai_const(hp).value))));
  954. end
  955. else
  956. begin
  957. writer.AsmWrite(tostr(longint(hi(tai_const(hp).value))));
  958. writer.AsmWrite(',');
  959. writer.AsmWrite(tostr(longint(lo(tai_const(hp).value))));
  960. end;
  961. end
  962. else
  963. WriteAixIntConst(tai_const(hp));
  964. writer.AsmLn;
  965. end;
  966. aitconst_gottpoff:
  967. begin
  968. writer.AsmWrite(#9'.word'#9+tai_const(hp).sym.name+'(gottpoff)+(.-'+tai_const(hp).endsym.name+tostr_with_plus(tai_const(hp).symofs)+')');
  969. writer.Asmln;
  970. end;
  971. aitconst_tlsgd:
  972. begin
  973. writer.AsmWrite(#9'.word'#9+tai_const(hp).sym.name+'(tlsgd)+(.-'+tai_const(hp).endsym.name+tostr_with_plus(tai_const(hp).symofs)+')');
  974. writer.Asmln;
  975. end;
  976. aitconst_tlsdesc:
  977. begin
  978. writer.AsmWrite(#9'.word'#9+tai_const(hp).sym.name+'(tlsdesc)+(.-'+tai_const(hp).endsym.name+tostr_with_plus(tai_const(hp).symofs)+')');
  979. writer.Asmln;
  980. end;
  981. aitconst_tpoff:
  982. begin
  983. if assigned(tai_const(hp).endsym) or (tai_const(hp).symofs<>0) then
  984. Internalerror(2019092805);
  985. writer.AsmWrite(#9'.word'#9+tai_const(hp).sym.name+'(tpoff)');
  986. writer.Asmln;
  987. end;
  988. {$endif cpu64bitaddr}
  989. aitconst_dtpoff:
  990. begin
  991. {$ifdef arm}
  992. writer.AsmWrite(#9'.word'#9+tai_const(hp).sym.name+'(tlsldo)');
  993. writer.Asmln;
  994. {$endif arm}
  995. {$ifdef x86_64}
  996. writer.AsmWrite(#9'.long'#9+tai_const(hp).sym.name+'@dtpoff');
  997. writer.Asmln;
  998. {$endif x86_64}
  999. {$ifdef i386}
  1000. writer.AsmWrite(#9'.word'#9+tai_const(hp).sym.name+'@tdpoff');
  1001. writer.Asmln;
  1002. {$endif i386}
  1003. end;
  1004. aitconst_got:
  1005. begin
  1006. if tai_const(hp).symofs<>0 then
  1007. InternalError(2015091401); // No symbol offset is allowed for GOT.
  1008. writer.AsmWrite(#9'.word'#9+tai_const(hp).sym.name+'(GOT)');
  1009. writer.AsmLn;
  1010. end;
  1011. aitconst_gotoff_symbol:
  1012. begin
  1013. if (tai_const(hp).sym=nil) then
  1014. InternalError(2014022601);
  1015. case target_info.cpu of
  1016. cpu_mipseb,cpu_mipsel:
  1017. begin
  1018. writer.AsmWrite(#9'.gpword'#9);
  1019. writer.AsmWrite(tai_const(hp).sym.name);
  1020. end;
  1021. cpu_i386:
  1022. begin
  1023. writer.AsmWrite(ait_const2str[aitconst_32bit]);
  1024. writer.AsmWrite(tai_const(hp).sym.name+'-_GLOBAL_OFFSET_TABLE_');
  1025. end;
  1026. else
  1027. InternalError(2014022602);
  1028. end;
  1029. if (tai_const(hp).value<>0) then
  1030. writer.AsmWrite(tostr_with_plus(tai_const(hp).value));
  1031. writer.AsmLn;
  1032. end;
  1033. aitconst_uleb128bit,
  1034. aitconst_sleb128bit,
  1035. {$ifdef cpu64bitaddr}
  1036. aitconst_128bit,
  1037. aitconst_64bit,
  1038. {$endif cpu64bitaddr}
  1039. aitconst_32bit,
  1040. aitconst_16bit,
  1041. aitconst_8bit,
  1042. aitconst_rva_symbol,
  1043. aitconst_secrel32_symbol,
  1044. aitconst_darwin_dwarf_delta32,
  1045. aitconst_darwin_dwarf_delta64,
  1046. aitconst_half16bit,
  1047. aitconst_gs,
  1048. aitconst_16bit_unaligned,
  1049. aitconst_32bit_unaligned,
  1050. aitconst_64bit_unaligned:
  1051. begin
  1052. { the AIX assembler (and for compatibility, the GNU
  1053. assembler when targeting AIX) automatically aligns
  1054. .short/.long/.llong to a multiple of 2/4/8 bytes. We
  1055. don't want that, since this may be data inside a packed
  1056. record -> use .vbyte instead (byte stream of fixed
  1057. length) }
  1058. if (target_info.system in systems_aix) and
  1059. (constdef in [aitconst_128bit,aitconst_64bit,aitconst_32bit,aitconst_16bit]) and
  1060. not assigned(tai_const(hp).sym) then
  1061. begin
  1062. WriteAixIntConst(tai_const(hp));
  1063. end
  1064. else if (target_info.system in systems_darwin) and
  1065. (constdef in [aitconst_uleb128bit,aitconst_sleb128bit]) then
  1066. begin
  1067. writer.AsmWrite(ait_const2str[aitconst_8bit]);
  1068. case tai_const(hp).consttype of
  1069. aitconst_uleb128bit:
  1070. WriteDecodedUleb128(qword(tai_const(hp).value));
  1071. aitconst_sleb128bit:
  1072. WriteDecodedSleb128(int64(tai_const(hp).value));
  1073. else
  1074. ;
  1075. end
  1076. end
  1077. else
  1078. begin
  1079. if (constdef in ait_unaligned_consts) and
  1080. (target_info.system in use_ua_sparc_systems) then
  1081. writer.AsmWrite(ait_ua_sparc_const2str[constdef])
  1082. else if (target_info.system in use_ua_elf_systems) then
  1083. writer.AsmWrite(ait_ua_elf_const2str[constdef])
  1084. { we can also have unaligned pointers in packed record
  1085. constants, which don't get translated into
  1086. unaligned tai -> always use vbyte }
  1087. else if target_info.system in systems_aix then
  1088. writer.AsmWrite(#9'.vbyte'#9+tostr(tai_const(hp).size)+',')
  1089. else if (asminfo^.id=as_solaris_as) then
  1090. writer.AsmWrite(ait_solaris_const2str[constdef])
  1091. else
  1092. writer.AsmWrite(ait_const2str[constdef]);
  1093. l:=0;
  1094. t := '';
  1095. repeat
  1096. if assigned(tai_const(hp).sym) then
  1097. begin
  1098. if assigned(tai_const(hp).endsym) then
  1099. begin
  1100. if (constdef in [aitconst_darwin_dwarf_delta32,aitconst_darwin_dwarf_delta64]) then
  1101. begin
  1102. s := NextSetLabel;
  1103. t := #9'.set '+s+','+tai_const(hp).endsym.name+'-'+tai_const(hp).sym.name;
  1104. end
  1105. else
  1106. s:=tai_const(hp).endsym.name+'-'+tai_const(hp).sym.name
  1107. end
  1108. else
  1109. s:=tai_const(hp).sym.name;
  1110. if replaceforbidden then
  1111. s:=ApplyAsmSymbolRestrictions(s);
  1112. if tai_const(hp).value<>0 then
  1113. s:=s+tostr_with_plus(tai_const(hp).value);
  1114. end
  1115. else
  1116. {$ifdef cpu64bitaddr}
  1117. s:=tostr(tai_const(hp).value);
  1118. {$else cpu64bitaddr}
  1119. { 64 bit constants are already handled above in this case }
  1120. s:=tostr(longint(tai_const(hp).value));
  1121. {$endif cpu64bitaddr}
  1122. if constdef = aitconst_half16bit then
  1123. s:='('+s+')/2';
  1124. if constdef = aitconst_gs then
  1125. s:='gs('+s+')';
  1126. writer.AsmWrite(s);
  1127. inc(l,length(s));
  1128. { Values with symbols are written on a single line to improve
  1129. reading of the .s file (PFV) }
  1130. if assigned(tai_const(hp).sym) or
  1131. not(LastSecType in [sec_data,sec_rodata,sec_rodata_norel]) or
  1132. (l>line_length) or
  1133. (hp.next=nil) or
  1134. (tai(hp.next).typ<>ait_const) or
  1135. (tai_const(hp.next).consttype<>constdef) or
  1136. assigned(tai_const(hp.next).sym) then
  1137. break;
  1138. hp:=tai(hp.next);
  1139. writer.AsmWrite(',');
  1140. until false;
  1141. if (t <> '') then
  1142. begin
  1143. writer.AsmLn;
  1144. writer.AsmWrite(t);
  1145. end;
  1146. end;
  1147. writer.AsmLn;
  1148. end;
  1149. else
  1150. internalerror(200704251);
  1151. end;
  1152. end;
  1153. ait_realconst :
  1154. begin
  1155. WriteRealConstAsBytes(tai_realconst(hp),#9'.byte'#9,do_line);
  1156. end;
  1157. ait_string :
  1158. begin
  1159. pos:=0;
  1160. if not(target_info.system in systems_aix) then
  1161. begin
  1162. for i:=1 to tai_string(hp).len do
  1163. begin
  1164. if pos=0 then
  1165. begin
  1166. writer.AsmWrite(#9'.ascii'#9'"');
  1167. pos:=20;
  1168. end;
  1169. ch:=tai_string(hp).str[i-1];
  1170. case ch of
  1171. #0, {This can't be done by range, because a bug in FPC}
  1172. #1..#31,
  1173. #128..#255 : s:='\'+tostr(ord(ch) shr 6)+tostr((ord(ch) and 63) shr 3)+tostr(ord(ch) and 7);
  1174. '"' : s:='\"';
  1175. '\' : s:='\\';
  1176. else
  1177. s:=ch;
  1178. end;
  1179. writer.AsmWrite(s);
  1180. inc(pos,length(s));
  1181. if (pos>line_length) or (i=tai_string(hp).len) then
  1182. begin
  1183. writer.AsmWriteLn('"');
  1184. pos:=0;
  1185. end;
  1186. end;
  1187. end
  1188. else
  1189. WriteAixStringConst(tai_string(hp));
  1190. end;
  1191. ait_label :
  1192. begin
  1193. if (tai_label(hp).labsym.is_used) then
  1194. begin
  1195. if (tai_label(hp).labsym.bind=AB_PRIVATE_EXTERN) then
  1196. begin
  1197. writer.AsmWrite(#9'.private_extern ');
  1198. writer.AsmWriteln(tai_label(hp).labsym.name);
  1199. end;
  1200. if tai_label(hp).labsym.bind in [AB_GLOBAL,AB_PRIVATE_EXTERN] then
  1201. begin
  1202. {$ifdef arm}
  1203. { do no change arm mode accidently, .globl seems to reset the mode }
  1204. if GenerateThumbCode or GenerateThumb2Code then
  1205. writer.AsmWriteln(#9'.thumb_func'#9);
  1206. {$endif arm}
  1207. writer.AsmWrite('.globl'#9);
  1208. if replaceforbidden then
  1209. writer.AsmWriteLn(ApplyAsmSymbolRestrictions(tai_label(hp).labsym.name))
  1210. else
  1211. writer.AsmWriteLn(tai_label(hp).labsym.name);
  1212. end;
  1213. if replaceforbidden then
  1214. writer.AsmWrite(ApplyAsmSymbolRestrictions(tai_label(hp).labsym.name))
  1215. else
  1216. writer.AsmWrite(tai_label(hp).labsym.name);
  1217. writer.AsmWriteLn(':');
  1218. end;
  1219. end;
  1220. ait_symbol :
  1221. begin
  1222. if (target_info.system=system_powerpc64_linux) and
  1223. (tai_symbol(hp).sym.typ=AT_FUNCTION) and
  1224. (cs_profile in current_settings.moduleswitches) then
  1225. writer.AsmWriteLn('.globl _mcount');
  1226. if tai_symbol(hp).is_global then
  1227. begin
  1228. writer.AsmWrite('.globl'#9);
  1229. if replaceforbidden then
  1230. writer.AsmWriteln(ApplyAsmSymbolRestrictions(tai_symbol(hp).sym.name))
  1231. else
  1232. writer.AsmWriteln(tai_symbol(hp).sym.name);
  1233. if (tai_symbol(hp).sym.bind=AB_PRIVATE_EXTERN) then
  1234. WriteHiddenSymbol(tai_symbol(hp).sym);
  1235. end;
  1236. if (target_info.system=system_powerpc64_linux) and
  1237. use_dotted_functions and
  1238. (tai_symbol(hp).sym.typ=AT_FUNCTION) then
  1239. begin
  1240. writer.AsmWriteLn('.section ".opd", "aw"');
  1241. writer.AsmWriteLn('.align 3');
  1242. writer.AsmWriteLn(tai_symbol(hp).sym.name + ':');
  1243. writer.AsmWriteLn('.quad .' + tai_symbol(hp).sym.name + ', .TOC.@tocbase, 0');
  1244. writer.AsmWriteLn('.previous');
  1245. writer.AsmWriteLn('.size ' + tai_symbol(hp).sym.name + ', 24');
  1246. if (tai_symbol(hp).is_global) then
  1247. writer.AsmWriteLn('.globl .' + tai_symbol(hp).sym.name);
  1248. writer.AsmWriteLn('.type .' + tai_symbol(hp).sym.name + ', @function');
  1249. { the dotted name is the name of the actual function entry }
  1250. writer.AsmWrite('.');
  1251. end
  1252. else if (target_info.system in systems_aix) and
  1253. (tai_symbol(hp).sym.typ = AT_FUNCTION) then
  1254. begin
  1255. if target_info.system=system_powerpc_aix then
  1256. begin
  1257. s:=#9'.long .';
  1258. ch:='2';
  1259. end
  1260. else
  1261. begin
  1262. s:=#9'.llong .';
  1263. ch:='3';
  1264. end;
  1265. writer.AsmWriteLn(#9'.csect '+ApplyAsmSymbolRestrictions(tai_symbol(hp).sym.name)+'[DS],'+ch);
  1266. writer.AsmWriteLn(ApplyAsmSymbolRestrictions(tai_symbol(hp).sym.name)+':');
  1267. writer.AsmWriteln(s+ApplyAsmSymbolRestrictions(tai_symbol(hp).sym.name)+', TOC[tc0], 0');
  1268. writer.AsmWriteln(#9'.csect .text[PR]');
  1269. if (tai_symbol(hp).is_global) then
  1270. writer.AsmWriteLn('.globl .'+ApplyAsmSymbolRestrictions(tai_symbol(hp).sym.name))
  1271. else
  1272. writer.AsmWriteLn('.lglobl .'+ApplyAsmSymbolRestrictions(tai_symbol(hp).sym.name));
  1273. { the dotted name is the name of the actual function entry }
  1274. writer.AsmWrite('.');
  1275. end
  1276. else
  1277. begin
  1278. if ((target_info.system <> system_arm_linux) and (target_info.system <> system_arm_android)) then
  1279. sepChar := '@'
  1280. else
  1281. sepChar := '#';
  1282. if (tf_needs_symbol_type in target_info.flags) then
  1283. begin
  1284. writer.AsmWrite(#9'.type'#9 + tai_symbol(hp).sym.name);
  1285. if (needsObject(tai_symbol(hp))) then
  1286. writer.AsmWriteLn(',' + sepChar + 'object')
  1287. else
  1288. writer.AsmWriteLn(',' + sepChar + 'function');
  1289. end;
  1290. end;
  1291. if replaceforbidden then
  1292. if not(tai_symbol(hp).has_value) then
  1293. writer.AsmWriteLn(ApplyAsmSymbolRestrictions(tai_symbol(hp).sym.name + ':'))
  1294. else
  1295. writer.AsmWriteLn(ApplyAsmSymbolRestrictions(tai_symbol(hp).sym.name + '=' + tostr(tai_symbol(hp).value)))
  1296. else if not(tai_symbol(hp).has_value) then
  1297. writer.AsmWriteLn(tai_symbol(hp).sym.name + ':')
  1298. else
  1299. writer.AsmWriteLn(tai_symbol(hp).sym.name + '=' + tostr(tai_symbol(hp).value));
  1300. end;
  1301. ait_symbolpair:
  1302. begin
  1303. writer.AsmWrite(#9);
  1304. writer.AsmWrite(symbolpairkindstr[tai_symbolpair(hp).kind]);
  1305. writer.AsmWrite(' ');
  1306. if tai_symbolpair(hp).kind<>spk_localentry then
  1307. s:=', '
  1308. else
  1309. { the .localentry directive has to specify the size from the
  1310. start till here of the non-local entry code as second argument }
  1311. s:=', .-';
  1312. if replaceforbidden then
  1313. begin
  1314. { avoid string truncation }
  1315. writer.AsmWrite(ApplyAsmSymbolRestrictions(tai_symbolpair(hp).sym^));
  1316. writer.AsmWrite(s);
  1317. writer.AsmWriteLn(ApplyAsmSymbolRestrictions(tai_symbolpair(hp).value^));
  1318. if tai_symbolpair(hp).kind=spk_set_global then
  1319. begin
  1320. writer.AsmWrite(#9'.globl ');
  1321. writer.AsmWriteLn(ApplyAsmSymbolRestrictions(tai_symbolpair(hp).sym^));
  1322. end;
  1323. end
  1324. else
  1325. begin
  1326. { avoid string truncation }
  1327. writer.AsmWrite(tai_symbolpair(hp).sym^);
  1328. writer.AsmWrite(s);
  1329. writer.AsmWriteLn(tai_symbolpair(hp).value^);
  1330. if tai_symbolpair(hp).kind=spk_set_global then
  1331. begin
  1332. writer.AsmWrite(#9'.globl ');
  1333. writer.AsmWriteLn(tai_symbolpair(hp).sym^);
  1334. end;
  1335. end;
  1336. end;
  1337. ait_symbol_end :
  1338. begin
  1339. if tf_needs_symbol_size in target_info.flags then
  1340. begin
  1341. s:=asminfo^.labelprefix+'e'+tostr(symendcount);
  1342. inc(symendcount);
  1343. writer.AsmWriteLn(s+':');
  1344. writer.AsmWrite(#9'.size'#9);
  1345. if (target_info.system=system_powerpc64_linux) and
  1346. use_dotted_functions and
  1347. (tai_symbol_end(hp).sym.typ=AT_FUNCTION) then
  1348. writer.AsmWrite('.');
  1349. if replaceforbidden then
  1350. writer.AsmWrite(ApplyAsmSymbolRestrictions(tai_symbol_end(hp).sym.name))
  1351. else
  1352. writer.AsmWrite(tai_symbol_end(hp).sym.name);
  1353. writer.AsmWrite(', '+s+' - ');
  1354. if (target_info.system=system_powerpc64_linux) and
  1355. use_dotted_functions and
  1356. (tai_symbol_end(hp).sym.typ=AT_FUNCTION) then
  1357. writer.AsmWrite('.');
  1358. if replaceforbidden then
  1359. writer.AsmWriteLn(ApplyAsmSymbolRestrictions(tai_symbol_end(hp).sym.name))
  1360. else
  1361. writer.AsmWriteLn(tai_symbol_end(hp).sym.name);
  1362. end;
  1363. end;
  1364. ait_instruction :
  1365. begin
  1366. WriteInstruction(hp);
  1367. end;
  1368. ait_stab :
  1369. begin
  1370. if assigned(tai_stab(hp).str) then
  1371. begin
  1372. writer.AsmWrite(#9'.'+stabtypestr[tai_stab(hp).stabtype]+' ');
  1373. writer.AsmWritePChar(tai_stab(hp).str);
  1374. writer.AsmLn;
  1375. end;
  1376. end;
  1377. ait_force_line,
  1378. ait_function_name :
  1379. begin
  1380. {$ifdef DEBUG_AGGAS}
  1381. WriteStr(s,hp.typ);
  1382. writer.AsmWriteLn('# '+s);
  1383. {$endif DEBUG_AGGAS}
  1384. end;
  1385. ait_cutobject :
  1386. begin
  1387. {$ifdef DEBUG_AGGAS}
  1388. writer.AsmWriteLn('# ait_cutobject');
  1389. {$endif DEBUG_AGGAS}
  1390. if SmartAsm then
  1391. begin
  1392. { only reset buffer if nothing has changed }
  1393. if not(writer.ClearIfEmpty) then
  1394. begin
  1395. writer.AsmClose;
  1396. DoAssemble;
  1397. writer.AsmCreate(tai_cutobject(hp).place);
  1398. end;
  1399. { avoid empty files }
  1400. while assigned(hp.next) and (tai(hp.next).typ in [ait_cutobject,ait_section,ait_comment]) do
  1401. begin
  1402. if tai(hp.next).typ=ait_section then
  1403. LastSecType:=tai_section(hp.next).sectype;
  1404. hp:=tai(hp.next);
  1405. end;
  1406. if LastSecType<>sec_none then
  1407. WriteSection(LastSecType,'',secorder_default,last_align);
  1408. writer.MarkEmpty;
  1409. end;
  1410. end;
  1411. ait_marker :
  1412. begin
  1413. {$ifdef DEBUG_AGGAS}
  1414. WriteStr(s,tai_marker(hp).Kind);
  1415. writer.AsmWriteLn('# ait_marker, kind: '+s);
  1416. {$endif DEBUG_AGGAS}
  1417. if tai_marker(hp).kind=mark_NoLineInfoStart then
  1418. inc(InlineLevel)
  1419. else if tai_marker(hp).kind=mark_NoLineInfoEnd then
  1420. dec(InlineLevel);
  1421. end;
  1422. ait_directive :
  1423. begin
  1424. WriteDirectiveName(tai_directive(hp).directive);
  1425. if tai_directive(hp).name <>'' then
  1426. begin
  1427. if replaceforbidden then
  1428. writer.AsmWrite(ApplyAsmSymbolRestrictions(tai_directive(hp).name))
  1429. else
  1430. writer.AsmWrite(tai_directive(hp).name);
  1431. end;
  1432. writer.AsmLn;
  1433. end;
  1434. ait_seh_directive :
  1435. begin
  1436. {$ifndef DISABLE_WIN64_SEH}
  1437. writer.AsmWrite(sehdirectivestr[tai_seh_directive(hp).kind]);
  1438. case tai_seh_directive(hp).datatype of
  1439. sd_none:;
  1440. sd_string:
  1441. begin
  1442. writer.AsmWrite(' '+tai_seh_directive(hp).data.name^);
  1443. if (tai_seh_directive(hp).data.flags and 1)<>0 then
  1444. writer.AsmWrite(',@except');
  1445. if (tai_seh_directive(hp).data.flags and 2)<>0 then
  1446. writer.AsmWrite(',@unwind');
  1447. end;
  1448. sd_reg:
  1449. writer.AsmWrite(' '+gas_regname(tai_seh_directive(hp).data.reg));
  1450. sd_offset:
  1451. writer.AsmWrite(' '+tostr(tai_seh_directive(hp).data.offset));
  1452. sd_regoffset:
  1453. writer.AsmWrite(' '+gas_regname(tai_seh_directive(hp).data.reg)+', '+
  1454. tostr(tai_seh_directive(hp).data.offset));
  1455. end;
  1456. writer.AsmLn;
  1457. {$endif DISABLE_WIN64_SEH}
  1458. end;
  1459. ait_varloc:
  1460. begin
  1461. if tai_varloc(hp).newlocationhi<>NR_NO then
  1462. writer.AsmWrite(strpnew('Var '+tai_varloc(hp).varsym.realname+' located in register '+
  1463. std_regname(tai_varloc(hp).newlocationhi)+':'+std_regname(tai_varloc(hp).newlocation)))
  1464. else
  1465. writer.AsmWrite(strpnew('Var '+tai_varloc(hp).varsym.realname+' located in register '+
  1466. std_regname(tai_varloc(hp).newlocation)));
  1467. writer.AsmLn;
  1468. end;
  1469. ait_cfi:
  1470. begin
  1471. WriteCFI(tai_cfi_base(hp));
  1472. end;
  1473. ait_eabi_attribute:
  1474. begin
  1475. case tai_eabi_attribute(hp).eattr_typ of
  1476. eattrtype_dword:
  1477. writer.AsmWrite(#9'.eabi_attribute '+tostr(tai_eabi_attribute(hp).tag)+','+tostr(tai_eabi_attribute(hp).value));
  1478. eattrtype_ntbs:
  1479. writer.AsmWrite(#9'.eabi_attribute '+tostr(tai_eabi_attribute(hp).tag)+',"'+tai_eabi_attribute(hp).valuestr^+'"');
  1480. else
  1481. Internalerror(2019100601);
  1482. end;
  1483. writer.AsmLn;
  1484. end;
  1485. else
  1486. internalerror(2006012201);
  1487. end;
  1488. lasthp:=hp;
  1489. hp:=tai(hp.next);
  1490. end;
  1491. end;
  1492. procedure TGNUAssembler.WriteExtraHeader;
  1493. begin
  1494. end;
  1495. procedure TGNUAssembler.WriteExtraFooter;
  1496. begin
  1497. end;
  1498. procedure TGNUAssembler.WriteInstruction(hp: tai);
  1499. begin
  1500. InstrWriter.WriteInstruction(hp);
  1501. end;
  1502. procedure TGNUAssembler.WriteWeakSymbolRef(s: tasmsymbol);
  1503. begin
  1504. writer.AsmWrite(#9'.weak ');
  1505. if asminfo^.dollarsign='$' then
  1506. writer.AsmWriteLn(s.name)
  1507. else
  1508. writer.AsmWriteLn(ApplyAsmSymbolRestrictions(s.name))
  1509. end;
  1510. procedure TGNUAssembler.WriteHiddenSymbol(sym: TAsmSymbol);
  1511. begin
  1512. { on Windows/(PE)COFF, global symbols are hidden by default: global
  1513. symbols that are not explicitly exported from an executable/library,
  1514. become hidden }
  1515. if target_info.system in systems_windows then
  1516. exit;
  1517. if target_info.system in systems_darwin then
  1518. writer.AsmWrite(#9'.private_extern ')
  1519. else
  1520. writer.AsmWrite(#9'.hidden ');
  1521. if asminfo^.dollarsign='$' then
  1522. writer.AsmWriteLn(sym.name)
  1523. else
  1524. writer.AsmWriteLn(ApplyAsmSymbolRestrictions(sym.name))
  1525. end;
  1526. procedure TGNUAssembler.WriteAixStringConst(hp: tai_string);
  1527. type
  1528. tterminationkind = (term_none,term_string,term_nostring);
  1529. var
  1530. i: longint;
  1531. pos: longint;
  1532. s: string;
  1533. ch: char;
  1534. instring: boolean;
  1535. procedure newstatement(terminationkind: tterminationkind);
  1536. begin
  1537. case terminationkind of
  1538. term_none: ;
  1539. term_string:
  1540. writer.AsmWriteLn('"');
  1541. term_nostring:
  1542. writer.AsmLn;
  1543. end;
  1544. writer.AsmWrite(#9'.byte'#9);
  1545. pos:=20;
  1546. instring:=false;
  1547. end;
  1548. begin
  1549. pos:=0;
  1550. instring:=false;
  1551. for i:=1 to hp.len do
  1552. begin
  1553. if pos=0 then
  1554. newstatement(term_none);
  1555. ch:=hp.str[i-1];
  1556. case ch of
  1557. #0..#31,
  1558. #127..#255 :
  1559. begin
  1560. if instring then
  1561. newstatement(term_string);
  1562. if pos=20 then
  1563. s:=tostr(ord(ch))
  1564. else
  1565. s:=', '+tostr(ord(ch))
  1566. end;
  1567. '"' :
  1568. if instring then
  1569. s:='""'
  1570. else
  1571. begin
  1572. if pos<>20 then
  1573. newstatement(term_nostring);
  1574. s:='"""';
  1575. instring:=true;
  1576. end;
  1577. else
  1578. if not instring then
  1579. begin
  1580. if (pos<>20) then
  1581. newstatement(term_nostring);
  1582. s:='"'+ch;
  1583. instring:=true;
  1584. end
  1585. else
  1586. s:=ch;
  1587. end;
  1588. writer.AsmWrite(s);
  1589. inc(pos,length(s));
  1590. if (pos>line_length) or (i=tai_string(hp).len) then
  1591. begin
  1592. if instring then
  1593. writer.AsmWriteLn('"')
  1594. else
  1595. writer.AsmLn;
  1596. pos:=0;
  1597. end;
  1598. end;
  1599. end;
  1600. procedure TGNUAssembler.WriteAixIntConst(hp: tai_const);
  1601. var
  1602. pos, size: longint;
  1603. begin
  1604. { only big endian AIX supported for now }
  1605. if target_info.endian<>endian_big then
  1606. internalerror(2012010401);
  1607. { limitation: can only write 4 bytes at a time }
  1608. pos:=0;
  1609. size:=tai_const(hp).size;
  1610. while pos<(size-4) do
  1611. begin
  1612. writer.AsmWrite(#9'.vbyte'#9'4, ');
  1613. writer.AsmWriteln(tostr(longint(tai_const(hp).value shr ((size-pos-4)*8))));
  1614. inc(pos,4);
  1615. end;
  1616. writer.AsmWrite(#9'.vbyte'#9);
  1617. writer.AsmWrite(tostr(size-pos));
  1618. writer.AsmWrite(', ');
  1619. case size-pos of
  1620. 1: writer.AsmWrite(tostr(byte(tai_const(hp).value)));
  1621. 2: writer.AsmWrite(tostr(word(tai_const(hp).value)));
  1622. 4: writer.AsmWrite(tostr(longint(tai_const(hp).value)));
  1623. else
  1624. internalerror(2012010402);
  1625. end;
  1626. end;
  1627. procedure TGNUAssembler.WriteUnalignedIntConst(hp: tai_const);
  1628. var
  1629. pos, size: longint;
  1630. begin
  1631. size:=tai_const(hp).size;
  1632. writer.AsmWrite(#9'.byte'#9);
  1633. if target_info.endian=endian_big then
  1634. begin
  1635. pos:=size-1;
  1636. while pos>=0 do
  1637. begin
  1638. writer.AsmWrite(tostr((tai_const(hp).value shr (pos*8)) and $ff));
  1639. dec(pos);
  1640. if pos>=0 then
  1641. writer.AsmWrite(', ')
  1642. else
  1643. writer.AsmLn;
  1644. end;
  1645. end
  1646. else
  1647. begin
  1648. pos:=0;
  1649. while pos<size do
  1650. begin
  1651. writer.AsmWriteln(tostr((tai_const(hp).value shr (pos*8)) and $ff));
  1652. inc(pos);
  1653. if pos<=size then
  1654. writer.AsmWrite(', ')
  1655. else
  1656. writer.AsmLn;
  1657. end;
  1658. end;
  1659. writer.AsmLn;
  1660. end;
  1661. procedure TGNUAssembler.WriteDirectiveName(dir: TAsmDirective);
  1662. begin
  1663. { TODO: implement asd_cpu for GAS => usually .arch or .cpu, but the CPU
  1664. name has to be translated as well }
  1665. if dir=asd_cpu then
  1666. writer.AsmWrite(asminfo^.comment+' CPU ')
  1667. else
  1668. writer.AsmWrite('.'+directivestr[dir]+' ');
  1669. end;
  1670. procedure TGNUAssembler.WriteAsmList;
  1671. var
  1672. n : string;
  1673. hal : tasmlisttype;
  1674. i: longint;
  1675. begin
  1676. {$ifdef EXTDEBUG}
  1677. if current_module.mainsource<>'' then
  1678. Comment(V_Debug,'Start writing gas-styled assembler output for '+current_module.mainsource);
  1679. {$endif}
  1680. if current_module.mainsource<>'' then
  1681. n:=ExtractFileName(current_module.mainsource)
  1682. else
  1683. n:=InputFileName;
  1684. { gcc does not add it either for Darwin. Grep for
  1685. TARGET_ASM_FILE_START_FILE_DIRECTIVE in gcc/config/*.h
  1686. }
  1687. if not(target_info.system in systems_darwin) then
  1688. writer.AsmWriteLn(#9'.file "'+FixFileName(n)+'"');
  1689. WriteExtraHeader;
  1690. writer.MarkEmpty;
  1691. symendcount:=0;
  1692. for hal:=low(TasmlistType) to high(TasmlistType) do
  1693. begin
  1694. if not (current_asmdata.asmlists[hal].empty) then
  1695. begin
  1696. writer.AsmWriteLn(asminfo^.comment+'Begin asmlist '+AsmlistTypeStr[hal]);
  1697. writetree(current_asmdata.asmlists[hal]);
  1698. writer.AsmWriteLn(asminfo^.comment+'End asmlist '+AsmlistTypeStr[hal]);
  1699. end;
  1700. end;
  1701. { add weak symbol markers }
  1702. for i:=0 to current_asmdata.asmsymboldict.count-1 do
  1703. if (tasmsymbol(current_asmdata.asmsymboldict[i]).bind=AB_WEAK_EXTERNAL) then
  1704. WriteWeakSymbolRef(tasmsymbol(current_asmdata.asmsymboldict[i]));
  1705. if create_smartlink_sections and
  1706. (target_info.system in systems_darwin) then
  1707. writer.AsmWriteLn(#9'.subsections_via_symbols');
  1708. { "no executable stack" marker }
  1709. { TODO: used by OpenBSD/NetBSD as well? }
  1710. if (target_info.system in (systems_linux + systems_android + systems_freebsd + systems_dragonfly)) and
  1711. not(cs_executable_stack in current_settings.moduleswitches) then
  1712. begin
  1713. writer.AsmWriteLn('.section .note.GNU-stack,"",%progbits');
  1714. end;
  1715. writer.AsmLn;
  1716. WriteExtraFooter;
  1717. {$ifdef EXTDEBUG}
  1718. if current_module.mainsource<>'' then
  1719. Comment(V_Debug,'Done writing gas-styled assembler output for '+current_module.mainsource);
  1720. {$endif EXTDEBUG}
  1721. end;
  1722. {****************************************************************************}
  1723. { Apple/GNU Assembler writer }
  1724. {****************************************************************************}
  1725. function TAppleGNUAssembler.sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;
  1726. begin
  1727. if (target_info.system in systems_darwin) then
  1728. case atype of
  1729. sec_user:
  1730. begin
  1731. result:='.section '+aname;
  1732. exit;
  1733. end;
  1734. sec_bss:
  1735. { all bss (lcomm) symbols are automatically put in the right }
  1736. { place by using the lcomm assembler directive }
  1737. atype := sec_none;
  1738. sec_debug_frame,
  1739. sec_eh_frame:
  1740. begin
  1741. result := '.section __DWARF,__debug_info,regular,debug';
  1742. exit;
  1743. end;
  1744. sec_debug_line:
  1745. begin
  1746. result := '.section __DWARF,__debug_line,regular,debug';
  1747. exit;
  1748. end;
  1749. sec_debug_info:
  1750. begin
  1751. result := '.section __DWARF,__debug_info,regular,debug';
  1752. exit;
  1753. end;
  1754. sec_debug_abbrev:
  1755. begin
  1756. result := '.section __DWARF,__debug_abbrev,regular,debug';
  1757. exit;
  1758. end;
  1759. sec_debug_aranges:
  1760. begin
  1761. result := '.section __DWARF,__debug_aranges,regular,debug';
  1762. exit;
  1763. end;
  1764. sec_debug_ranges:
  1765. begin
  1766. result := '.section __DWARF,__debug_ranges,regular,debug';
  1767. exit;
  1768. end;
  1769. sec_rodata:
  1770. begin
  1771. result := '.const_data';
  1772. exit;
  1773. end;
  1774. sec_rodata_norel:
  1775. begin
  1776. result := '.const';
  1777. exit;
  1778. end;
  1779. sec_fpc:
  1780. begin
  1781. result := '.section __TEXT, .fpc, regular, no_dead_strip';
  1782. exit;
  1783. end;
  1784. sec_code:
  1785. begin
  1786. if (aname='fpc_geteipasebx') or
  1787. (aname='fpc_geteipasecx') then
  1788. begin
  1789. result:='.section __TEXT,__textcoal_nt,coalesced,pure_instructions'#10'.weak_definition '+aname+
  1790. #10'.private_extern '+aname;
  1791. exit;
  1792. end;
  1793. end;
  1794. sec_data_nonlazy:
  1795. begin
  1796. result:='.section __DATA, __nl_symbol_ptr,non_lazy_symbol_pointers';
  1797. exit;
  1798. end;
  1799. sec_data_lazy:
  1800. begin
  1801. result:='.section __DATA, __la_symbol_ptr,lazy_symbol_pointers';
  1802. exit;
  1803. end;
  1804. sec_init_func:
  1805. begin
  1806. result:='.section __DATA, __mod_init_func, mod_init_funcs';
  1807. exit;
  1808. end;
  1809. sec_term_func:
  1810. begin
  1811. result:='.section __DATA, __mod_term_func, mod_term_funcs';
  1812. exit;
  1813. end;
  1814. low(TObjCAsmSectionType)..high(TObjCAsmSectionType):
  1815. begin
  1816. result:='.section '+objc_section_name(atype);
  1817. exit
  1818. end;
  1819. else
  1820. ;
  1821. end;
  1822. result := inherited sectionname(atype,aname,aorder);
  1823. end;
  1824. procedure TAppleGNUAssembler.WriteWeakSymbolRef(s: tasmsymbol);
  1825. begin
  1826. writer.AsmWriteLn(#9'.weak_reference '+s.name);
  1827. end;
  1828. procedure TAppleGNUAssembler.WriteDirectiveName(dir: TAsmDirective);
  1829. begin
  1830. case dir of
  1831. asd_weak_reference:
  1832. writer.AsmWrite('.weak_reference ');
  1833. asd_weak_definition:
  1834. writer.AsmWrite('.weak_definition ');
  1835. else
  1836. inherited;
  1837. end;
  1838. end;
  1839. {****************************************************************************}
  1840. { a.out/GNU Assembler writer }
  1841. {****************************************************************************}
  1842. function TAoutGNUAssembler.sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;
  1843. const
  1844. (* Translation table - replace unsupported section types with basic ones. *)
  1845. SecXTable: array[TAsmSectionType] of TAsmSectionType = (
  1846. sec_none,
  1847. sec_none,
  1848. sec_code,
  1849. sec_data,
  1850. sec_data (* sec_rodata *),
  1851. sec_data (* sec_rodata_norel *),
  1852. sec_bss,
  1853. sec_data (* sec_threadvar *),
  1854. { used for wince exception handling }
  1855. sec_code (* sec_pdata *),
  1856. { used for darwin import stubs }
  1857. sec_code (* sec_stub *),
  1858. sec_data,(* sec_data_nonlazy *)
  1859. sec_data,(* sec_data_lazy *)
  1860. sec_data,(* sec_init_func *)
  1861. sec_data,(* sec_term_func *)
  1862. { stabs }
  1863. sec_stab,sec_stabstr,
  1864. { win32 }
  1865. sec_data (* sec_idata2 *),
  1866. sec_data (* sec_idata4 *),
  1867. sec_data (* sec_idata5 *),
  1868. sec_data (* sec_idata6 *),
  1869. sec_data (* sec_idata7 *),
  1870. sec_data (* sec_edata *),
  1871. { C++ exception handling unwinding (uses dwarf) }
  1872. sec_eh_frame,
  1873. { dwarf }
  1874. sec_debug_frame,
  1875. sec_debug_info,
  1876. sec_debug_line,
  1877. sec_debug_abbrev,
  1878. sec_debug_aranges,
  1879. sec_debug_ranges,
  1880. { ELF resources (+ references to stabs debug information sections) }
  1881. sec_code (* sec_fpc *),
  1882. { Table of contents section }
  1883. sec_code (* sec_toc *),
  1884. sec_code (* sec_init *),
  1885. sec_code (* sec_fini *),
  1886. sec_none (* sec_objc_class *),
  1887. sec_none (* sec_objc_meta_class *),
  1888. sec_none (* sec_objc_cat_cls_meth *),
  1889. sec_none (* sec_objc_cat_inst_meth *),
  1890. sec_none (* sec_objc_protocol *),
  1891. sec_none (* sec_objc_string_object *),
  1892. sec_none (* sec_objc_cls_meth *),
  1893. sec_none (* sec_objc_inst_meth *),
  1894. sec_none (* sec_objc_cls_refs *),
  1895. sec_none (* sec_objc_message_refs *),
  1896. sec_none (* sec_objc_symbols *),
  1897. sec_none (* sec_objc_category *),
  1898. sec_none (* sec_objc_class_vars *),
  1899. sec_none (* sec_objc_instance_vars *),
  1900. sec_none (* sec_objc_module_info *),
  1901. sec_none (* sec_objc_class_names *),
  1902. sec_none (* sec_objc_meth_var_types *),
  1903. sec_none (* sec_objc_meth_var_names *),
  1904. sec_none (* sec_objc_selector_strs *),
  1905. sec_none (* sec_objc_protocol_ext *),
  1906. sec_none (* sec_objc_class_ext *),
  1907. sec_none (* sec_objc_property *),
  1908. sec_none (* sec_objc_image_info *),
  1909. sec_none (* sec_objc_cstring_object *),
  1910. sec_none (* sec_objc_sel_fixup *),
  1911. sec_none (* sec_objc_data *),
  1912. sec_none (* sec_objc_const *),
  1913. sec_none (* sec_objc_sup_refs *),
  1914. sec_none (* sec_data_coalesced *),
  1915. sec_none (* sec_objc_classlist *),
  1916. sec_none (* sec_objc_nlclasslist *),
  1917. sec_none (* sec_objc_catlist *),
  1918. sec_none (* sec_objc_nlcatlist *),
  1919. sec_none (* sec_objc_protlist *),
  1920. sec_none (* sec_stack *),
  1921. sec_none (* sec_heap *),
  1922. sec_none (* gcc_except_table *),
  1923. sec_none (* sec_arm_attribute *)
  1924. );
  1925. begin
  1926. Result := inherited SectionName (SecXTable [AType], AName, AOrder);
  1927. end;
  1928. {****************************************************************************}
  1929. { Abstract Instruction Writer }
  1930. {****************************************************************************}
  1931. constructor TCPUInstrWriter.create(_owner: TGNUAssembler);
  1932. begin
  1933. inherited create;
  1934. owner := _owner;
  1935. end;
  1936. end.