aggas.pas 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507
  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. interface
  23. uses
  24. cclasses,
  25. globtype,globals,
  26. aasmbase,aasmtai,aasmdata,aasmcpu,
  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. procedure WriteSection(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder);
  38. procedure WriteExtraHeader;virtual;
  39. procedure WriteInstruction(hp: tai);
  40. procedure WriteWeakSymbolDef(s: tasmsymbol); virtual;
  41. public
  42. function MakeCmdLine: TCmdStr; override;
  43. procedure WriteTree(p:TAsmList);override;
  44. procedure WriteAsmList;override;
  45. destructor destroy; override;
  46. private
  47. setcount: longint;
  48. procedure WriteDecodedSleb128(a: int64);
  49. procedure WriteDecodedUleb128(a: qword);
  50. function NextSetLabel: string;
  51. protected
  52. InstrWriter: TCPUInstrWriter;
  53. end;
  54. {# This is the base class for writing instructions.
  55. The WriteInstruction() method must be overriden
  56. to write a single instruction to the assembler
  57. file.
  58. }
  59. TCPUInstrWriter = class
  60. constructor create(_owner: TGNUAssembler);
  61. procedure WriteInstruction(hp : tai); virtual; abstract;
  62. protected
  63. owner: TGNUAssembler;
  64. end;
  65. { TAppleGNUAssembler }
  66. TAppleGNUAssembler=class(TGNUAssembler)
  67. protected
  68. function sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;override;
  69. procedure WriteWeakSymbolDef(s: tasmsymbol); override;
  70. end;
  71. TAoutGNUAssembler=class(TGNUAssembler)
  72. function sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;override;
  73. end;
  74. implementation
  75. uses
  76. SysUtils,
  77. cutils,cfileutl,systems,
  78. fmodule,finput,verbose,
  79. itcpugas,cpubase
  80. ;
  81. const
  82. line_length = 70;
  83. var
  84. symendcount : longint;
  85. type
  86. {$ifdef cpuextended}
  87. t80bitarray = array[0..9] of byte;
  88. {$endif cpuextended}
  89. t64bitarray = array[0..7] of byte;
  90. t32bitarray = array[0..3] of byte;
  91. {****************************************************************************}
  92. { Support routines }
  93. {****************************************************************************}
  94. function fixline(s:string):string;
  95. {
  96. return s with all leading and ending spaces and tabs removed
  97. }
  98. var
  99. i,j,k : integer;
  100. begin
  101. i:=length(s);
  102. while (i>0) and (s[i] in [#9,' ']) do
  103. dec(i);
  104. j:=1;
  105. while (j<i) and (s[j] in [#9,' ']) do
  106. inc(j);
  107. for k:=j to i do
  108. if s[k] in [#0..#31,#127..#255] then
  109. s[k]:='.';
  110. fixline:=Copy(s,j,i-j+1);
  111. end;
  112. function single2str(d : single) : string;
  113. var
  114. hs : string;
  115. begin
  116. str(d,hs);
  117. { replace space with + }
  118. if hs[1]=' ' then
  119. hs[1]:='+';
  120. single2str:='0d'+hs
  121. end;
  122. function double2str(d : double) : string;
  123. var
  124. hs : string;
  125. begin
  126. str(d,hs);
  127. { replace space with + }
  128. if hs[1]=' ' then
  129. hs[1]:='+';
  130. double2str:='0d'+hs
  131. end;
  132. function extended2str(e : extended) : string;
  133. var
  134. hs : string;
  135. begin
  136. str(e,hs);
  137. { replace space with + }
  138. if hs[1]=' ' then
  139. hs[1]:='+';
  140. extended2str:='0d'+hs
  141. end;
  142. { convert floating point values }
  143. { to correct endian }
  144. procedure swap64bitarray(var t: t64bitarray);
  145. var
  146. b: byte;
  147. begin
  148. b:= t[7];
  149. t[7] := t[0];
  150. t[0] := b;
  151. b := t[6];
  152. t[6] := t[1];
  153. t[1] := b;
  154. b:= t[5];
  155. t[5] := t[2];
  156. t[2] := b;
  157. b:= t[4];
  158. t[4] := t[3];
  159. t[3] := b;
  160. end;
  161. procedure swap32bitarray(var t: t32bitarray);
  162. var
  163. b: byte;
  164. begin
  165. b:= t[1];
  166. t[1]:= t[2];
  167. t[2]:= b;
  168. b:= t[0];
  169. t[0]:= t[3];
  170. t[3]:= b;
  171. end;
  172. const
  173. ait_const2str : array[aitconst_128bit..aitconst_darwin_dwarf_delta32] of string[20]=(
  174. #9'.fixme128'#9,#9'.quad'#9,#9'.long'#9,#9'.short'#9,#9'.byte'#9,
  175. #9'.sleb128'#9,#9'.uleb128'#9,
  176. #9'.rva'#9,#9'.secrel32'#9,#9'.indirect_symbol'#9,#9'.quad'#9,#9'.long'#9
  177. );
  178. {****************************************************************************}
  179. { GNU Assembler writer }
  180. {****************************************************************************}
  181. destructor TGNUAssembler.Destroy;
  182. begin
  183. InstrWriter.free;
  184. inherited destroy;
  185. end;
  186. function TGNUAssembler.MakeCmdLine: TCmdStr;
  187. begin
  188. result := inherited MakeCmdLine;
  189. // MWE: disabled again. It generates dwarf info for the generated .s
  190. // files as well. This conflicts with the info we generate
  191. // if target_dbg.id = dbg_dwarf then
  192. // result := result + ' --gdwarf-2';
  193. end;
  194. function TGNUAssembler.NextSetLabel: string;
  195. begin
  196. inc(setcount);
  197. result := target_asm.labelprefix+'$set$'+tostr(setcount);
  198. end;
  199. function TGNUAssembler.sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;
  200. const
  201. secnames : array[TAsmSectiontype] of string[length('__DATA, __datacoal_nt,coalesced')] = ('',
  202. '.text',
  203. '.data',
  204. { why doesn't .rodata work? (FK) }
  205. { sometimes we have to create a data.rel.ro instead of .rodata, e.g. for }
  206. { vtables (and anything else containing relocations), otherwise those are }
  207. { not relocated properly on e.g. linux/ppc64. g++ generates there for a }
  208. { vtable for a class called Window: }
  209. { .section .data.rel.ro._ZTV6Window,"awG",@progbits,_ZTV6Window,comdat }
  210. { TODO: .data.ro not yet working}
  211. {$if defined(arm) or defined(powerpc)}
  212. '.rodata',
  213. {$else arm}
  214. '.data',
  215. {$endif arm}
  216. {$if defined(m68k)} { Amiga/m68k GNU AS doesn't seem to like .rodata (KB) }
  217. '.data',
  218. {$else}
  219. '.rodata',
  220. {$endif}
  221. '.bss',
  222. '.threadvar',
  223. '.pdata',
  224. '', { stubs }
  225. '.stab',
  226. '.stabstr',
  227. '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
  228. '.eh_frame',
  229. '.debug_frame','.debug_info','.debug_line','.debug_abbrev',
  230. '.fpc',
  231. '.toc',
  232. '.init',
  233. '.fini',
  234. '.objc_class',
  235. '.objc_meta_class',
  236. '.objc_cat_cls_meth',
  237. '.objc_cat_inst_meth',
  238. '.objc_protocol',
  239. '.objc_string_object',
  240. '.objc_cls_meth',
  241. '.objc_inst_meth',
  242. '.objc_cls_refs',
  243. '.objc_message_refs',
  244. '.objc_symbols',
  245. '.objc_category',
  246. '.objc_class_vars',
  247. '.objc_instance_vars',
  248. '.objc_module_info',
  249. '.objc_class_names',
  250. '.objc_meth_var_types',
  251. '.objc_meth_var_names',
  252. '.objc_selector_strs',
  253. '.objc_protocol_ext',
  254. '.objc_class_ext',
  255. '.objc_property',
  256. '.objc_image_info',
  257. '.objc_cstring_object',
  258. '.objc_sel_fixup',
  259. '__DATA,__objc_data',
  260. '__DATA,__objc_const',
  261. '.objc_superrefs',
  262. '__DATA, __datacoal_nt,coalesced',
  263. '.objc_classlist',
  264. '.objc_nlclasslist',
  265. '.objc_catlist',
  266. '.obcj_nlcatlist',
  267. '.objc_protolist'
  268. );
  269. secnames_pic : array[TAsmSectiontype] of string[length('__DATA, __datacoal_nt,coalesced')] = ('',
  270. '.text',
  271. '.data.rel',
  272. '.data.rel',
  273. '.data.rel',
  274. '.bss',
  275. '.threadvar',
  276. '.pdata',
  277. '', { stubs }
  278. '.stab',
  279. '.stabstr',
  280. '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
  281. '.eh_frame',
  282. '.debug_frame','.debug_info','.debug_line','.debug_abbrev',
  283. '.fpc',
  284. '.toc',
  285. '.init',
  286. '.fini',
  287. '.objc_class',
  288. '.objc_meta_class',
  289. '.objc_cat_cls_meth',
  290. '.objc_cat_inst_meth',
  291. '.objc_protocol',
  292. '.objc_string_object',
  293. '.objc_cls_meth',
  294. '.objc_inst_meth',
  295. '.objc_cls_refs',
  296. '.objc_message_refs',
  297. '.objc_symbols',
  298. '.objc_category',
  299. '.objc_class_vars',
  300. '.objc_instance_vars',
  301. '.objc_module_info',
  302. '.objc_class_names',
  303. '.objc_meth_var_types',
  304. '.objc_meth_var_names',
  305. '.objc_selector_strs',
  306. '.objc_protocol_ext',
  307. '.objc_class_ext',
  308. '.objc_property',
  309. '.objc_image_info',
  310. '.objc_cstring_object',
  311. '.objc_sel_fixup',
  312. '__DATA, __objc_data',
  313. '__DATA, __objc_const',
  314. '.objc_superrefs',
  315. '__DATA, __datacoal_nt,coalesced',
  316. '.objc_classlist',
  317. '.objc_nlclasslist',
  318. '.objc_catlist',
  319. '.obcj_nlcatlist',
  320. '.objc_protolist'
  321. );
  322. var
  323. sep : string[3];
  324. secname : string;
  325. begin
  326. if (cs_create_pic in current_settings.moduleswitches) and
  327. not(target_info.system in systems_darwin) then
  328. secname:=secnames_pic[atype]
  329. else
  330. secname:=secnames[atype];
  331. {$ifdef m68k}
  332. { old Amiga GNU AS doesn't support .section .fpc }
  333. if (atype=sec_fpc) and (target_info.system = system_m68k_amiga) then
  334. secname:=secnames[sec_data];
  335. {$endif}
  336. if (atype=sec_fpc) and (Copy(aname,1,3)='res') then
  337. begin
  338. result:=secname+'.'+aname;
  339. exit;
  340. end;
  341. if (atype=sec_threadvar) and
  342. (target_info.system=system_i386_win32) then
  343. secname:='.tls';
  344. { go32v2 stub only loads .text and .data sections, and allocates space for .bss.
  345. Thus, data which normally goes into .rodata and .rodata_norel sections must
  346. end up in .data section }
  347. if (atype in [sec_rodata,sec_rodata_norel]) and
  348. (target_info.system=system_i386_go32v2) then
  349. secname:='.data';
  350. { For bss we need to set some flags that are target dependent,
  351. it is easier to disable it for smartlinking. It doesn't take up
  352. filespace }
  353. if not(target_info.system in systems_darwin) and
  354. create_smartlink_sections and
  355. (aname<>'') and
  356. (atype<>sec_toc) and
  357. { on embedded systems every byte counts, so smartlink bss too }
  358. ((atype<>sec_bss) or (target_info.system in system_embedded)) then
  359. begin
  360. case aorder of
  361. secorder_begin :
  362. sep:='.b_';
  363. secorder_end :
  364. sep:='.z_';
  365. else
  366. sep:='.n_';
  367. end;
  368. result:=secname+sep+aname
  369. end
  370. else
  371. result:=secname;
  372. end;
  373. procedure TGNUAssembler.WriteSection(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder);
  374. var
  375. s : string;
  376. begin
  377. AsmLn;
  378. case target_info.system of
  379. system_i386_OS2,
  380. system_i386_EMX,
  381. system_m68k_amiga, { amiga has old GNU AS (2.14), which blews up from .section (KB) }
  382. system_m68k_linux: ;
  383. system_powerpc_darwin,
  384. system_i386_darwin,
  385. system_powerpc64_darwin,
  386. system_x86_64_darwin,
  387. system_arm_darwin:
  388. begin
  389. if (atype in [sec_stub,sec_objc_data,sec_objc_const,sec_data_coalesced]) then
  390. AsmWrite('.section ');
  391. end
  392. else
  393. AsmWrite('.section ');
  394. end;
  395. s:=sectionname(atype,aname,aorder);
  396. AsmWrite(s);
  397. case atype of
  398. sec_fpc :
  399. if aname = 'resptrs' then
  400. AsmWrite(', "a", @progbits');
  401. sec_stub :
  402. begin
  403. case target_info.system of
  404. { there are processor-independent shortcuts available }
  405. { for this, namely .symbol_stub and .picsymbol_stub, but }
  406. { they don't work and gcc doesn't use them either... }
  407. system_powerpc_darwin,
  408. system_powerpc64_darwin:
  409. if (cs_create_pic in current_settings.moduleswitches) then
  410. AsmWriteln('__TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32')
  411. else
  412. AsmWriteln('__TEXT,__symbol_stub1,symbol_stubs,pure_instructions,16');
  413. system_i386_darwin:
  414. AsmWriteln('__IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5');
  415. system_arm_darwin:
  416. if (cs_create_pic in current_settings.moduleswitches) then
  417. AsmWriteln('.section __TEXT,__picsymbolstub4,symbol_stubs,none,16')
  418. else
  419. AsmWriteln('.section __TEXT,__symbol_stub4,symbol_stubs,none,12')
  420. { darwin/x86-64 uses RIP-based GOT addressing, no symbol stubs }
  421. else
  422. internalerror(2006031101);
  423. end;
  424. end;
  425. end;
  426. AsmLn;
  427. LastSecType:=atype;
  428. end;
  429. procedure TGNUAssembler.WriteDecodedUleb128(a: qword);
  430. var
  431. i,len : longint;
  432. buf : array[0..63] of byte;
  433. begin
  434. len:=EncodeUleb128(a,buf);
  435. for i:=0 to len-1 do
  436. begin
  437. if (i > 0) then
  438. AsmWrite(',');
  439. AsmWrite(tostr(buf[i]));
  440. end;
  441. end;
  442. procedure TGNUAssembler.WriteDecodedSleb128(a: int64);
  443. var
  444. i,len : longint;
  445. buf : array[0..255] of byte;
  446. begin
  447. len:=EncodeSleb128(a,buf);
  448. for i:=0 to len-1 do
  449. begin
  450. if (i > 0) then
  451. AsmWrite(',');
  452. AsmWrite(tostr(buf[i]));
  453. end;
  454. end;
  455. procedure TGNUAssembler.WriteTree(p:TAsmList);
  456. function needsObject(hp : tai_symbol) : boolean;
  457. begin
  458. needsObject :=
  459. (
  460. assigned(hp.next) and
  461. (tai(hp.next).typ in [ait_const,ait_datablock,
  462. ait_real_32bit,ait_real_64bit,ait_real_80bit,ait_comp_64bit])
  463. ) or
  464. (hp.sym.typ=AT_DATA);
  465. end;
  466. var
  467. ch : char;
  468. hp : tai;
  469. hp1 : tailineinfo;
  470. constdef : taiconst_type;
  471. s,t : string;
  472. i,pos,l : longint;
  473. InlineLevel : longint;
  474. last_align : longint;
  475. co : comp;
  476. sin : single;
  477. d : double;
  478. {$ifdef cpuextended}
  479. e : extended;
  480. {$endif cpuextended}
  481. do_line : boolean;
  482. sepChar : char;
  483. begin
  484. if not assigned(p) then
  485. exit;
  486. last_align := 2;
  487. InlineLevel:=0;
  488. { lineinfo is only needed for al_procedures (PFV) }
  489. do_line:=(cs_asm_source in current_settings.globalswitches) or
  490. ((cs_lineinfo in current_settings.moduleswitches)
  491. and (p=current_asmdata.asmlists[al_procedures]));
  492. hp:=tai(p.first);
  493. while assigned(hp) do
  494. begin
  495. if not(hp.typ in SkipLineInfo) then
  496. begin
  497. hp1 := hp as tailineinfo;
  498. current_filepos:=hp1.fileinfo;
  499. { no line info for inlined code }
  500. if do_line and (inlinelevel=0) then
  501. begin
  502. { load infile }
  503. if lastfileinfo.fileindex<>hp1.fileinfo.fileindex then
  504. begin
  505. infile:=current_module.sourcefiles.get_file(hp1.fileinfo.fileindex);
  506. if assigned(infile) then
  507. begin
  508. { open only if needed !! }
  509. if (cs_asm_source in current_settings.globalswitches) then
  510. infile.open;
  511. end;
  512. { avoid unnecessary reopens of the same file !! }
  513. lastfileinfo.fileindex:=hp1.fileinfo.fileindex;
  514. { be sure to change line !! }
  515. lastfileinfo.line:=-1;
  516. end;
  517. { write source }
  518. if (cs_asm_source in current_settings.globalswitches) and
  519. assigned(infile) then
  520. begin
  521. if (infile<>lastinfile) then
  522. begin
  523. AsmWriteLn(target_asm.comment+'['+infile.name^+']');
  524. if assigned(lastinfile) then
  525. lastinfile.close;
  526. end;
  527. if (hp1.fileinfo.line<>lastfileinfo.line) and
  528. ((hp1.fileinfo.line<infile.maxlinebuf) or (InlineLevel>0)) then
  529. begin
  530. if (hp1.fileinfo.line<>0) and
  531. ((infile.linebuf^[hp1.fileinfo.line]>=0) or (InlineLevel>0)) then
  532. AsmWriteLn(target_asm.comment+'['+tostr(hp1.fileinfo.line)+'] '+
  533. fixline(infile.GetLineStr(hp1.fileinfo.line)));
  534. { set it to a negative value !
  535. to make that is has been read already !! PM }
  536. if (infile.linebuf^[hp1.fileinfo.line]>=0) then
  537. infile.linebuf^[hp1.fileinfo.line]:=-infile.linebuf^[hp1.fileinfo.line]-1;
  538. end;
  539. end;
  540. lastfileinfo:=hp1.fileinfo;
  541. lastinfile:=infile;
  542. end;
  543. end;
  544. case hp.typ of
  545. ait_comment :
  546. Begin
  547. AsmWrite(target_asm.comment);
  548. AsmWritePChar(tai_comment(hp).str);
  549. AsmLn;
  550. End;
  551. ait_regalloc :
  552. begin
  553. if (cs_asm_regalloc in current_settings.globalswitches) then
  554. begin
  555. AsmWrite(#9+target_asm.comment+'Register ');
  556. repeat
  557. AsmWrite(std_regname(Tai_regalloc(hp).reg));
  558. if (hp.next=nil) or
  559. (tai(hp.next).typ<>ait_regalloc) or
  560. (tai_regalloc(hp.next).ratype<>tai_regalloc(hp).ratype) then
  561. break;
  562. hp:=tai(hp.next);
  563. AsmWrite(',');
  564. until false;
  565. AsmWrite(' ');
  566. AsmWriteLn(regallocstr[tai_regalloc(hp).ratype]);
  567. end;
  568. end;
  569. ait_tempalloc :
  570. begin
  571. if (cs_asm_tempalloc in current_settings.globalswitches) then
  572. begin
  573. {$ifdef EXTDEBUG}
  574. if assigned(tai_tempalloc(hp).problem) then
  575. AsmWriteLn(target_asm.comment+'Temp '+tostr(tai_tempalloc(hp).temppos)+','+
  576. tostr(tai_tempalloc(hp).tempsize)+' '+tai_tempalloc(hp).problem^)
  577. else
  578. {$endif EXTDEBUG}
  579. AsmWriteLn(target_asm.comment+'Temp '+tostr(tai_tempalloc(hp).temppos)+','+
  580. tostr(tai_tempalloc(hp).tempsize)+' '+tempallocstr[tai_tempalloc(hp).allocation]);
  581. end;
  582. end;
  583. ait_align :
  584. begin
  585. last_align := tai_align_abstract(hp).aligntype;
  586. if tai_align_abstract(hp).aligntype>1 then
  587. begin
  588. if not(target_info.system in systems_darwin) then
  589. begin
  590. AsmWrite(#9'.balign '+tostr(tai_align_abstract(hp).aligntype));
  591. if tai_align_abstract(hp).use_op then
  592. AsmWrite(','+tostr(tai_align_abstract(hp).fillop))
  593. {$ifdef x86}
  594. { force NOP as alignment op code }
  595. else if LastSecType=sec_code then
  596. AsmWrite(',0x90');
  597. {$endif x86}
  598. end
  599. else
  600. begin
  601. { darwin as only supports .align }
  602. if not ispowerof2(tai_align_abstract(hp).aligntype,i) then
  603. internalerror(2003010305);
  604. AsmWrite(#9'.align '+tostr(i));
  605. last_align := i;
  606. end;
  607. AsmLn;
  608. end;
  609. end;
  610. ait_section :
  611. begin
  612. if tai_section(hp).sectype<>sec_none then
  613. WriteSection(tai_section(hp).sectype,tai_section(hp).name^,tai_section(hp).secorder)
  614. else
  615. begin
  616. {$ifdef EXTDEBUG}
  617. AsmWrite(target_asm.comment);
  618. AsmWriteln(' sec_none');
  619. {$endif EXTDEBUG}
  620. end;
  621. end;
  622. ait_datablock :
  623. begin
  624. if (target_info.system in systems_darwin) then
  625. begin
  626. { On Mac OS X you can't have common symbols in a shared library
  627. since those are in the TEXT section and the text section is
  628. read-only in shared libraries (so it can be shared among different
  629. processes). The alternate code creates some kind of common symbols
  630. in the data segment.
  631. }
  632. if tai_datablock(hp).is_global then
  633. begin
  634. asmwrite('.globl ');
  635. asmwriteln(tai_datablock(hp).sym.name);
  636. asmwriteln('.data');
  637. asmwrite('.zerofill __DATA, __common, ');
  638. asmwrite(tai_datablock(hp).sym.name);
  639. asmwriteln(', '+tostr(tai_datablock(hp).size)+','+tostr(last_align));
  640. if not(LastSecType in [sec_data,sec_none]) then
  641. writesection(LastSecType,'',secorder_default);
  642. end
  643. else
  644. begin
  645. asmwrite(#9'.lcomm'#9);
  646. asmwrite(tai_datablock(hp).sym.name);
  647. asmwrite(','+tostr(tai_datablock(hp).size));
  648. asmwrite(','+tostr(last_align));
  649. asmln;
  650. end;
  651. end
  652. else
  653. begin
  654. {$ifdef USE_COMM_IN_BSS}
  655. if writingpackages then
  656. begin
  657. { The .comm is required for COMMON symbols. These are used
  658. in the shared library loading. All the symbols declared in
  659. the .so file need to resolve to the data allocated in the main
  660. program (PFV) }
  661. if tai_datablock(hp).is_global then
  662. begin
  663. asmwrite(#9'.comm'#9);
  664. asmwrite(tai_datablock(hp).sym.name);
  665. asmwrite(','+tostr(tai_datablock(hp).size));
  666. asmwrite(','+tostr(last_align));
  667. asmln;
  668. end
  669. else
  670. begin
  671. asmwrite(#9'.lcomm'#9);
  672. asmwrite(tai_datablock(hp).sym.name);
  673. asmwrite(','+tostr(tai_datablock(hp).size));
  674. asmwrite(','+tostr(last_align));
  675. asmln;
  676. end
  677. end
  678. else
  679. {$endif USE_COMM_IN_BSS}
  680. begin
  681. if Tai_datablock(hp).is_global then
  682. begin
  683. asmwrite(#9'.globl ');
  684. asmwriteln(Tai_datablock(hp).sym.name);
  685. end;
  686. if (target_info.system <> system_arm_linux) then
  687. sepChar := '@'
  688. else
  689. sepChar := '%';
  690. if (tf_needs_symbol_type in target_info.flags) then
  691. asmwriteln(#9'.type '+Tai_datablock(hp).sym.name+','+sepChar+'object');
  692. if (tf_needs_symbol_size in target_info.flags) and (tai_datablock(hp).size > 0) then
  693. asmwriteln(#9'.size '+Tai_datablock(hp).sym.name+','+tostr(Tai_datablock(hp).size));
  694. asmwrite(Tai_datablock(hp).sym.name);
  695. asmwriteln(':');
  696. asmwriteln(#9'.zero '+tostr(Tai_datablock(hp).size));
  697. end;
  698. end;
  699. end;
  700. ait_const:
  701. begin
  702. constdef:=tai_const(hp).consttype;
  703. case constdef of
  704. {$ifndef cpu64bitaddr}
  705. aitconst_128bit :
  706. begin
  707. internalerror(200404291);
  708. end;
  709. aitconst_64bit :
  710. begin
  711. if assigned(tai_const(hp).sym) then
  712. internalerror(200404292);
  713. AsmWrite(ait_const2str[aitconst_32bit]);
  714. if target_info.endian = endian_little then
  715. begin
  716. AsmWrite(tostr(longint(lo(tai_const(hp).value))));
  717. AsmWrite(',');
  718. AsmWrite(tostr(longint(hi(tai_const(hp).value))));
  719. end
  720. else
  721. begin
  722. AsmWrite(tostr(longint(hi(tai_const(hp).value))));
  723. AsmWrite(',');
  724. AsmWrite(tostr(longint(lo(tai_const(hp).value))));
  725. end;
  726. AsmLn;
  727. end;
  728. {$endif cpu64bitaddr}
  729. aitconst_uleb128bit,
  730. aitconst_sleb128bit,
  731. {$ifdef cpu64bitaddr}
  732. aitconst_128bit,
  733. aitconst_64bit,
  734. {$endif cpu64bitaddr}
  735. aitconst_32bit,
  736. aitconst_16bit,
  737. aitconst_8bit,
  738. aitconst_rva_symbol,
  739. aitconst_secrel32_symbol,
  740. aitconst_indirect_symbol,
  741. aitconst_darwin_dwarf_delta32,
  742. aitconst_darwin_dwarf_delta64:
  743. begin
  744. if (target_info.system in systems_darwin) and
  745. (constdef in [aitconst_uleb128bit,aitconst_sleb128bit]) then
  746. begin
  747. AsmWrite(ait_const2str[aitconst_8bit]);
  748. case tai_const(hp).consttype of
  749. aitconst_uleb128bit:
  750. WriteDecodedUleb128(qword(tai_const(hp).value));
  751. aitconst_sleb128bit:
  752. WriteDecodedSleb128(int64(tai_const(hp).value));
  753. end
  754. end
  755. else
  756. begin
  757. AsmWrite(ait_const2str[constdef]);
  758. l:=0;
  759. t := '';
  760. repeat
  761. if assigned(tai_const(hp).sym) then
  762. begin
  763. if assigned(tai_const(hp).endsym) then
  764. begin
  765. if (constdef in [aitconst_darwin_dwarf_delta32,aitconst_darwin_dwarf_delta64]) then
  766. begin
  767. s := NextSetLabel;
  768. t := #9'.set '+s+','+tai_const(hp).endsym.name+'-'+tai_const(hp).sym.name;
  769. end
  770. else
  771. s:=tai_const(hp).endsym.name+'-'+tai_const(hp).sym.name
  772. end
  773. else
  774. s:=tai_const(hp).sym.name;
  775. if tai_const(hp).value<>0 then
  776. s:=s+tostr_with_plus(tai_const(hp).value);
  777. end
  778. else
  779. s:=tostr(tai_const(hp).value);
  780. AsmWrite(s);
  781. inc(l,length(s));
  782. { Values with symbols are written on a single line to improve
  783. reading of the .s file (PFV) }
  784. if assigned(tai_const(hp).sym) or
  785. not(LastSecType in [sec_data,sec_rodata,sec_rodata_norel]) or
  786. (l>line_length) or
  787. (hp.next=nil) or
  788. (tai(hp.next).typ<>ait_const) or
  789. (tai_const(hp.next).consttype<>constdef) or
  790. assigned(tai_const(hp.next).sym) then
  791. break;
  792. hp:=tai(hp.next);
  793. AsmWrite(',');
  794. until false;
  795. if (t <> '') then
  796. begin
  797. AsmLn;
  798. AsmWrite(t);
  799. end;
  800. end;
  801. AsmLn;
  802. end;
  803. else
  804. internalerror(200704251);
  805. end;
  806. end;
  807. { the "and defined(FPC_HAS_TYPE_EXTENDED)" isn't optimal but currently the only solution
  808. it prevents proper cross compilation to i386 though
  809. }
  810. {$if defined(cpuextended) and defined(FPC_HAS_TYPE_EXTENDED)}
  811. ait_real_80bit :
  812. begin
  813. if do_line then
  814. AsmWriteLn(target_asm.comment+'value: '+extended2str(tai_real_80bit(hp).value));
  815. { Make sure e is a extended type, bestreal could be
  816. a different type (bestreal) !! (PFV) }
  817. e:=tai_real_80bit(hp).value;
  818. AsmWrite(#9'.byte'#9);
  819. for i:=0 to 9 do
  820. begin
  821. if i<>0 then
  822. AsmWrite(',');
  823. AsmWrite(tostr(t80bitarray(e)[i]));
  824. end;
  825. AsmLn;
  826. end;
  827. {$endif cpuextended}
  828. ait_real_64bit :
  829. begin
  830. if do_line then
  831. AsmWriteLn(target_asm.comment+'value: '+double2str(tai_real_64bit(hp).value));
  832. d:=tai_real_64bit(hp).value;
  833. { swap the values to correct endian if required }
  834. if source_info.endian <> target_info.endian then
  835. swap64bitarray(t64bitarray(d));
  836. AsmWrite(#9'.byte'#9);
  837. {$ifdef arm}
  838. if tai_real_64bit(hp).formatoptions=fo_hiloswapped then
  839. begin
  840. for i:=4 to 7 do
  841. begin
  842. if i<>4 then
  843. AsmWrite(',');
  844. AsmWrite(tostr(t64bitarray(d)[i]));
  845. end;
  846. for i:=0 to 3 do
  847. begin
  848. AsmWrite(',');
  849. AsmWrite(tostr(t64bitarray(d)[i]));
  850. end;
  851. end
  852. else
  853. {$endif arm}
  854. begin
  855. for i:=0 to 7 do
  856. begin
  857. if i<>0 then
  858. AsmWrite(',');
  859. AsmWrite(tostr(t64bitarray(d)[i]));
  860. end;
  861. end;
  862. AsmLn;
  863. end;
  864. ait_real_32bit :
  865. begin
  866. if do_line then
  867. AsmWriteLn(target_asm.comment+'value: '+single2str(tai_real_32bit(hp).value));
  868. sin:=tai_real_32bit(hp).value;
  869. { swap the values to correct endian if required }
  870. if source_info.endian <> target_info.endian then
  871. swap32bitarray(t32bitarray(sin));
  872. AsmWrite(#9'.byte'#9);
  873. for i:=0 to 3 do
  874. begin
  875. if i<>0 then
  876. AsmWrite(',');
  877. AsmWrite(tostr(t32bitarray(sin)[i]));
  878. end;
  879. AsmLn;
  880. end;
  881. ait_comp_64bit :
  882. begin
  883. if do_line then
  884. AsmWriteLn(target_asm.comment+'value: '+extended2str(tai_comp_64bit(hp).value));
  885. AsmWrite(#9'.byte'#9);
  886. co:=comp(tai_comp_64bit(hp).value);
  887. { swap the values to correct endian if required }
  888. if source_info.endian <> target_info.endian then
  889. swap64bitarray(t64bitarray(co));
  890. for i:=0 to 7 do
  891. begin
  892. if i<>0 then
  893. AsmWrite(',');
  894. AsmWrite(tostr(t64bitarray(co)[i]));
  895. end;
  896. AsmLn;
  897. end;
  898. ait_string :
  899. begin
  900. pos:=0;
  901. for i:=1 to tai_string(hp).len do
  902. begin
  903. if pos=0 then
  904. begin
  905. AsmWrite(#9'.ascii'#9'"');
  906. pos:=20;
  907. end;
  908. ch:=tai_string(hp).str[i-1];
  909. case ch of
  910. #0, {This can't be done by range, because a bug in FPC}
  911. #1..#31,
  912. #128..#255 : s:='\'+tostr(ord(ch) shr 6)+tostr((ord(ch) and 63) shr 3)+tostr(ord(ch) and 7);
  913. '"' : s:='\"';
  914. '\' : s:='\\';
  915. else
  916. s:=ch;
  917. end;
  918. AsmWrite(s);
  919. inc(pos,length(s));
  920. if (pos>line_length) or (i=tai_string(hp).len) then
  921. begin
  922. AsmWriteLn('"');
  923. pos:=0;
  924. end;
  925. end;
  926. end;
  927. ait_label :
  928. begin
  929. if (tai_label(hp).labsym.is_used) then
  930. begin
  931. if (tai_label(hp).labsym.bind=AB_PRIVATE_EXTERN) then
  932. begin
  933. AsmWrite(#9'.private_extern ');
  934. AsmWriteln(tai_label(hp).labsym.name);
  935. end;
  936. if tai_label(hp).labsym.bind in [AB_GLOBAL,AB_PRIVATE_EXTERN] then
  937. begin
  938. AsmWrite('.globl'#9);
  939. AsmWriteLn(tai_label(hp).labsym.name);
  940. end;
  941. AsmWrite(tai_label(hp).labsym.name);
  942. AsmWriteLn(':');
  943. end;
  944. end;
  945. ait_symbol :
  946. begin
  947. if (tai_symbol(hp).sym.bind=AB_PRIVATE_EXTERN) then
  948. begin
  949. AsmWrite(#9'.private_extern ');
  950. AsmWriteln(tai_symbol(hp).sym.name);
  951. end;
  952. if (target_info.system = system_powerpc64_linux) and
  953. (tai_symbol(hp).sym.typ = AT_FUNCTION) and (cs_profile in current_settings.moduleswitches) then
  954. begin
  955. AsmWriteLn('.globl _mcount');
  956. end;
  957. if tai_symbol(hp).is_global then
  958. begin
  959. AsmWrite('.globl'#9);
  960. AsmWriteLn(tai_symbol(hp).sym.name);
  961. end;
  962. if (target_info.system = system_powerpc64_linux) and
  963. (tai_symbol(hp).sym.typ = AT_FUNCTION) then
  964. begin
  965. AsmWriteLn('.section ".opd", "aw"');
  966. AsmWriteLn('.align 3');
  967. AsmWriteLn(tai_symbol(hp).sym.name + ':');
  968. AsmWriteLn('.quad .' + tai_symbol(hp).sym.name + ', .TOC.@tocbase, 0');
  969. AsmWriteLn('.previous');
  970. AsmWriteLn('.size ' + tai_symbol(hp).sym.name + ', 24');
  971. if (tai_symbol(hp).is_global) then
  972. AsmWriteLn('.globl .' + tai_symbol(hp).sym.name);
  973. AsmWriteLn('.type .' + tai_symbol(hp).sym.name + ', @function');
  974. { the dotted name is the name of the actual function entry }
  975. AsmWrite('.');
  976. end
  977. else
  978. begin
  979. if (target_info.system <> system_arm_linux) then
  980. sepChar := '@'
  981. else
  982. sepChar := '#';
  983. if (tf_needs_symbol_type in target_info.flags) then
  984. begin
  985. AsmWrite(#9'.type'#9 + tai_symbol(hp).sym.name);
  986. if (needsObject(tai_symbol(hp))) then
  987. AsmWriteLn(',' + sepChar + 'object')
  988. else
  989. AsmWriteLn(',' + sepChar + 'function');
  990. end;
  991. end;
  992. if not(tai_symbol(hp).has_value) then
  993. AsmWriteLn(tai_symbol(hp).sym.name + ':')
  994. else
  995. AsmWriteLn(tai_symbol(hp).sym.name + '=' + tostr(tai_symbol(hp).value));
  996. end;
  997. {$ifdef arm}
  998. ait_thumb_func:
  999. begin
  1000. AsmWriteLn(#9'.thumb_func');
  1001. end;
  1002. {$endif arm}
  1003. ait_symbol_end :
  1004. begin
  1005. if tf_needs_symbol_size in target_info.flags then
  1006. begin
  1007. s:=target_asm.labelprefix+'e'+tostr(symendcount);
  1008. inc(symendcount);
  1009. AsmWriteLn(s+':');
  1010. AsmWrite(#9'.size'#9);
  1011. if (target_info.system = system_powerpc64_linux) and (tai_symbol_end(hp).sym.typ = AT_FUNCTION) then
  1012. AsmWrite('.');
  1013. AsmWrite(tai_symbol_end(hp).sym.name);
  1014. AsmWrite(', '+s+' - ');
  1015. if (target_info.system = system_powerpc64_linux) and (tai_symbol_end(hp).sym.typ = AT_FUNCTION) then
  1016. AsmWrite('.');
  1017. AsmWriteLn(tai_symbol_end(hp).sym.name);
  1018. end;
  1019. end;
  1020. ait_instruction :
  1021. begin
  1022. WriteInstruction(hp);
  1023. end;
  1024. ait_stab :
  1025. begin
  1026. if assigned(tai_stab(hp).str) then
  1027. begin
  1028. AsmWrite(#9'.'+stabtypestr[tai_stab(hp).stabtype]+' ');
  1029. AsmWritePChar(tai_stab(hp).str);
  1030. AsmLn;
  1031. end;
  1032. end;
  1033. ait_force_line,
  1034. ait_function_name : ;
  1035. ait_cutobject :
  1036. begin
  1037. if SmartAsm then
  1038. begin
  1039. { only reset buffer if nothing has changed }
  1040. if AsmSize=AsmStartSize then
  1041. AsmClear
  1042. else
  1043. begin
  1044. AsmClose;
  1045. DoAssemble;
  1046. AsmCreate(tai_cutobject(hp).place);
  1047. end;
  1048. { avoid empty files }
  1049. while assigned(hp.next) and (tai(hp.next).typ in [ait_cutobject,ait_section,ait_comment]) do
  1050. begin
  1051. if tai(hp.next).typ=ait_section then
  1052. LastSecType:=tai_section(hp.next).sectype;
  1053. hp:=tai(hp.next);
  1054. end;
  1055. if LastSecType<>sec_none then
  1056. WriteSection(LastSecType,'',secorder_default);
  1057. AsmStartSize:=AsmSize;
  1058. end;
  1059. end;
  1060. ait_marker :
  1061. if tai_marker(hp).kind=mark_InlineStart then
  1062. inc(InlineLevel)
  1063. else if tai_marker(hp).kind=mark_InlineEnd then
  1064. dec(InlineLevel);
  1065. ait_directive :
  1066. begin
  1067. AsmWrite('.'+directivestr[tai_directive(hp).directive]+' ');
  1068. if assigned(tai_directive(hp).name) then
  1069. AsmWrite(tai_directive(hp).name^);
  1070. AsmLn;
  1071. end;
  1072. else
  1073. internalerror(2006012201);
  1074. end;
  1075. hp:=tai(hp.next);
  1076. end;
  1077. end;
  1078. procedure TGNUAssembler.WriteExtraHeader;
  1079. begin
  1080. end;
  1081. procedure TGNUAssembler.WriteInstruction(hp: tai);
  1082. begin
  1083. InstrWriter.WriteInstruction(hp);
  1084. end;
  1085. procedure TGNUAssembler.WriteWeakSymbolDef(s: tasmsymbol);
  1086. begin
  1087. AsmWriteLn(#9'.weak '+s.name);
  1088. end;
  1089. procedure TGNUAssembler.WriteAsmList;
  1090. var
  1091. n : string;
  1092. hal : tasmlisttype;
  1093. i: longint;
  1094. begin
  1095. {$ifdef EXTDEBUG}
  1096. if assigned(current_module.mainsource) then
  1097. Comment(V_Debug,'Start writing gas-styled assembler output for '+current_module.mainsource^);
  1098. {$endif}
  1099. if assigned(current_module.mainsource) then
  1100. n:=ExtractFileName(current_module.mainsource^)
  1101. else
  1102. n:=InputFileName;
  1103. { gcc does not add it either for Darwin (and AIX). Grep for
  1104. TARGET_ASM_FILE_START_FILE_DIRECTIVE in gcc/config/*.h
  1105. }
  1106. if not(target_info.system in systems_darwin) then
  1107. AsmWriteLn(#9'.file "'+FixFileName(n)+'"');
  1108. WriteExtraHeader;
  1109. AsmStartSize:=AsmSize;
  1110. symendcount:=0;
  1111. for hal:=low(TasmlistType) to high(TasmlistType) do
  1112. begin
  1113. AsmWriteLn(target_asm.comment+'Begin asmlist '+AsmlistTypeStr[hal]);
  1114. writetree(current_asmdata.asmlists[hal]);
  1115. AsmWriteLn(target_asm.comment+'End asmlist '+AsmlistTypeStr[hal]);
  1116. end;
  1117. { add weak symbol markers }
  1118. for i:=0 to current_asmdata.asmsymboldict.count-1 do
  1119. if (tasmsymbol(current_asmdata.asmsymboldict[i]).bind=AB_WEAK_EXTERNAL) then
  1120. writeweaksymboldef(tasmsymbol(current_asmdata.asmsymboldict[i]));
  1121. if create_smartlink_sections and
  1122. (target_info.system in systems_darwin) then
  1123. AsmWriteLn(#9'.subsections_via_symbols');
  1124. { "no executable stack" marker for Linux }
  1125. if (target_info.system in system_linux) and
  1126. not(cs_executable_stack in current_settings.moduleswitches) then
  1127. begin
  1128. AsmWriteLn('.section .note.GNU-stack,"",%progbits');
  1129. end;
  1130. AsmLn;
  1131. {$ifdef EXTDEBUG}
  1132. if assigned(current_module.mainsource) then
  1133. Comment(V_Debug,'Done writing gas-styled assembler output for '+current_module.mainsource^);
  1134. {$endif EXTDEBUG}
  1135. end;
  1136. {****************************************************************************}
  1137. { Apple/GNU Assembler writer }
  1138. {****************************************************************************}
  1139. function TAppleGNUAssembler.sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;
  1140. begin
  1141. if (target_info.system in systems_darwin) then
  1142. case atype of
  1143. sec_bss:
  1144. { all bss (lcomm) symbols are automatically put in the right }
  1145. { place by using the lcomm assembler directive }
  1146. atype := sec_none;
  1147. sec_debug_frame,
  1148. sec_eh_frame:
  1149. begin
  1150. result := '.section __DWARF,__debug_info,regular,debug';
  1151. exit;
  1152. end;
  1153. sec_debug_line:
  1154. begin
  1155. result := '.section __DWARF,__debug_line,regular,debug';
  1156. exit;
  1157. end;
  1158. sec_debug_info:
  1159. begin
  1160. result := '.section __DWARF,__debug_info,regular,debug';
  1161. exit;
  1162. end;
  1163. sec_debug_abbrev:
  1164. begin
  1165. result := '.section __DWARF,__debug_abbrev,regular,debug';
  1166. exit;
  1167. end;
  1168. sec_rodata:
  1169. begin
  1170. result := '.const_data';
  1171. exit;
  1172. end;
  1173. sec_rodata_norel:
  1174. begin
  1175. result := '.const';
  1176. exit;
  1177. end;
  1178. sec_fpc:
  1179. begin
  1180. result := '.section __TEXT, .fpc, regular, no_dead_strip';
  1181. exit;
  1182. end;
  1183. sec_code:
  1184. begin
  1185. if (aname='fpc_geteipasebx') or
  1186. (aname='fpc_geteipasecx') then
  1187. begin
  1188. result:='.section __TEXT,__textcoal_nt,coalesced,pure_instructions'#10'.weak_definition '+aname+
  1189. #10'.private_extern '+aname;
  1190. exit;
  1191. end;
  1192. end;
  1193. sec_objc_protocol_ext:
  1194. begin
  1195. result:='.section __OBJC, __protocol_ext, regular, no_dead_strip';
  1196. exit;
  1197. end;
  1198. sec_objc_class_ext:
  1199. begin
  1200. result:='.section __OBJC, __class_ext, regular, no_dead_strip';
  1201. exit;
  1202. end;
  1203. sec_objc_property:
  1204. begin
  1205. result:='.section __OBJC, __property, regular, no_dead_strip';
  1206. exit;
  1207. end;
  1208. sec_objc_image_info:
  1209. begin
  1210. result:='.section __OBJC, __image_info, regular, no_dead_strip';
  1211. exit;
  1212. end;
  1213. sec_objc_cstring_object:
  1214. begin
  1215. result:='.section __OBJC, __cstring_object, regular, no_dead_strip';
  1216. exit;
  1217. end;
  1218. sec_objc_sel_fixup:
  1219. begin
  1220. result:='.section __OBJC, __sel_fixup, regular, no_dead_strip';
  1221. exit;
  1222. end;
  1223. sec_objc_message_refs:
  1224. begin
  1225. if (target_info.system in system_objc_nfabi) then
  1226. begin
  1227. result:='.section __DATA, __objc_selrefs, literal_pointers, no_dead_strip';
  1228. exit;
  1229. end;
  1230. end;
  1231. sec_objc_cls_refs:
  1232. begin
  1233. if (target_info.system in system_objc_nfabi) then
  1234. begin
  1235. result:='.section __DATA, __objc_clsrefs, regular, no_dead_strip';
  1236. exit;
  1237. end;
  1238. end;
  1239. sec_objc_meth_var_names,
  1240. sec_objc_class_names:
  1241. begin
  1242. if (target_info.system in system_objc_nfabi) then
  1243. begin
  1244. result:='.cstring';
  1245. exit
  1246. end;
  1247. end;
  1248. sec_objc_inst_meth,
  1249. sec_objc_cls_meth,
  1250. sec_objc_cat_inst_meth,
  1251. sec_objc_cat_cls_meth:
  1252. begin
  1253. if (target_info.system in system_objc_nfabi) then
  1254. begin
  1255. result:='.section __DATA, __objc_const';
  1256. exit;
  1257. end;
  1258. end;
  1259. sec_objc_meta_class,
  1260. sec_objc_class:
  1261. begin
  1262. if (target_info.system in system_objc_nfabi) then
  1263. begin
  1264. result:='.section __DATA, __objc_data';
  1265. exit;
  1266. end;
  1267. end;
  1268. sec_objc_sup_refs:
  1269. begin
  1270. result:='.section __DATA, __objc_superrefs, regular, no_dead_strip';
  1271. exit
  1272. end;
  1273. sec_objc_classlist:
  1274. begin
  1275. result:='.section __DATA, __objc_classlist, regular, no_dead_strip';
  1276. exit
  1277. end;
  1278. sec_objc_nlclasslist:
  1279. begin
  1280. result:='.section __DATA, __objc_nlclasslist, regular, no_dead_strip';
  1281. exit
  1282. end;
  1283. sec_objc_catlist:
  1284. begin
  1285. result:='.section __DATA, __objc_catlist, regular, no_dead_strip';
  1286. exit
  1287. end;
  1288. sec_objc_nlcatlist:
  1289. begin
  1290. result:='.section __DATA, __objc_nlcatlist, regular, no_dead_strip';
  1291. exit
  1292. end;
  1293. sec_objc_protolist:
  1294. begin
  1295. result:='.section __DATA, __objc_protolist, coalesced, no_dead_strip';
  1296. exit;
  1297. end;
  1298. end;
  1299. result := inherited sectionname(atype,aname,aorder);
  1300. end;
  1301. procedure TAppleGNUAssembler.WriteWeakSymbolDef(s: tasmsymbol);
  1302. begin
  1303. AsmWriteLn(#9'.weak_reference '+s.name);
  1304. end;
  1305. {****************************************************************************}
  1306. { a.out/GNU Assembler writer }
  1307. {****************************************************************************}
  1308. function TAoutGNUAssembler.sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;
  1309. const
  1310. (* Translation table - replace unsupported section types with basic ones. *)
  1311. SecXTable: array[TAsmSectionType] of TAsmSectionType = (
  1312. sec_none,
  1313. sec_code,
  1314. sec_data,
  1315. sec_data (* sec_rodata *),
  1316. sec_data (* sec_rodata_norel *),
  1317. sec_bss,
  1318. sec_data (* sec_threadvar *),
  1319. { used for wince exception handling }
  1320. sec_code (* sec_pdata *),
  1321. { used for darwin import stubs }
  1322. sec_code (* sec_stub *),
  1323. { stabs }
  1324. sec_stab,sec_stabstr,
  1325. { win32 }
  1326. sec_data (* sec_idata2 *),
  1327. sec_data (* sec_idata4 *),
  1328. sec_data (* sec_idata5 *),
  1329. sec_data (* sec_idata6 *),
  1330. sec_data (* sec_idata7 *),
  1331. sec_data (* sec_edata *),
  1332. { C++ exception handling unwinding (uses dwarf) }
  1333. sec_eh_frame,
  1334. { dwarf }
  1335. sec_debug_frame,
  1336. sec_debug_info,
  1337. sec_debug_line,
  1338. sec_debug_abbrev,
  1339. { ELF resources (+ references to stabs debug information sections) }
  1340. sec_code (* sec_fpc *),
  1341. { Table of contents section }
  1342. sec_code (* sec_toc *),
  1343. sec_code (* sec_init *),
  1344. sec_code (* sec_fini *),
  1345. sec_none (* sec_objc_class *),
  1346. sec_none (* sec_objc_meta_class *),
  1347. sec_none (* sec_objc_cat_cls_meth *),
  1348. sec_none (* sec_objc_cat_inst_meth *),
  1349. sec_none (* sec_objc_protocol *),
  1350. sec_none (* sec_objc_string_object *),
  1351. sec_none (* sec_objc_cls_meth *),
  1352. sec_none (* sec_objc_inst_meth *),
  1353. sec_none (* sec_objc_cls_refs *),
  1354. sec_none (* sec_objc_message_refs *),
  1355. sec_none (* sec_objc_symbols *),
  1356. sec_none (* sec_objc_category *),
  1357. sec_none (* sec_objc_class_vars *),
  1358. sec_none (* sec_objc_instance_vars *),
  1359. sec_none (* sec_objc_module_info *),
  1360. sec_none (* sec_objc_class_names *),
  1361. sec_none (* sec_objc_meth_var_types *),
  1362. sec_none (* sec_objc_meth_var_names *),
  1363. sec_none (* sec_objc_selector_strs *),
  1364. sec_none (* sec_objc_protocol_ext *),
  1365. sec_none (* sec_objc_class_ext *),
  1366. sec_none (* sec_objc_property *),
  1367. sec_none (* sec_objc_image_info *),
  1368. sec_none (* sec_objc_cstring_object *),
  1369. sec_none (* sec_objc_sel_fixup *),
  1370. sec_none (* sec_objc_data *),
  1371. sec_none (* sec_objc_const *),
  1372. sec_none (* sec_objc_sup_refs *),
  1373. sec_none (* sec_data_coalesced *),
  1374. sec_none (* sec_objc_classlist *),
  1375. sec_none (* sec_objc_nlclasslist *),
  1376. sec_none (* sec_objc_catlist *),
  1377. sec_none (* sec_objc_nlcatlist *),
  1378. sec_none (* sec_objc_protlist *)
  1379. );
  1380. begin
  1381. Result := inherited SectionName (SecXTable [AType], AName, AOrder);
  1382. end;
  1383. {****************************************************************************}
  1384. { Abstract Instruction Writer }
  1385. {****************************************************************************}
  1386. constructor TCPUInstrWriter.create(_owner: TGNUAssembler);
  1387. begin
  1388. inherited create;
  1389. owner := _owner;
  1390. end;
  1391. end.