aggas.pas 78 KB

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