aggas.pas 80 KB

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