aggas.pas 78 KB

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