aggas.pas 77 KB

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