aggas.pas 71 KB

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