aggas.pas 78 KB

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