aggas.pas 71 KB

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