aggas.pas 72 KB

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