aggas.pas 78 KB

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