aggas.pas 71 KB

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