aggas.pas 78 KB

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