aggas.pas 71 KB

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