2
0

aggas.pas 85 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247
  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','.debug_loc','.debug_loclists',
  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','.debug_loc','.debug_loclists',
  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. system_m68k_human68k: { see above... (KB) }
  454. begin
  455. { ... but vasm is GAS compatible on amiga/atari, and supports named sections }
  456. if create_smartlink_sections then
  457. begin
  458. writer.AsmWrite('.section ');
  459. usesectionflags:=true;
  460. usesectionprogbits:=true;
  461. { hack, to avoid linker warnings on Amiga/Atari, when vlink merges
  462. rodata sections into data sections. Also avoid the warning when
  463. the linker realizes the code section cannot be write protected and
  464. adds the writable bit. }
  465. if atype in [sec_code,sec_rodata,sec_rodata_norel] then
  466. include(secflags,SF_W);
  467. end;
  468. end;
  469. system_i386_go32v2,
  470. system_i386_win32,
  471. system_x86_64_win64,
  472. system_i386_nativent,
  473. system_i386_wince,
  474. system_arm_wince,
  475. system_aarch64_win64:
  476. begin
  477. { according to the GNU AS guide AS for COFF does not support the
  478. progbits }
  479. writer.AsmWrite('.section ');
  480. usesectionflags:=true;
  481. end;
  482. system_powerpc_darwin,
  483. system_i386_darwin,
  484. system_i386_iphonesim,
  485. system_powerpc64_darwin,
  486. system_x86_64_darwin,
  487. system_arm_ios,
  488. system_aarch64_ios,
  489. system_aarch64_iphonesim,
  490. system_aarch64_darwin,
  491. system_x86_64_iphonesim,
  492. system_powerpc_aix,
  493. system_powerpc64_aix:
  494. begin
  495. if (atype in [sec_stub]) then
  496. writer.AsmWrite('.section ');
  497. end;
  498. system_wasm32_wasi,
  499. system_wasm32_embedded:
  500. begin
  501. writer.AsmWrite('.section ');
  502. end
  503. else
  504. begin
  505. writer.AsmWrite('.section ');
  506. { sectionname may rename those sections, so we do not write flags/progbits for them,
  507. the assembler will ignore them/spite out a warning anyways }
  508. if not(atype in [sec_data,sec_rodata,sec_rodata_norel]) and
  509. not(asminfo^.id=as_solaris_as) then
  510. begin
  511. usesectionflags:=true;
  512. usesectionprogbits:=true;
  513. end;
  514. end
  515. end;
  516. s:=sectionname(atype,aname,aorder);
  517. writer.AsmWrite(s);
  518. { flags explicitly defined? }
  519. if (usesectionflags or usesectionprogbits) and
  520. ((secflags<>[]) or
  521. (secprogbits<>SPB_None)) then
  522. begin
  523. if usesectionflags then
  524. begin
  525. s:=',"'+sectionflags(secflags);
  526. writer.AsmWrite(s+'"');
  527. end;
  528. if usesectionprogbits then
  529. begin
  530. case secprogbits of
  531. SPB_PROGBITS:
  532. writer.AsmWrite(',%progbits');
  533. SPB_NOBITS:
  534. writer.AsmWrite(',%nobits');
  535. SPB_NOTE:
  536. writer.AsmWrite(',%note');
  537. SPB_None:
  538. ;
  539. else
  540. InternalError(2019100801);
  541. end;
  542. end;
  543. end
  544. else
  545. case atype of
  546. sec_fpc :
  547. if aname = 'resptrs' then
  548. writer.AsmWrite(', "a", @progbits');
  549. sec_stub :
  550. begin
  551. case target_info.system of
  552. { there are processor-independent shortcuts available }
  553. { for this, namely .symbol_stub and .picsymbol_stub, but }
  554. { they don't work and gcc doesn't use them either... }
  555. system_powerpc_darwin,
  556. system_powerpc64_darwin:
  557. if (cs_create_pic in current_settings.moduleswitches) then
  558. writer.AsmWriteln('__TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32')
  559. else
  560. writer.AsmWriteln('__TEXT,__symbol_stub1,symbol_stubs,pure_instructions,16');
  561. system_i386_darwin,
  562. system_i386_iphonesim:
  563. writer.AsmWriteln('__IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5');
  564. system_arm_ios:
  565. if (cs_create_pic in current_settings.moduleswitches) then
  566. writer.AsmWriteln('__TEXT,__picsymbolstub4,symbol_stubs,none,16')
  567. else
  568. writer.AsmWriteln('__TEXT,__symbol_stub4,symbol_stubs,none,12')
  569. { darwin/(x86-64/AArch64) uses PC-based GOT addressing, no
  570. explicit symbol stubs }
  571. else
  572. internalerror(2006031101);
  573. end;
  574. end;
  575. else
  576. { GNU AS won't recognize '.text.n_something' section name as belonging
  577. to '.text' and assigns default attributes to it, which is not
  578. always correct. We have to fix it.
  579. TODO: This likely applies to all systems which smartlink without
  580. creating libraries }
  581. begin
  582. if is_smart_section(atype) and (aname<>'') then
  583. begin
  584. s:=sectionattrs(atype);
  585. if (s<>'') then
  586. writer.AsmWrite(',"'+s+'"');
  587. end;
  588. if target_info.system in systems_aix then
  589. begin
  590. s:=sectionalignment_aix(atype,secalign);
  591. if s<>'' then
  592. writer.AsmWrite(','+s);
  593. end;
  594. end;
  595. end;
  596. writer.AsmLn;
  597. LastSecType:=atype;
  598. end;
  599. procedure TGNUAssembler.WriteCFI(hp: tai_cfi_base);
  600. begin
  601. writer.AsmWrite(cfi2str[hp.cfityp]);
  602. case hp.cfityp of
  603. cfi_startproc,
  604. cfi_endproc:
  605. ;
  606. cfi_undefined,
  607. cfi_restore,
  608. cfi_def_cfa_register:
  609. begin
  610. writer.AsmWrite(' ');
  611. writer.AsmWrite(gas_regname(tai_cfi_op_reg(hp).reg1));
  612. end;
  613. cfi_def_cfa_offset:
  614. begin
  615. writer.AsmWrite(' ');
  616. writer.AsmWrite(tostr(tai_cfi_op_val(hp).val1));
  617. end;
  618. cfi_offset:
  619. begin
  620. writer.AsmWrite(' ');
  621. writer.AsmWrite(gas_regname(tai_cfi_op_reg_val(hp).reg1));
  622. writer.AsmWrite(',');
  623. writer.AsmWrite(tostr(tai_cfi_op_reg_val(hp).val));
  624. end;
  625. else
  626. internalerror(2019030203);
  627. end;
  628. writer.AsmLn;
  629. end;
  630. {$ifdef WASM}
  631. procedure TGNUAssembler.WriteFuncType(functype: TWasmFuncType);
  632. var
  633. wasm_basic_typ: TWasmBasicType;
  634. first: boolean;
  635. begin
  636. writer.AsmWrite('(');
  637. first:=true;
  638. for wasm_basic_typ in functype.params do
  639. begin
  640. if first then
  641. first:=false
  642. else
  643. writer.AsmWrite(',');
  644. writer.AsmWrite(gas_wasm_basic_type_str[wasm_basic_typ]);
  645. end;
  646. writer.AsmWrite(') -> (');
  647. first:=true;
  648. for wasm_basic_typ in functype.results do
  649. begin
  650. if first then
  651. first:=false
  652. else
  653. writer.AsmWrite(',');
  654. writer.AsmWrite(gas_wasm_basic_type_str[wasm_basic_typ]);
  655. end;
  656. writer.AsmWrite(')');
  657. end;
  658. {$endif WASM}
  659. procedure TGNUAssembler.WriteTree(p:TAsmList);
  660. function needsObject(hp : tai_symbol) : boolean;
  661. begin
  662. needsObject :=
  663. (
  664. assigned(hp.next) and
  665. (tai(hp.next).typ in [ait_const,ait_datablock,ait_realconst])
  666. ) or
  667. (hp.sym.typ in [AT_DATA,AT_METADATA]);
  668. end;
  669. procedure doalign(alignment: byte; use_op: boolean; fillop: byte; maxbytes: byte; out last_align: longint;lasthp:tai);
  670. var
  671. i: longint;
  672. alignment64 : int64;
  673. {$ifdef m68k}
  674. instr : string;
  675. {$endif}
  676. begin
  677. last_align:=alignment;
  678. if alignment>1 then
  679. begin
  680. if not(target_info.system in (systems_darwin+systems_aix)) then
  681. begin
  682. {$ifdef m68k}
  683. if not use_op and (lastsectype=sec_code) then
  684. begin
  685. if not ispowerof2(alignment,i) then
  686. internalerror(2014022201);
  687. { the Coldfire manual suggests the TBF instruction for
  688. alignments, but somehow QEMU does not interpret that
  689. correctly... }
  690. {if current_settings.cputype in cpu_coldfire then
  691. instr:='0x51fc'
  692. else}
  693. instr:='0x4e71';
  694. writer.AsmWrite(#9'.balignw '+tostr(alignment)+','+instr);
  695. end
  696. else
  697. begin
  698. {$endif m68k}
  699. alignment64:=alignment;
  700. if (maxbytes<>alignment) and ispowerof2(alignment64,i) then
  701. begin
  702. if use_op then
  703. begin
  704. writer.AsmWrite(#9'.p2align '+tostr(i)+','+tostr(fillop)+','+tostr(maxbytes));
  705. writer.AsmLn;
  706. writer.AsmWrite(#9'.p2align '+tostr(i-1)+','+tostr(fillop));
  707. end
  708. else
  709. begin
  710. writer.AsmWrite(#9'.p2align '+tostr(i)+',,'+tostr(maxbytes));
  711. writer.AsmLn;
  712. writer.AsmWrite(#9'.p2align '+tostr(i-1));
  713. end
  714. end
  715. else
  716. begin
  717. writer.AsmWrite(#9'.balign '+tostr(alignment));
  718. if use_op then
  719. writer.AsmWrite(','+tostr(fillop))
  720. {$ifdef x86}
  721. { force NOP as alignment op code }
  722. else if (LastSecType=sec_code) and (asminfo^.id<>as_solaris_as) then
  723. writer.AsmWrite(',0x90');
  724. {$endif x86}
  725. end;
  726. {$ifdef m68k}
  727. end;
  728. {$endif m68k}
  729. end
  730. else
  731. begin
  732. { darwin and aix as only support .align }
  733. if not ispowerof2(alignment,i) then
  734. internalerror(2003010305);
  735. writer.AsmWrite(#9'.align '+tostr(i));
  736. last_align:=i;
  737. end;
  738. writer.AsmLn;
  739. end;
  740. end;
  741. {$ifdef WASM}
  742. procedure WriteFuncTypeDirective(hp:tai_functype);
  743. begin
  744. writer.AsmWrite(#9'.functype'#9);
  745. writer.AsmWrite(hp.funcname);
  746. writer.AsmWrite(' ');
  747. WriteFuncType(hp.functype);
  748. writer.AsmLn;
  749. end;
  750. procedure WriteTagType(hp: tai_tagtype);
  751. var
  752. wasm_basic_typ: TWasmBasicType;
  753. first: boolean;
  754. begin
  755. writer.AsmWrite(#9'.tagtype'#9);
  756. writer.AsmWrite(hp.tagname);
  757. first:=true;
  758. for wasm_basic_typ in hp.params do
  759. begin
  760. if first then
  761. begin
  762. first:=false;
  763. writer.AsmWrite(' ');
  764. end
  765. else
  766. writer.AsmWrite(',');
  767. writer.AsmWrite(gas_wasm_basic_type_str[wasm_basic_typ]);
  768. end;
  769. writer.AsmLn;
  770. end;
  771. {$endif WASM}
  772. var
  773. ch : char;
  774. lasthp,
  775. hp : tai;
  776. constdef : taiconst_type;
  777. s,t : string;
  778. i,pos,l : longint;
  779. InlineLevel : cardinal;
  780. last_align : longint;
  781. do_line : boolean;
  782. sepChar : char;
  783. replaceforbidden: boolean;
  784. begin
  785. if not assigned(p) then
  786. exit;
  787. replaceforbidden:=asminfo^.dollarsign<>'$';
  788. last_align := 2;
  789. InlineLevel:=0;
  790. { lineinfo is only needed for al_procedures (PFV) }
  791. do_line:=(cs_asm_source in current_settings.globalswitches) or
  792. ((cs_lineinfo in current_settings.moduleswitches)
  793. and (p=current_asmdata.asmlists[al_procedures]));
  794. lasthp:=nil;
  795. hp:=tai(p.first);
  796. while assigned(hp) do
  797. begin
  798. prefetch(pointer(hp.next)^);
  799. if not(hp.typ in SkipLineInfo) then
  800. begin
  801. current_filepos:=tailineinfo(hp).fileinfo;
  802. { no line info for inlined code }
  803. if do_line and (inlinelevel=0) then
  804. WriteSourceLine(hp as tailineinfo);
  805. end;
  806. case hp.typ of
  807. ait_align :
  808. begin
  809. 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);
  810. end;
  811. ait_section :
  812. begin
  813. ResetSourceLines;
  814. if tai_section(hp).sectype<>sec_none then
  815. if replaceforbidden then
  816. WriteSection(tai_section(hp).sectype,ApplyAsmSymbolRestrictions(tai_section(hp).name^),tai_section(hp).secorder,
  817. tai_section(hp).secalign,tai_section(hp).secflags,tai_section(hp).secprogbits)
  818. else
  819. WriteSection(tai_section(hp).sectype,tai_section(hp).name^,tai_section(hp).secorder,
  820. tai_section(hp).secalign,tai_section(hp).secflags,tai_section(hp).secprogbits)
  821. else
  822. begin
  823. {$ifdef EXTDEBUG}
  824. writer.AsmWrite(asminfo^.comment);
  825. writer.AsmWriteln(' sec_none');
  826. {$endif EXTDEBUG}
  827. end;
  828. end;
  829. ait_datablock :
  830. begin
  831. if (target_info.system in systems_darwin) then
  832. begin
  833. { On Mac OS X you can't have common symbols in a shared library
  834. since those are in the TEXT section and the text section is
  835. read-only in shared libraries (so it can be shared among different
  836. processes). The alternate code creates some kind of common symbols
  837. in the data segment.
  838. }
  839. if tai_datablock(hp).is_global then
  840. begin
  841. if tai_datablock(hp).sym.bind=AB_PRIVATE_EXTERN then
  842. WriteHiddenSymbol(tai_datablock(hp).sym);
  843. writer.AsmWrite('.globl ');
  844. writer.AsmWriteln(tai_datablock(hp).sym.name);
  845. writer.AsmWriteln('.data');
  846. writer.AsmWrite('.zerofill __DATA, __common, ');
  847. writer.AsmWrite(tai_datablock(hp).sym.name);
  848. writer.AsmWriteln(', '+tostr(tai_datablock(hp).size)+','+tostr(last_align));
  849. if not(LastSecType in [sec_data,sec_none]) then
  850. writesection(LastSecType,'',secorder_default,1 shl last_align);
  851. end
  852. else
  853. begin
  854. writer.AsmWrite(#9'.lcomm'#9);
  855. writer.AsmWrite(tai_datablock(hp).sym.name);
  856. writer.AsmWrite(','+tostr(tai_datablock(hp).size));
  857. writer.AsmWrite(','+tostr(last_align));
  858. writer.AsmLn;
  859. end;
  860. end
  861. else if target_info.system in systems_aix then
  862. begin
  863. if tai_datablock(hp).is_global then
  864. begin
  865. writer.AsmWrite(#9'.globl ');
  866. writer.AsmWriteln(ApplyAsmSymbolRestrictions(tai_datablock(hp).sym.name));
  867. writer.AsmWrite(ApplyAsmSymbolRestrictions(tai_datablock(hp).sym.name));
  868. writer.AsmWriteln(':');
  869. writer.AsmWrite(#9'.space ');
  870. writer.AsmWriteln(tostr(tai_datablock(hp).size));
  871. if not(LastSecType in [sec_data,sec_none]) then
  872. writesection(LastSecType,'',secorder_default,1 shl last_align);
  873. end
  874. else
  875. begin
  876. writer.AsmWrite(#9'.lcomm ');
  877. writer.AsmWrite(ApplyAsmSymbolRestrictions(tai_datablock(hp).sym.name));
  878. writer.AsmWrite(',');
  879. writer.AsmWrite(tostr(tai_datablock(hp).size)+',');
  880. writer.AsmWrite('_data.bss_,');
  881. writer.AsmWriteln(tostr(last_align));
  882. end;
  883. end
  884. else
  885. begin
  886. {$ifdef USE_COMM_IN_BSS}
  887. if writingpackages then
  888. begin
  889. { The .comm is required for COMMON symbols. These are used
  890. in the shared library loading. All the symbols declared in
  891. the .so file need to resolve to the data allocated in the main
  892. program (PFV) }
  893. if tai_datablock(hp).is_global then
  894. begin
  895. writer.AsmWrite(#9'.comm'#9);
  896. if replaceforbidden then
  897. writer.AsmWrite(ApplyAsmSymbolRestrictions(tai_datablock(hp).sym.name))
  898. else
  899. writer.AsmWrite(tai_datablock(hp).sym.name);
  900. writer.AsmWrite(','+tostr(tai_datablock(hp).size));
  901. writer.AsmWrite(','+tostr(last_align));
  902. writer.AsmLn;
  903. end
  904. else
  905. begin
  906. writer.AsmWrite(#9'.lcomm'#9);
  907. if replaceforbidden then
  908. writer.AsmWrite(ApplyAsmSymbolRestrictions(tai_datablock(hp).sym.name));
  909. else
  910. writer.AsmWrite(tai_datablock(hp).sym.name);
  911. writer.AsmWrite(','+tostr(tai_datablock(hp).size));
  912. writer.AsmWrite(','+tostr(last_align));
  913. writer.AsmLn;
  914. end
  915. end
  916. else
  917. {$endif USE_COMM_IN_BSS}
  918. begin
  919. if Tai_datablock(hp).is_global then
  920. begin
  921. if (tai_datablock(hp).sym.bind=AB_PRIVATE_EXTERN) then
  922. WriteHiddenSymbol(tai_datablock(hp).sym);
  923. writer.AsmWrite(#9'.globl ');
  924. if replaceforbidden then
  925. writer.AsmWriteln(ApplyAsmSymbolRestrictions(Tai_datablock(hp).sym.name))
  926. else
  927. writer.AsmWriteln(Tai_datablock(hp).sym.name);
  928. end;
  929. if ((target_info.system <> system_arm_linux) and (target_info.system <> system_arm_android)) then
  930. sepChar := '@'
  931. else
  932. sepChar := '%';
  933. if replaceforbidden then
  934. begin
  935. if (tf_needs_symbol_type in target_info.flags) then
  936. writer.AsmWriteln(#9'.type '+ApplyAsmSymbolRestrictions(Tai_datablock(hp).sym.name)+','+sepChar+'object');
  937. if (tf_needs_symbol_size in target_info.flags) and (tai_datablock(hp).size > 0) then
  938. writer.AsmWriteln(#9'.size '+ApplyAsmSymbolRestrictions(Tai_datablock(hp).sym.name)+','+tostr(Tai_datablock(hp).size));
  939. writer.AsmWrite(ApplyAsmSymbolRestrictions(Tai_datablock(hp).sym.name))
  940. end
  941. else
  942. begin
  943. if (tf_needs_symbol_type in target_info.flags) then
  944. writer.AsmWriteln(#9'.type '+Tai_datablock(hp).sym.name+','+sepChar+'object');
  945. if (tf_needs_symbol_size in target_info.flags) and (tai_datablock(hp).size > 0) then
  946. writer.AsmWriteln(#9'.size '+Tai_datablock(hp).sym.name+','+tostr(Tai_datablock(hp).size));
  947. writer.AsmWrite(Tai_datablock(hp).sym.name);
  948. end;
  949. writer.AsmWriteln(':');
  950. writer.AsmWriteln(#9'.zero '+tostr(Tai_datablock(hp).size));
  951. end;
  952. end;
  953. end;
  954. ait_const:
  955. begin
  956. constdef:=tai_const(hp).consttype;
  957. case constdef of
  958. {$ifndef cpu64bitaddr}
  959. aitconst_128bit :
  960. begin
  961. internalerror(200404291);
  962. end;
  963. aitconst_64bit :
  964. begin
  965. if assigned(tai_const(hp).sym) then
  966. internalerror(200404292);
  967. if not(target_info.system in systems_aix) then
  968. begin
  969. if (target_info.system in use_ua_elf_systems) then
  970. writer.AsmWrite(ait_ua_elf_const2str[aitconst_32bit])
  971. else
  972. writer.AsmWrite(ait_const2str[aitconst_32bit]);
  973. if target_info.endian = endian_little then
  974. begin
  975. writer.AsmWrite(tostr(longint(lo(tai_const(hp).value))));
  976. writer.AsmWrite(',');
  977. writer.AsmWrite(tostr(longint(hi(tai_const(hp).value))));
  978. end
  979. else
  980. begin
  981. writer.AsmWrite(tostr(longint(hi(tai_const(hp).value))));
  982. writer.AsmWrite(',');
  983. writer.AsmWrite(tostr(longint(lo(tai_const(hp).value))));
  984. end;
  985. end
  986. else
  987. WriteAixIntConst(tai_const(hp));
  988. writer.AsmLn;
  989. end;
  990. aitconst_gottpoff:
  991. begin
  992. writer.AsmWrite(#9'.word'#9+tai_const(hp).sym.name+'(gottpoff)+(.-'+tai_const(hp).endsym.name+tostr_with_plus(tai_const(hp).symofs)+')');
  993. writer.Asmln;
  994. end;
  995. aitconst_tlsgd:
  996. begin
  997. writer.AsmWrite(#9'.word'#9+tai_const(hp).sym.name+'(tlsgd)+(.-'+tai_const(hp).endsym.name+tostr_with_plus(tai_const(hp).symofs)+')');
  998. writer.Asmln;
  999. end;
  1000. aitconst_tlsdesc:
  1001. begin
  1002. writer.AsmWrite(#9'.word'#9+tai_const(hp).sym.name+'(tlsdesc)+(.-'+tai_const(hp).endsym.name+tostr_with_plus(tai_const(hp).symofs)+')');
  1003. writer.Asmln;
  1004. end;
  1005. aitconst_tpoff:
  1006. begin
  1007. if assigned(tai_const(hp).endsym) or (tai_const(hp).symofs<>0) then
  1008. Internalerror(2019092805);
  1009. writer.AsmWrite(#9'.word'#9+tai_const(hp).sym.name+'(tpoff)');
  1010. writer.Asmln;
  1011. end;
  1012. {$endif cpu64bitaddr}
  1013. aitconst_dtpoff:
  1014. begin
  1015. {$ifdef arm}
  1016. writer.AsmWrite(#9'.word'#9+tai_const(hp).sym.name+'(tlsldo)');
  1017. writer.Asmln;
  1018. {$endif arm}
  1019. {$ifdef x86_64}
  1020. writer.AsmWrite(#9'.long'#9+tai_const(hp).sym.name+'@dtpoff');
  1021. writer.Asmln;
  1022. {$endif x86_64}
  1023. {$ifdef i386}
  1024. writer.AsmWrite(#9'.word'#9+tai_const(hp).sym.name+'@tdpoff');
  1025. writer.Asmln;
  1026. {$endif i386}
  1027. end;
  1028. aitconst_got:
  1029. begin
  1030. if tai_const(hp).symofs<>0 then
  1031. InternalError(2015091401); // No symbol offset is allowed for GOT.
  1032. writer.AsmWrite(#9'.word'#9+tai_const(hp).sym.name+'(GOT)');
  1033. writer.AsmLn;
  1034. end;
  1035. aitconst_gotoff_symbol:
  1036. begin
  1037. if (tai_const(hp).sym=nil) then
  1038. InternalError(2014022601);
  1039. case target_info.cpu of
  1040. cpu_mipseb,cpu_mipsel:
  1041. begin
  1042. writer.AsmWrite(#9'.gpword'#9);
  1043. writer.AsmWrite(tai_const(hp).sym.name);
  1044. end;
  1045. cpu_i386:
  1046. begin
  1047. writer.AsmWrite(ait_const2str[aitconst_32bit]);
  1048. writer.AsmWrite(tai_const(hp).sym.name+'-_GLOBAL_OFFSET_TABLE_');
  1049. end;
  1050. else
  1051. InternalError(2014022602);
  1052. end;
  1053. if (tai_const(hp).value<>0) then
  1054. writer.AsmWrite(tostr_with_plus(tai_const(hp).value));
  1055. writer.AsmLn;
  1056. end;
  1057. aitconst_uleb128bit,
  1058. aitconst_sleb128bit,
  1059. {$ifdef cpu64bitaddr}
  1060. aitconst_128bit,
  1061. aitconst_64bit,
  1062. {$endif cpu64bitaddr}
  1063. aitconst_32bit,
  1064. aitconst_16bit,
  1065. aitconst_8bit,
  1066. aitconst_rva_symbol,
  1067. aitconst_secrel32_symbol,
  1068. aitconst_darwin_dwarf_delta32,
  1069. aitconst_darwin_dwarf_delta64,
  1070. aitconst_half16bit,
  1071. aitconst_gs,
  1072. aitconst_16bit_unaligned,
  1073. aitconst_32bit_unaligned,
  1074. aitconst_64bit_unaligned:
  1075. begin
  1076. { the AIX assembler (and for compatibility, the GNU
  1077. assembler when targeting AIX) automatically aligns
  1078. .short/.long/.llong to a multiple of 2/4/8 bytes. We
  1079. don't want that, since this may be data inside a packed
  1080. record -> use .vbyte instead (byte stream of fixed
  1081. length) }
  1082. if (target_info.system in systems_aix) and
  1083. (constdef in [aitconst_128bit,aitconst_64bit,aitconst_32bit,aitconst_16bit]) and
  1084. not assigned(tai_const(hp).sym) then
  1085. begin
  1086. WriteAixIntConst(tai_const(hp));
  1087. end
  1088. else if (target_info.system in systems_darwin) and
  1089. (constdef in [aitconst_uleb128bit,aitconst_sleb128bit]) then
  1090. begin
  1091. writer.AsmWrite(ait_const2str[aitconst_8bit]);
  1092. case tai_const(hp).consttype of
  1093. aitconst_uleb128bit:
  1094. writer.AsmWrite(uleb128tostr(qword(tai_const(hp).value)));
  1095. aitconst_sleb128bit:
  1096. writer.AsmWrite(sleb128tostr(tai_const(hp).value));
  1097. else
  1098. ;
  1099. end
  1100. end
  1101. else
  1102. begin
  1103. if (constdef in ait_unaligned_consts) and
  1104. (target_info.system in use_ua_sparc_systems) then
  1105. writer.AsmWrite(ait_ua_sparc_const2str[constdef])
  1106. else if (target_info.system in use_ua_elf_systems) then
  1107. writer.AsmWrite(ait_ua_elf_const2str[constdef])
  1108. { we can also have unaligned pointers in packed record
  1109. constants, which don't get translated into
  1110. unaligned tai -> always use vbyte }
  1111. else if target_info.system in systems_aix then
  1112. writer.AsmWrite(#9'.vbyte'#9+tostr(tai_const(hp).size)+',')
  1113. else if (asminfo^.id=as_solaris_as) then
  1114. writer.AsmWrite(ait_solaris_const2str[constdef])
  1115. else
  1116. writer.AsmWrite(ait_const2str[constdef]);
  1117. l:=0;
  1118. t := '';
  1119. repeat
  1120. if assigned(tai_const(hp).sym) then
  1121. begin
  1122. if assigned(tai_const(hp).endsym) then
  1123. begin
  1124. if (constdef in [aitconst_darwin_dwarf_delta32,aitconst_darwin_dwarf_delta64]) then
  1125. begin
  1126. s := NextSetLabel;
  1127. t := #9'.set '+s+','+tai_const(hp).endsym.name+'-'+tai_const(hp).sym.name;
  1128. end
  1129. else
  1130. s:=tai_const(hp).endsym.name+'-'+tai_const(hp).sym.name
  1131. end
  1132. else
  1133. s:=tai_const(hp).sym.name;
  1134. if replaceforbidden then
  1135. s:=ApplyAsmSymbolRestrictions(s);
  1136. if tai_const(hp).value<>0 then
  1137. s:=s+tostr_with_plus(tai_const(hp).value);
  1138. end
  1139. else
  1140. {$ifdef cpu64bitaddr}
  1141. s:=tostr(tai_const(hp).value);
  1142. {$else cpu64bitaddr}
  1143. { 64 bit constants are already handled above in this case }
  1144. s:=tostr(longint(tai_const(hp).value));
  1145. {$endif cpu64bitaddr}
  1146. if constdef = aitconst_half16bit then
  1147. s:='('+s+')/2';
  1148. if constdef = aitconst_gs then
  1149. s:='gs('+s+')';
  1150. writer.AsmWrite(s);
  1151. inc(l,length(s));
  1152. { Values with symbols are written on a single line to improve
  1153. reading of the .s file (PFV) }
  1154. if assigned(tai_const(hp).sym) or
  1155. not(LastSecType in [sec_data,sec_rodata,sec_rodata_norel]) or
  1156. (l>line_length) or
  1157. (hp.next=nil) or
  1158. (tai(hp.next).typ<>ait_const) or
  1159. (tai_const(hp.next).consttype<>constdef) or
  1160. assigned(tai_const(hp.next).sym) then
  1161. break;
  1162. hp:=tai(hp.next);
  1163. writer.AsmWrite(',');
  1164. until false;
  1165. if (t <> '') then
  1166. begin
  1167. writer.AsmLn;
  1168. writer.AsmWrite(t);
  1169. end;
  1170. end;
  1171. writer.AsmLn;
  1172. end;
  1173. else
  1174. internalerror(200704251);
  1175. end;
  1176. end;
  1177. ait_realconst :
  1178. begin
  1179. WriteRealConstAsBytes(tai_realconst(hp),#9'.byte'#9,do_line);
  1180. end;
  1181. ait_string :
  1182. begin
  1183. pos:=0;
  1184. if not(target_info.system in systems_aix) then
  1185. begin
  1186. for i:=1 to tai_string(hp).len do
  1187. begin
  1188. if pos=0 then
  1189. begin
  1190. writer.AsmWrite(#9'.ascii'#9'"');
  1191. pos:=20;
  1192. end;
  1193. ch:=tai_string(hp).str[i-1];
  1194. case ch of
  1195. #0, {This can't be done by range, because a bug in FPC}
  1196. #1..#31,
  1197. #128..#255 : s:='\'+tostr(ord(ch) shr 6)+tostr((ord(ch) and 63) shr 3)+tostr(ord(ch) and 7);
  1198. '"' : s:='\"';
  1199. '\' : s:='\\';
  1200. else
  1201. s:=ch;
  1202. end;
  1203. writer.AsmWrite(s);
  1204. inc(pos,length(s));
  1205. if (pos>line_length) or (i=tai_string(hp).len) then
  1206. begin
  1207. writer.AsmWriteLn('"');
  1208. pos:=0;
  1209. end;
  1210. end;
  1211. end
  1212. else
  1213. WriteAixStringConst(tai_string(hp));
  1214. end;
  1215. ait_label :
  1216. begin
  1217. {$ifdef DEBUG_LABEL}
  1218. writer.AsmWrite(asminfo^.comment);
  1219. writer.AsmWriteLn('References = ' + tostr(tai_label(hp).labsym.getrefs));
  1220. if tai_label(hp).labsym.getrefs=0 then
  1221. writer.AsmWriteln(asminfo^.comment+'Optimized out label '+tai_label(hp).labsym.name);
  1222. {$endif DEBUG_LABEL}
  1223. if (tai_label(hp).labsym.is_used) then
  1224. begin
  1225. if tai_label(hp).labsym.bind in [AB_GLOBAL,AB_PRIVATE_EXTERN] then
  1226. begin
  1227. if (tai_label(hp).labsym.bind=AB_PRIVATE_EXTERN) then
  1228. begin
  1229. writer.AsmWrite(#9'.private_extern ');
  1230. writer.AsmWriteln(tai_label(hp).labsym.name);
  1231. end;
  1232. {$ifdef arm}
  1233. { do no change arm mode accidently, .globl seems to reset the mode }
  1234. if GenerateThumbCode or GenerateThumb2Code then
  1235. writer.AsmWriteln(#9'.thumb_func'#9);
  1236. {$endif arm}
  1237. writer.AsmWrite('.globl'#9);
  1238. if replaceforbidden then
  1239. writer.AsmWriteLn(ApplyAsmSymbolRestrictions(tai_label(hp).labsym.name))
  1240. else
  1241. writer.AsmWriteLn(tai_label(hp).labsym.name);
  1242. end;
  1243. if replaceforbidden then
  1244. writer.AsmWrite(ApplyAsmSymbolRestrictions(tai_label(hp).labsym.name))
  1245. else
  1246. writer.AsmWrite(tai_label(hp).labsym.name);
  1247. writer.AsmWriteLn(':');
  1248. end;
  1249. end;
  1250. ait_symbol :
  1251. begin
  1252. if (target_info.system=system_powerpc64_linux) and
  1253. (tai_symbol(hp).sym.typ=AT_FUNCTION) and
  1254. (cs_profile in current_settings.moduleswitches) then
  1255. writer.AsmWriteLn('.globl _mcount');
  1256. if tai_symbol(hp).is_global then
  1257. begin
  1258. writer.AsmWrite('.globl'#9);
  1259. if replaceforbidden then
  1260. writer.AsmWriteln(ApplyAsmSymbolRestrictions(tai_symbol(hp).sym.name))
  1261. else
  1262. writer.AsmWriteln(tai_symbol(hp).sym.name);
  1263. if (tai_symbol(hp).sym.bind=AB_PRIVATE_EXTERN) then
  1264. WriteHiddenSymbol(tai_symbol(hp).sym);
  1265. end;
  1266. if (target_info.system=system_powerpc64_linux) and
  1267. use_dotted_functions and
  1268. (tai_symbol(hp).sym.typ=AT_FUNCTION) then
  1269. begin
  1270. writer.AsmWriteLn('.section ".opd", "aw"');
  1271. writer.AsmWriteLn('.align 3');
  1272. writer.AsmWriteLn(tai_symbol(hp).sym.name + ':');
  1273. writer.AsmWriteLn('.quad .' + tai_symbol(hp).sym.name + ', .TOC.@tocbase, 0');
  1274. writer.AsmWriteLn('.previous');
  1275. writer.AsmWriteLn('.size ' + tai_symbol(hp).sym.name + ', 24');
  1276. if (tai_symbol(hp).is_global) then
  1277. writer.AsmWriteLn('.globl .' + tai_symbol(hp).sym.name);
  1278. writer.AsmWriteLn('.type .' + tai_symbol(hp).sym.name + ', @function');
  1279. { the dotted name is the name of the actual function entry }
  1280. writer.AsmWrite('.');
  1281. end
  1282. else if (target_info.system in systems_aix) and
  1283. (tai_symbol(hp).sym.typ = AT_FUNCTION) then
  1284. begin
  1285. if target_info.system=system_powerpc_aix then
  1286. begin
  1287. s:=#9'.long .';
  1288. ch:='2';
  1289. end
  1290. else
  1291. begin
  1292. s:=#9'.llong .';
  1293. ch:='3';
  1294. end;
  1295. writer.AsmWriteLn(#9'.csect '+ApplyAsmSymbolRestrictions(tai_symbol(hp).sym.name)+'[DS],'+ch);
  1296. writer.AsmWriteLn(ApplyAsmSymbolRestrictions(tai_symbol(hp).sym.name)+':');
  1297. writer.AsmWriteln(s+ApplyAsmSymbolRestrictions(tai_symbol(hp).sym.name)+', TOC[tc0], 0');
  1298. writer.AsmWriteln(#9'.csect .text[PR]');
  1299. if (tai_symbol(hp).is_global) then
  1300. writer.AsmWriteLn('.globl .'+ApplyAsmSymbolRestrictions(tai_symbol(hp).sym.name))
  1301. else
  1302. writer.AsmWriteLn('.lglobl .'+ApplyAsmSymbolRestrictions(tai_symbol(hp).sym.name));
  1303. { the dotted name is the name of the actual function entry }
  1304. writer.AsmWrite('.');
  1305. end
  1306. else if tai_symbol(hp).sym.typ=AT_WASM_EXCEPTION_TAG then
  1307. begin
  1308. { nothing here, to ensure we don' write the .type directive for exception tags }
  1309. end
  1310. else
  1311. begin
  1312. if ((target_info.system <> system_arm_linux) and (target_info.system <> system_arm_android)) or
  1313. (target_asm.id=as_arm_vasm) then
  1314. sepChar := '@'
  1315. else
  1316. sepChar := '#';
  1317. if (tf_needs_symbol_type in target_info.flags) then
  1318. begin
  1319. writer.AsmWrite(#9'.type'#9 + tai_symbol(hp).sym.name);
  1320. if (needsObject(tai_symbol(hp))) then
  1321. writer.AsmWriteLn(',' + sepChar + 'object')
  1322. else
  1323. writer.AsmWriteLn(',' + sepChar + 'function');
  1324. end;
  1325. end;
  1326. if replaceforbidden then
  1327. if not(tai_symbol(hp).has_value) then
  1328. writer.AsmWriteLn(ApplyAsmSymbolRestrictions(tai_symbol(hp).sym.name + ':'))
  1329. else
  1330. writer.AsmWriteLn(ApplyAsmSymbolRestrictions(tai_symbol(hp).sym.name + '=' + tostr(tai_symbol(hp).value)))
  1331. else if not(tai_symbol(hp).has_value) then
  1332. writer.AsmWriteLn(tai_symbol(hp).sym.name + ':')
  1333. else
  1334. writer.AsmWriteLn(tai_symbol(hp).sym.name + '=' + tostr(tai_symbol(hp).value));
  1335. end;
  1336. ait_symbolpair:
  1337. begin
  1338. writer.AsmWrite(#9);
  1339. writer.AsmWrite(symbolpairkindstr[tai_symbolpair(hp).kind]);
  1340. writer.AsmWrite(' ');
  1341. if tai_symbolpair(hp).kind<>spk_localentry then
  1342. s:=', '
  1343. else
  1344. { the .localentry directive has to specify the size from the
  1345. start till here of the non-local entry code as second argument }
  1346. s:=', .-';
  1347. if ((target_info.system <> system_arm_linux) and (target_info.system <> system_arm_android)) then
  1348. sepChar := '@'
  1349. else
  1350. sepChar := '#';
  1351. if replaceforbidden then
  1352. begin
  1353. { avoid string truncation }
  1354. writer.AsmWrite(ApplyAsmSymbolRestrictions(tai_symbolpair(hp).sym^));
  1355. writer.AsmWrite(s);
  1356. writer.AsmWriteLn(ApplyAsmSymbolRestrictions(tai_symbolpair(hp).value^));
  1357. if tai_symbolpair(hp).kind=spk_set_global then
  1358. begin
  1359. writer.AsmWrite(#9'.globl ');
  1360. writer.AsmWriteLn(ApplyAsmSymbolRestrictions(tai_symbolpair(hp).sym^));
  1361. end;
  1362. if (tf_needs_symbol_type in target_info.flags) then
  1363. begin
  1364. writer.AsmWrite(#9'.type'#9 + ApplyAsmSymbolRestrictions(tai_symbolpair(hp).sym^));
  1365. writer.AsmWriteLn(',' + sepChar + 'function');
  1366. end;
  1367. end
  1368. else
  1369. begin
  1370. { avoid string truncation }
  1371. writer.AsmWrite(tai_symbolpair(hp).sym^);
  1372. writer.AsmWrite(s);
  1373. writer.AsmWriteLn(tai_symbolpair(hp).value^);
  1374. if tai_symbolpair(hp).kind=spk_set_global then
  1375. begin
  1376. writer.AsmWrite(#9'.globl ');
  1377. writer.AsmWriteLn(tai_symbolpair(hp).sym^);
  1378. end;
  1379. if (tf_needs_symbol_type in target_info.flags) then
  1380. begin
  1381. writer.AsmWrite(#9'.type'#9 + tai_symbolpair(hp).sym^);
  1382. writer.AsmWriteLn(',' + sepChar + 'function');
  1383. end;
  1384. end;
  1385. end;
  1386. ait_symbol_end :
  1387. begin
  1388. if tf_needs_symbol_size in target_info.flags then
  1389. begin
  1390. s:=asminfo^.labelprefix+'e'+tostr(symendcount);
  1391. inc(symendcount);
  1392. writer.AsmWriteLn(s+':');
  1393. writer.AsmWrite(#9'.size'#9);
  1394. if (target_info.system=system_powerpc64_linux) and
  1395. use_dotted_functions and
  1396. (tai_symbol_end(hp).sym.typ=AT_FUNCTION) then
  1397. writer.AsmWrite('.');
  1398. if replaceforbidden then
  1399. writer.AsmWrite(ApplyAsmSymbolRestrictions(tai_symbol_end(hp).sym.name))
  1400. else
  1401. writer.AsmWrite(tai_symbol_end(hp).sym.name);
  1402. writer.AsmWrite(', '+s+' - ');
  1403. if (target_info.system=system_powerpc64_linux) and
  1404. use_dotted_functions and
  1405. (tai_symbol_end(hp).sym.typ=AT_FUNCTION) then
  1406. writer.AsmWrite('.');
  1407. if replaceforbidden then
  1408. writer.AsmWriteLn(ApplyAsmSymbolRestrictions(tai_symbol_end(hp).sym.name))
  1409. else
  1410. writer.AsmWriteLn(tai_symbol_end(hp).sym.name);
  1411. end;
  1412. end;
  1413. ait_instruction :
  1414. begin
  1415. WriteInstruction(hp);
  1416. end;
  1417. ait_stab :
  1418. begin
  1419. if assigned(tai_stab(hp).str) then
  1420. begin
  1421. writer.AsmWrite(#9'.'+stabtypestr[tai_stab(hp).stabtype]+' ');
  1422. writer.AsmWritePChar(tai_stab(hp).str);
  1423. writer.AsmLn;
  1424. end;
  1425. end;
  1426. ait_force_line,
  1427. ait_function_name :
  1428. begin
  1429. {$ifdef DEBUG_AGGAS}
  1430. WriteStr(s,hp.typ);
  1431. writer.AsmWriteLn('# '+s);
  1432. {$endif DEBUG_AGGAS}
  1433. end;
  1434. ait_cutobject :
  1435. begin
  1436. {$ifdef DEBUG_AGGAS}
  1437. writer.AsmWriteLn('# ait_cutobject');
  1438. {$endif DEBUG_AGGAS}
  1439. if SmartAsm then
  1440. begin
  1441. { only reset buffer if nothing has changed }
  1442. if not(writer.ClearIfEmpty) then
  1443. begin
  1444. writer.AsmClose;
  1445. DoAssemble;
  1446. writer.AsmCreate(tai_cutobject(hp).place);
  1447. end;
  1448. { avoid empty files }
  1449. while assigned(hp.next) and (tai(hp.next).typ in [ait_cutobject,ait_section,ait_comment]) do
  1450. begin
  1451. if tai(hp.next).typ=ait_section then
  1452. LastSecType:=tai_section(hp.next).sectype;
  1453. hp:=tai(hp.next);
  1454. end;
  1455. if LastSecType<>sec_none then
  1456. WriteSection(LastSecType,'',secorder_default,last_align);
  1457. writer.MarkEmpty;
  1458. end;
  1459. end;
  1460. ait_marker :
  1461. begin
  1462. {$ifdef DEBUG_AGGAS}
  1463. WriteStr(s,tai_marker(hp).Kind);
  1464. writer.AsmWriteLn('# ait_marker, kind: '+s);
  1465. {$endif DEBUG_AGGAS}
  1466. if tai_marker(hp).kind=mark_NoLineInfoStart then
  1467. inc(InlineLevel)
  1468. else if tai_marker(hp).kind=mark_NoLineInfoEnd then
  1469. dec(InlineLevel);
  1470. end;
  1471. ait_directive :
  1472. begin
  1473. WriteDirectiveName(tai_directive(hp).directive);
  1474. if tai_directive(hp).name <>'' then
  1475. begin
  1476. if replaceforbidden then
  1477. writer.AsmWrite(ApplyAsmSymbolRestrictions(tai_directive(hp).name))
  1478. else
  1479. writer.AsmWrite(tai_directive(hp).name);
  1480. end;
  1481. writer.AsmLn;
  1482. end;
  1483. ait_seh_directive :
  1484. begin
  1485. {$ifndef DISABLE_WIN64_SEH}
  1486. writer.AsmWrite(sehdirectivestr[tai_seh_directive(hp).kind]);
  1487. case tai_seh_directive(hp).datatype of
  1488. sd_none:;
  1489. sd_string:
  1490. begin
  1491. writer.AsmWrite(' '+tai_seh_directive(hp).data.name^);
  1492. if (tai_seh_directive(hp).data.flags and 1)<>0 then
  1493. writer.AsmWrite(',@except');
  1494. if (tai_seh_directive(hp).data.flags and 2)<>0 then
  1495. writer.AsmWrite(',@unwind');
  1496. end;
  1497. sd_reg:
  1498. writer.AsmWrite(' '+gas_regname(tai_seh_directive(hp).data.reg));
  1499. sd_offset:
  1500. writer.AsmWrite(' '+tostr(tai_seh_directive(hp).data.offset));
  1501. sd_regoffset:
  1502. writer.AsmWrite(' '+gas_regname(tai_seh_directive(hp).data.reg)+', '+
  1503. tostr(tai_seh_directive(hp).data.offset));
  1504. end;
  1505. writer.AsmLn;
  1506. {$endif DISABLE_WIN64_SEH}
  1507. end;
  1508. ait_cfi:
  1509. begin
  1510. WriteCFI(tai_cfi_base(hp));
  1511. end;
  1512. ait_eabi_attribute:
  1513. begin
  1514. { as of today, vasm does not support the eabi directives }
  1515. if target_asm.id<>as_arm_vasm then
  1516. begin
  1517. case tai_eabi_attribute(hp).eattr_typ of
  1518. eattrtype_dword:
  1519. writer.AsmWrite(#9'.eabi_attribute '+tostr(tai_eabi_attribute(hp).tag)+','+tostr(tai_eabi_attribute(hp).value));
  1520. eattrtype_ntbs:
  1521. begin
  1522. if assigned(tai_eabi_attribute(hp).valuestr) then
  1523. writer.AsmWrite(#9'.eabi_attribute '+tostr(tai_eabi_attribute(hp).tag)+',"'+tai_eabi_attribute(hp).valuestr^+'"')
  1524. else
  1525. writer.AsmWrite(#9'.eabi_attribute '+tostr(tai_eabi_attribute(hp).tag)+',""');
  1526. end
  1527. else
  1528. Internalerror(2019100601);
  1529. end;
  1530. writer.AsmLn;
  1531. end;
  1532. end;
  1533. {$ifdef WASM}
  1534. ait_local:
  1535. begin
  1536. if tai_local(hp).first then
  1537. writer.AsmWrite(#9'.local'#9)
  1538. else
  1539. writer.AsmWrite(', ');
  1540. writer.AsmWrite(gas_wasm_basic_type_str[tai_local(hp).bastyp]);
  1541. if tai_local(hp).last then
  1542. writer.AsmLn;
  1543. end;
  1544. ait_globaltype:
  1545. begin
  1546. writer.AsmWrite(#9'.globaltype'#9);
  1547. writer.AsmWrite(tai_globaltype(hp).globalname);
  1548. writer.AsmWrite(', ');
  1549. writer.AsmWrite(gas_wasm_basic_type_str[tai_globaltype(hp).gtype]);
  1550. if tai_globaltype(hp).immutable then
  1551. writer.AsmWrite(', immutable');
  1552. writer.AsmLn;
  1553. if tai_globaltype(hp).is_global then
  1554. begin
  1555. writer.AsmWrite(#9'.globl ');
  1556. writer.AsmWriteLn(tai_globaltype(hp).globalname);
  1557. end;
  1558. if not tai_globaltype(hp).is_external then
  1559. begin
  1560. writer.AsmWrite(tai_globaltype(hp).globalname);
  1561. writer.AsmWriteLn(':');
  1562. end;
  1563. end;
  1564. ait_functype:
  1565. WriteFuncTypeDirective(tai_functype(hp));
  1566. ait_export_name:
  1567. begin
  1568. writer.AsmWrite(#9'.export_name'#9);
  1569. writer.AsmWrite(tai_export_name(hp).intname);
  1570. writer.AsmWrite(', ');
  1571. writer.AsmWriteLn(tai_export_name(hp).extname);
  1572. end;
  1573. ait_tagtype:
  1574. WriteTagType(tai_tagtype(hp));
  1575. ait_import_module:
  1576. begin
  1577. writer.AsmWrite(#9'.import_module'#9);
  1578. writer.AsmWrite(tai_import_module(hp).symname);
  1579. writer.AsmWrite(', ');
  1580. writer.AsmWriteLn(tai_import_module(hp).importmodule);
  1581. end;
  1582. ait_import_name:
  1583. begin
  1584. writer.AsmWrite(#9'.import_name'#9);
  1585. writer.AsmWrite(tai_import_name(hp).symname);
  1586. writer.AsmWrite(', ');
  1587. writer.AsmWriteLn(tai_import_name(hp).importname);
  1588. end;
  1589. ait_wasm_structured_instruction:
  1590. begin
  1591. { What we output for these is not valid llvm-mc output
  1592. and we only print it for compiler debug purposes.
  1593. These shouldn't be present in the final asmlist. }
  1594. if hp is tai_wasmstruc_block then
  1595. begin
  1596. writer.AsmWriteLn('.err block {');
  1597. WriteTree(tai_wasmstruc_block(hp).inner_asmlist);
  1598. writer.AsmWriteLn('.err } end block');
  1599. end
  1600. else if hp is tai_wasmstruc_loop then
  1601. begin
  1602. writer.AsmWriteLn('.err loop {');
  1603. WriteTree(tai_wasmstruc_loop(hp).inner_asmlist);
  1604. writer.AsmWriteLn('.err } end loop');
  1605. end
  1606. else if hp is tai_wasmstruc_if then
  1607. begin
  1608. writer.AsmWriteLn('.err if {');
  1609. WriteTree(tai_wasmstruc_if(hp).then_asmlist);
  1610. writer.AsmWriteLn('.err } else {');
  1611. WriteTree(tai_wasmstruc_if(hp).else_asmlist);
  1612. writer.AsmWriteLn('.err } endif');
  1613. end
  1614. else if hp is tai_wasmstruc_try then
  1615. begin
  1616. writer.AsmWriteLn('.err try {');
  1617. WriteTree(tai_wasmstruc_try(hp).try_asmlist);
  1618. if hp is tai_wasmstruc_try_catch then
  1619. with tai_wasmstruc_try_catch(hp) do
  1620. begin
  1621. for i:=low(catch_list) to high(catch_list) do
  1622. begin
  1623. writer.AsmWriteLn('.err catch');
  1624. WriteTree(catch_list[i].asmlist);
  1625. end;
  1626. if assigned(catch_all_asmlist) then
  1627. begin
  1628. writer.AsmWriteLn('.err catch_all');
  1629. WriteTree(catch_all_asmlist);
  1630. end;
  1631. writer.AsmWriteLn('.err } end try');
  1632. end
  1633. else if hp is tai_wasmstruc_try_delegate then
  1634. writer.AsmWriteLn('.err } delegate')
  1635. else
  1636. writer.AsmWriteLn('.err unknown try structured instruction: ' + hp.ClassType.ClassName);
  1637. end
  1638. else
  1639. writer.AsmWriteLn('.err structured instruction: ' + hp.ClassType.ClassName);
  1640. end;
  1641. {$endif WASM}
  1642. else
  1643. if not WriteComments(hp) then
  1644. internalerror(2006012201);
  1645. end;
  1646. lasthp:=hp;
  1647. hp:=tai(hp.next);
  1648. end;
  1649. end;
  1650. procedure TGNUAssembler.WriteExtraHeader;
  1651. begin
  1652. end;
  1653. procedure TGNUAssembler.WriteExtraFooter;
  1654. begin
  1655. end;
  1656. procedure TGNUAssembler.WriteInstruction(hp: tai);
  1657. begin
  1658. InstrWriter.WriteInstruction(hp);
  1659. end;
  1660. procedure TGNUAssembler.WriteWeakSymbolRef(s: tasmsymbol);
  1661. begin
  1662. writer.AsmWrite(#9'.weak ');
  1663. if asminfo^.dollarsign='$' then
  1664. writer.AsmWriteLn(s.name)
  1665. else
  1666. writer.AsmWriteLn(ApplyAsmSymbolRestrictions(s.name))
  1667. end;
  1668. procedure TGNUAssembler.WriteHiddenSymbol(sym: TAsmSymbol);
  1669. begin
  1670. { on Windows/(PE)COFF, global symbols are hidden by default: global
  1671. symbols that are not explicitly exported from an executable/library,
  1672. become hidden }
  1673. if (target_info.system in (systems_windows+systems_wince+systems_nativent)) then
  1674. exit;
  1675. if target_info.system in systems_darwin then
  1676. writer.AsmWrite(#9'.private_extern ')
  1677. else
  1678. writer.AsmWrite(#9'.hidden ');
  1679. if asminfo^.dollarsign='$' then
  1680. writer.AsmWriteLn(sym.name)
  1681. else
  1682. writer.AsmWriteLn(ApplyAsmSymbolRestrictions(sym.name))
  1683. end;
  1684. procedure TGNUAssembler.WriteAixStringConst(hp: tai_string);
  1685. type
  1686. tterminationkind = (term_none,term_string,term_nostring);
  1687. var
  1688. i: longint;
  1689. pos: longint;
  1690. s: string;
  1691. ch: char;
  1692. instring: boolean;
  1693. procedure newstatement(terminationkind: tterminationkind);
  1694. begin
  1695. case terminationkind of
  1696. term_none: ;
  1697. term_string:
  1698. writer.AsmWriteLn('"');
  1699. term_nostring:
  1700. writer.AsmLn;
  1701. end;
  1702. writer.AsmWrite(#9'.byte'#9);
  1703. pos:=20;
  1704. instring:=false;
  1705. end;
  1706. begin
  1707. pos:=0;
  1708. instring:=false;
  1709. for i:=1 to hp.len do
  1710. begin
  1711. if pos=0 then
  1712. newstatement(term_none);
  1713. ch:=hp.str[i-1];
  1714. case ch of
  1715. #0..#31,
  1716. #127..#255 :
  1717. begin
  1718. if instring then
  1719. newstatement(term_string);
  1720. if pos=20 then
  1721. s:=tostr(ord(ch))
  1722. else
  1723. s:=', '+tostr(ord(ch))
  1724. end;
  1725. '"' :
  1726. if instring then
  1727. s:='""'
  1728. else
  1729. begin
  1730. if pos<>20 then
  1731. newstatement(term_nostring);
  1732. s:='"""';
  1733. instring:=true;
  1734. end;
  1735. else
  1736. if not instring then
  1737. begin
  1738. if (pos<>20) then
  1739. newstatement(term_nostring);
  1740. s:='"'+ch;
  1741. instring:=true;
  1742. end
  1743. else
  1744. s:=ch;
  1745. end;
  1746. writer.AsmWrite(s);
  1747. inc(pos,length(s));
  1748. if (pos>line_length) or (i=tai_string(hp).len) then
  1749. begin
  1750. if instring then
  1751. writer.AsmWriteLn('"')
  1752. else
  1753. writer.AsmLn;
  1754. pos:=0;
  1755. end;
  1756. end;
  1757. end;
  1758. procedure TGNUAssembler.WriteAixIntConst(hp: tai_const);
  1759. var
  1760. pos, size: longint;
  1761. begin
  1762. { only big endian AIX supported for now }
  1763. if target_info.endian<>endian_big then
  1764. internalerror(2012010401);
  1765. { limitation: can only write 4 bytes at a time }
  1766. pos:=0;
  1767. size:=tai_const(hp).size;
  1768. while pos<(size-4) do
  1769. begin
  1770. writer.AsmWrite(#9'.vbyte'#9'4, ');
  1771. writer.AsmWriteln(tostr(longint(tai_const(hp).value shr ((size-pos-4)*8))));
  1772. inc(pos,4);
  1773. end;
  1774. writer.AsmWrite(#9'.vbyte'#9);
  1775. writer.AsmWrite(tostr(size-pos));
  1776. writer.AsmWrite(', ');
  1777. case size-pos of
  1778. 1: writer.AsmWrite(tostr(byte(tai_const(hp).value)));
  1779. 2: writer.AsmWrite(tostr(word(tai_const(hp).value)));
  1780. 4: writer.AsmWrite(tostr(longint(tai_const(hp).value)));
  1781. else
  1782. internalerror(2012010402);
  1783. end;
  1784. end;
  1785. procedure TGNUAssembler.WriteUnalignedIntConst(hp: tai_const);
  1786. var
  1787. pos, size: longint;
  1788. begin
  1789. size:=tai_const(hp).size;
  1790. writer.AsmWrite(#9'.byte'#9);
  1791. if target_info.endian=endian_big then
  1792. begin
  1793. pos:=size-1;
  1794. while pos>=0 do
  1795. begin
  1796. writer.AsmWrite(tostr((tai_const(hp).value shr (pos*8)) and $ff));
  1797. dec(pos);
  1798. if pos>=0 then
  1799. writer.AsmWrite(', ')
  1800. else
  1801. writer.AsmLn;
  1802. end;
  1803. end
  1804. else
  1805. begin
  1806. pos:=0;
  1807. while pos<size do
  1808. begin
  1809. writer.AsmWriteln(tostr((tai_const(hp).value shr (pos*8)) and $ff));
  1810. inc(pos);
  1811. if pos<=size then
  1812. writer.AsmWrite(', ')
  1813. else
  1814. writer.AsmLn;
  1815. end;
  1816. end;
  1817. writer.AsmLn;
  1818. end;
  1819. procedure TGNUAssembler.WriteDirectiveName(dir: TAsmDirective);
  1820. begin
  1821. { TODO: implement asd_cpu for GAS => usually .arch or .cpu, but the CPU
  1822. name has to be translated as well }
  1823. if dir=asd_cpu then
  1824. writer.AsmWrite(asminfo^.comment+' CPU ')
  1825. else
  1826. writer.AsmWrite('.'+directivestr[dir]+' ');
  1827. end;
  1828. procedure TGNUAssembler.WriteAsmList;
  1829. var
  1830. n : string;
  1831. hal : tasmlisttype;
  1832. i: longint;
  1833. begin
  1834. {$ifdef EXTDEBUG}
  1835. if current_module.mainsource<>'' then
  1836. Comment(V_Debug,'Start writing gas-styled assembler output for '+current_module.mainsource);
  1837. {$endif}
  1838. if current_module.mainsource<>'' then
  1839. n:=ExtractFileName(current_module.mainsource)
  1840. else
  1841. n:=InputFileName;
  1842. { gcc does not add it either for Darwin. Grep for
  1843. TARGET_ASM_FILE_START_FILE_DIRECTIVE in gcc/config/*.h
  1844. }
  1845. if not(target_info.system in systems_darwin) then
  1846. writer.AsmWriteLn(#9'.file "'+FixFileName(n)+'"');
  1847. WriteExtraHeader;
  1848. writer.MarkEmpty;
  1849. symendcount:=0;
  1850. for hal:=low(TasmlistType) to high(TasmlistType) do
  1851. begin
  1852. if not (current_asmdata.asmlists[hal].empty) then
  1853. begin
  1854. writer.AsmWriteLn(asminfo^.comment+'Begin asmlist '+AsmlistTypeStr[hal]);
  1855. writetree(current_asmdata.asmlists[hal]);
  1856. writer.AsmWriteLn(asminfo^.comment+'End asmlist '+AsmlistTypeStr[hal]);
  1857. end;
  1858. end;
  1859. { add weak symbol markers }
  1860. for i:=0 to current_asmdata.asmsymboldict.count-1 do
  1861. if (tasmsymbol(current_asmdata.asmsymboldict[i]).bind=AB_WEAK_EXTERNAL) then
  1862. WriteWeakSymbolRef(tasmsymbol(current_asmdata.asmsymboldict[i]));
  1863. if create_smartlink_sections and
  1864. (target_info.system in systems_darwin) then
  1865. writer.AsmWriteLn(#9'.subsections_via_symbols');
  1866. { "no executable stack" marker }
  1867. { TODO: used by OpenBSD/NetBSD as well? }
  1868. if (target_info.system in (systems_linux + systems_android + systems_freebsd + systems_dragonfly)) and
  1869. not(cs_executable_stack in current_settings.moduleswitches) then
  1870. begin
  1871. writer.AsmWriteLn('.section .note.GNU-stack,"",%progbits');
  1872. end;
  1873. writer.AsmLn;
  1874. WriteExtraFooter;
  1875. {$ifdef EXTDEBUG}
  1876. if current_module.mainsource<>'' then
  1877. Comment(V_Debug,'Done writing gas-styled assembler output for '+current_module.mainsource);
  1878. {$endif EXTDEBUG}
  1879. end;
  1880. {****************************************************************************}
  1881. { Apple/GNU Assembler writer }
  1882. {****************************************************************************}
  1883. function TAppleGNUAssembler.sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;
  1884. begin
  1885. if (target_info.system in systems_darwin) then
  1886. case atype of
  1887. sec_user:
  1888. begin
  1889. result:='.section '+aname;
  1890. exit;
  1891. end;
  1892. sec_bss:
  1893. { all bss (lcomm) symbols are automatically put in the right }
  1894. { place by using the lcomm assembler directive }
  1895. atype := sec_none;
  1896. sec_debug_frame,
  1897. sec_eh_frame:
  1898. begin
  1899. result := '.section __DWARF,__debug_info,regular,debug';
  1900. exit;
  1901. end;
  1902. sec_debug_line:
  1903. begin
  1904. result := '.section __DWARF,__debug_line,regular,debug';
  1905. exit;
  1906. end;
  1907. sec_debug_info:
  1908. begin
  1909. result := '.section __DWARF,__debug_info,regular,debug';
  1910. exit;
  1911. end;
  1912. sec_debug_abbrev:
  1913. begin
  1914. result := '.section __DWARF,__debug_abbrev,regular,debug';
  1915. exit;
  1916. end;
  1917. sec_debug_aranges:
  1918. begin
  1919. result := '.section __DWARF,__debug_aranges,regular,debug';
  1920. exit;
  1921. end;
  1922. sec_debug_ranges:
  1923. begin
  1924. result := '.section __DWARF,__debug_ranges,regular,debug';
  1925. exit;
  1926. end;
  1927. sec_rodata:
  1928. begin
  1929. result := '.const_data';
  1930. exit;
  1931. end;
  1932. sec_rodata_norel:
  1933. begin
  1934. result := '.const';
  1935. exit;
  1936. end;
  1937. sec_fpc:
  1938. begin
  1939. result := '.section __TEXT, .fpc, regular, no_dead_strip';
  1940. exit;
  1941. end;
  1942. sec_code:
  1943. begin
  1944. if (aname='fpc_geteipasebx') or
  1945. (aname='fpc_geteipasecx') then
  1946. begin
  1947. result:='.section __TEXT,__textcoal_nt,coalesced,pure_instructions'#10'.weak_definition '+aname+
  1948. #10'.private_extern '+aname;
  1949. exit;
  1950. end;
  1951. end;
  1952. sec_data_nonlazy:
  1953. begin
  1954. result:='.section __DATA, __nl_symbol_ptr,non_lazy_symbol_pointers';
  1955. exit;
  1956. end;
  1957. sec_data_lazy:
  1958. begin
  1959. result:='.section __DATA, __la_symbol_ptr,lazy_symbol_pointers';
  1960. exit;
  1961. end;
  1962. sec_init_func:
  1963. begin
  1964. result:='.section __DATA, __mod_init_func, mod_init_funcs';
  1965. exit;
  1966. end;
  1967. sec_term_func:
  1968. begin
  1969. result:='.section __DATA, __mod_term_func, mod_term_funcs';
  1970. exit;
  1971. end;
  1972. low(TObjCAsmSectionType)..high(TObjCAsmSectionType):
  1973. begin
  1974. result:='.section '+objc_section_name(atype);
  1975. exit
  1976. end;
  1977. else
  1978. ;
  1979. end;
  1980. result := inherited sectionname(atype,aname,aorder);
  1981. end;
  1982. procedure TAppleGNUAssembler.WriteWeakSymbolRef(s: tasmsymbol);
  1983. begin
  1984. writer.AsmWriteLn(#9'.weak_reference '+s.name);
  1985. end;
  1986. procedure TAppleGNUAssembler.WriteDirectiveName(dir: TAsmDirective);
  1987. begin
  1988. case dir of
  1989. asd_weak_reference:
  1990. writer.AsmWrite('.weak_reference ');
  1991. asd_weak_definition:
  1992. writer.AsmWrite('.weak_definition ');
  1993. else
  1994. inherited;
  1995. end;
  1996. end;
  1997. {****************************************************************************}
  1998. { a.out/GNU Assembler writer }
  1999. {****************************************************************************}
  2000. function TAoutGNUAssembler.sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;
  2001. const
  2002. (* Translation table - replace unsupported section types with basic ones. *)
  2003. SecXTable: array[TAsmSectionType] of TAsmSectionType = (
  2004. sec_none,
  2005. sec_none,
  2006. sec_code,
  2007. sec_data,
  2008. sec_data (* sec_rodata *),
  2009. sec_data (* sec_rodata_norel *),
  2010. sec_bss,
  2011. sec_data (* sec_threadvar *),
  2012. { used for wince exception handling }
  2013. sec_code (* sec_pdata *),
  2014. { used for darwin import stubs }
  2015. sec_code (* sec_stub *),
  2016. sec_data,(* sec_data_nonlazy *)
  2017. sec_data,(* sec_data_lazy *)
  2018. sec_data,(* sec_init_func *)
  2019. sec_data,(* sec_term_func *)
  2020. { stabs }
  2021. sec_stab,sec_stabstr,
  2022. { win32 }
  2023. sec_data (* sec_idata2 *),
  2024. sec_data (* sec_idata4 *),
  2025. sec_data (* sec_idata5 *),
  2026. sec_data (* sec_idata6 *),
  2027. sec_data (* sec_idata7 *),
  2028. sec_data (* sec_edata *),
  2029. { C++ exception handling unwinding (uses dwarf) }
  2030. sec_eh_frame,
  2031. { dwarf }
  2032. sec_debug_frame,
  2033. sec_debug_info,
  2034. sec_debug_line,
  2035. sec_debug_abbrev,
  2036. sec_debug_aranges,
  2037. sec_debug_ranges,
  2038. sec_debug_loc,
  2039. sec_debug_loclists,
  2040. { ELF resources (+ references to stabs debug information sections) }
  2041. sec_code (* sec_fpc *),
  2042. { Table of contents section }
  2043. sec_code (* sec_toc *),
  2044. sec_code (* sec_init *),
  2045. sec_code (* sec_fini *),
  2046. sec_none (* sec_objc_class *),
  2047. sec_none (* sec_objc_meta_class *),
  2048. sec_none (* sec_objc_cat_cls_meth *),
  2049. sec_none (* sec_objc_cat_inst_meth *),
  2050. sec_none (* sec_objc_protocol *),
  2051. sec_none (* sec_objc_string_object *),
  2052. sec_none (* sec_objc_cls_meth *),
  2053. sec_none (* sec_objc_inst_meth *),
  2054. sec_none (* sec_objc_cls_refs *),
  2055. sec_none (* sec_objc_message_refs *),
  2056. sec_none (* sec_objc_symbols *),
  2057. sec_none (* sec_objc_category *),
  2058. sec_none (* sec_objc_class_vars *),
  2059. sec_none (* sec_objc_instance_vars *),
  2060. sec_none (* sec_objc_module_info *),
  2061. sec_none (* sec_objc_class_names *),
  2062. sec_none (* sec_objc_meth_var_types *),
  2063. sec_none (* sec_objc_meth_var_names *),
  2064. sec_none (* sec_objc_selector_strs *),
  2065. sec_none (* sec_objc_protocol_ext *),
  2066. sec_none (* sec_objc_class_ext *),
  2067. sec_none (* sec_objc_property *),
  2068. sec_none (* sec_objc_image_info *),
  2069. sec_none (* sec_objc_cstring_object *),
  2070. sec_none (* sec_objc_sel_fixup *),
  2071. sec_none (* sec_objc_data *),
  2072. sec_none (* sec_objc_const *),
  2073. sec_none (* sec_objc_sup_refs *),
  2074. sec_none (* sec_data_coalesced *),
  2075. sec_none (* sec_objc_classlist *),
  2076. sec_none (* sec_objc_nlclasslist *),
  2077. sec_none (* sec_objc_catlist *),
  2078. sec_none (* sec_objc_nlcatlist *),
  2079. sec_none (* sec_objc_protlist *),
  2080. sec_none (* sec_stack *),
  2081. sec_none (* sec_heap *),
  2082. sec_none (* gcc_except_table *),
  2083. sec_none (* sec_arm_attribute *)
  2084. );
  2085. begin
  2086. Result := inherited SectionName (SecXTable [AType], AName, AOrder);
  2087. end;
  2088. {****************************************************************************}
  2089. { Abstract Instruction Writer }
  2090. {****************************************************************************}
  2091. constructor TCPUInstrWriter.create(_owner: TGNUAssembler);
  2092. begin
  2093. inherited create;
  2094. owner := _owner;
  2095. end;
  2096. end.