aggas.pas 83 KB

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