aggas.pas 87 KB

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