aggas.pas 80 KB

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