aggas.pas 77 KB

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