aggas.pas 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824
  1. {
  2. Copyright (c) 1998-2004 by the Free Pascal team
  3. This unit implements generic GNU assembler (v2.8 or later)
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. { Base unit for writing GNU assembler output.
  18. }
  19. unit aggas;
  20. {$i fpcdefs.inc}
  21. interface
  22. uses
  23. {$IFDEF USE_SYSUTILS}
  24. SysUtils,
  25. {$ELSE USE_SYSUTILS}
  26. dos,
  27. {$ENDIF USE_SYSUTILS}
  28. cclasses,
  29. globals,
  30. aasmbase,aasmtai,aasmcpu,
  31. assemble;
  32. type
  33. {# This is a derived class which is used to write
  34. GAS styled assembler.
  35. The WriteInstruction() method must be overriden
  36. to write a single instruction to the assembler
  37. file.
  38. }
  39. TGNUAssembler=class(texternalassembler)
  40. protected
  41. function sectionname(atype:tasmsectiontype;const aname:string):string;virtual;
  42. procedure WriteSection(atype:tasmsectiontype;const aname:string);
  43. procedure WriteExtraHeader;virtual;
  44. procedure WriteInstruction(hp: tai); virtual; abstract;
  45. public
  46. procedure WriteTree(p:TAAsmoutput);override;
  47. procedure WriteAsmList;override;
  48. end;
  49. implementation
  50. uses
  51. cutils,globtype,systems,
  52. fmodule,finput,verbose,
  53. itcpugas
  54. ;
  55. const
  56. line_length = 70;
  57. var
  58. CurrSecType : TAsmSectionType; { last section type written }
  59. lastfileinfo : tfileposinfo;
  60. infile,
  61. lastinfile : tinputfile;
  62. symendcount : longint;
  63. type
  64. {$ifdef cpuextended}
  65. t80bitarray = array[0..9] of byte;
  66. {$endif cpuextended}
  67. t64bitarray = array[0..7] of byte;
  68. t32bitarray = array[0..3] of byte;
  69. {****************************************************************************}
  70. { Support routines }
  71. {****************************************************************************}
  72. function fixline(s:string):string;
  73. {
  74. return s with all leading and ending spaces and tabs removed
  75. }
  76. var
  77. i,j,k : integer;
  78. begin
  79. i:=length(s);
  80. while (i>0) and (s[i] in [#9,' ']) do
  81. dec(i);
  82. j:=1;
  83. while (j<i) and (s[j] in [#9,' ']) do
  84. inc(j);
  85. for k:=j to i do
  86. if s[k] in [#0..#31,#127..#255] then
  87. s[k]:='.';
  88. fixline:=Copy(s,j,i-j+1);
  89. end;
  90. function single2str(d : single) : string;
  91. var
  92. hs : string;
  93. begin
  94. str(d,hs);
  95. { replace space with + }
  96. if hs[1]=' ' then
  97. hs[1]:='+';
  98. single2str:='0d'+hs
  99. end;
  100. function double2str(d : double) : string;
  101. var
  102. hs : string;
  103. begin
  104. str(d,hs);
  105. { replace space with + }
  106. if hs[1]=' ' then
  107. hs[1]:='+';
  108. double2str:='0d'+hs
  109. end;
  110. function extended2str(e : extended) : string;
  111. var
  112. hs : string;
  113. begin
  114. str(e,hs);
  115. { replace space with + }
  116. if hs[1]=' ' then
  117. hs[1]:='+';
  118. extended2str:='0d'+hs
  119. end;
  120. { convert floating point values }
  121. { to correct endian }
  122. procedure swap64bitarray(var t: t64bitarray);
  123. var
  124. b: byte;
  125. begin
  126. b:= t[7];
  127. t[7] := t[0];
  128. t[0] := b;
  129. b := t[6];
  130. t[6] := t[1];
  131. t[1] := b;
  132. b:= t[5];
  133. t[5] := t[2];
  134. t[2] := b;
  135. b:= t[4];
  136. t[4] := t[3];
  137. t[3] := b;
  138. end;
  139. procedure swap32bitarray(var t: t32bitarray);
  140. var
  141. b: byte;
  142. begin
  143. b:= t[1];
  144. t[1]:= t[2];
  145. t[2]:= b;
  146. b:= t[0];
  147. t[0]:= t[3];
  148. t[3]:= b;
  149. end;
  150. const
  151. ait_const2str : array[ait_const_128bit..ait_const_indirect_symbol] of string[20]=(
  152. #9'.fixme128'#9,#9'.quad'#9,#9'.long'#9,#9'.short'#9,#9'.byte'#9,
  153. #9'.sleb128'#9,#9'.uleb128'#9,
  154. #9'.rva'#9,#9'.indirect_symbol'#9
  155. );
  156. {****************************************************************************}
  157. { GNU Assembler writer }
  158. {****************************************************************************}
  159. function TGNUAssembler.sectionname(atype:tasmsectiontype;const aname:string):string;
  160. const
  161. secnames : array[tasmsectiontype] of string[12] = ('',
  162. {$warning TODO .rodata not yet working}
  163. '.text','.data','.data','.bss','.threadvar',
  164. 'common',
  165. '.note',
  166. '.stab','.stabstr',
  167. '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
  168. '.eh_frame',
  169. '.debug_frame',
  170. 'fpc.resptrs'
  171. );
  172. begin
  173. if use_smartlink_section and
  174. (aname<>'') then
  175. result:=secnames[atype]+'.'+aname
  176. else
  177. result:=secnames[atype];
  178. end;
  179. procedure TGNUAssembler.WriteSection(atype:tasmsectiontype;const aname:string);
  180. var
  181. s : string;
  182. begin
  183. AsmLn;
  184. case target_info.system of
  185. system_powerpc_darwin, system_i386_OS2, system_i386_EMX: ;
  186. else
  187. AsmWrite('.section ');
  188. end;
  189. s:=sectionname(atype,aname);
  190. AsmWrite(s);
  191. if atype=sec_fpc then
  192. AsmWrite(', "a", @progbits');
  193. AsmLn;
  194. CurrSecType:=atype;
  195. end;
  196. procedure TGNUAssembler.WriteTree(p:TAAsmoutput);
  197. var
  198. ch : char;
  199. hp : tai;
  200. hp1 : tailineinfo;
  201. consttyp : taitype;
  202. s : string;
  203. i,pos,l : longint;
  204. InlineLevel : longint;
  205. last_align : longint;
  206. co : comp;
  207. sin : single;
  208. d : double;
  209. {$ifdef cpuextended}
  210. e : extended;
  211. {$endif cpuextended}
  212. do_line : boolean;
  213. begin
  214. if not assigned(p) then
  215. exit;
  216. last_align := 2;
  217. InlineLevel:=0;
  218. { lineinfo is only needed for al_procedures (PFV) }
  219. do_line:=(cs_asm_source in aktglobalswitches) or
  220. ((cs_lineinfo in aktmoduleswitches)
  221. and (p=asmlist[al_procedures]));
  222. hp:=tai(p.first);
  223. while assigned(hp) do
  224. begin
  225. if not(hp.typ in SkipLineInfo) then
  226. begin
  227. hp1 := hp as tailineinfo;
  228. aktfilepos:=hp1.fileinfo;
  229. { no line info for inlined code }
  230. if do_line and (inlinelevel=0) then
  231. begin
  232. { load infile }
  233. if lastfileinfo.fileindex<>hp1.fileinfo.fileindex then
  234. begin
  235. infile:=current_module.sourcefiles.get_file(hp1.fileinfo.fileindex);
  236. if assigned(infile) then
  237. begin
  238. { open only if needed !! }
  239. if (cs_asm_source in aktglobalswitches) then
  240. infile.open;
  241. end;
  242. { avoid unnecessary reopens of the same file !! }
  243. lastfileinfo.fileindex:=hp1.fileinfo.fileindex;
  244. { be sure to change line !! }
  245. lastfileinfo.line:=-1;
  246. end;
  247. { write source }
  248. if (cs_asm_source in aktglobalswitches) and
  249. assigned(infile) then
  250. begin
  251. if (infile<>lastinfile) then
  252. begin
  253. AsmWriteLn(target_asm.comment+'['+infile.name^+']');
  254. if assigned(lastinfile) then
  255. lastinfile.close;
  256. end;
  257. if (hp1.fileinfo.line<>lastfileinfo.line) and
  258. ((hp1.fileinfo.line<infile.maxlinebuf) or (InlineLevel>0)) then
  259. begin
  260. if (hp1.fileinfo.line<>0) and
  261. ((infile.linebuf^[hp1.fileinfo.line]>=0) or (InlineLevel>0)) then
  262. AsmWriteLn(target_asm.comment+'['+tostr(hp1.fileinfo.line)+'] '+
  263. fixline(infile.GetLineStr(hp1.fileinfo.line)));
  264. { set it to a negative value !
  265. to make that is has been read already !! PM }
  266. if (infile.linebuf^[hp1.fileinfo.line]>=0) then
  267. infile.linebuf^[hp1.fileinfo.line]:=-infile.linebuf^[hp1.fileinfo.line]-1;
  268. end;
  269. end;
  270. lastfileinfo:=hp1.fileinfo;
  271. lastinfile:=infile;
  272. end;
  273. end;
  274. case hp.typ of
  275. ait_comment :
  276. Begin
  277. AsmWrite(target_asm.comment);
  278. AsmWritePChar(tai_comment(hp).str);
  279. AsmLn;
  280. End;
  281. ait_regalloc :
  282. begin
  283. if (cs_asm_regalloc in aktglobalswitches) then
  284. begin
  285. AsmWrite(#9+target_asm.comment+'Register ');
  286. repeat
  287. AsmWrite(gas_regname(Tai_regalloc(hp).reg));
  288. if (hp.next=nil) or
  289. (tai(hp.next).typ<>ait_regalloc) or
  290. (tai_regalloc(hp.next).ratype<>tai_regalloc(hp).ratype) then
  291. break;
  292. hp:=tai(hp.next);
  293. AsmWrite(',');
  294. until false;
  295. AsmWrite(' ');
  296. AsmWriteLn(regallocstr[tai_regalloc(hp).ratype]);
  297. end;
  298. end;
  299. ait_tempalloc :
  300. begin
  301. if (cs_asm_tempalloc in aktglobalswitches) then
  302. begin
  303. {$ifdef EXTDEBUG}
  304. if assigned(tai_tempalloc(hp).problem) then
  305. AsmWriteLn(target_asm.comment+'Temp '+tostr(tai_tempalloc(hp).temppos)+','+
  306. tostr(tai_tempalloc(hp).tempsize)+' '+tai_tempalloc(hp).problem^)
  307. else
  308. {$endif EXTDEBUG}
  309. AsmWriteLn(target_asm.comment+'Temp '+tostr(tai_tempalloc(hp).temppos)+','+
  310. tostr(tai_tempalloc(hp).tempsize)+' '+tempallocstr[tai_tempalloc(hp).allocation]);
  311. end;
  312. end;
  313. ait_align :
  314. begin
  315. if tai_align(hp).aligntype>1 then
  316. begin
  317. if target_info.system <> system_powerpc_darwin then
  318. begin
  319. AsmWrite(#9'.balign '+tostr(tai_align(hp).aligntype));
  320. if tai_align(hp).use_op then
  321. AsmWrite(','+tostr(tai_align(hp).fillop))
  322. end
  323. else
  324. begin
  325. { darwin as only supports .align }
  326. if not ispowerof2(tai_align(hp).aligntype,i) then
  327. internalerror(2003010305);
  328. AsmWrite(#9'.align '+tostr(i));
  329. last_align := i;
  330. end;
  331. AsmLn;
  332. end;
  333. end;
  334. ait_section :
  335. begin
  336. if tai_section(hp).sectype<>sec_none then
  337. WriteSection(tai_section(hp).sectype,tai_section(hp).name^)
  338. else
  339. begin
  340. {$ifdef EXTDEBUG}
  341. AsmWrite(target_asm.comment);
  342. AsmWriteln(' sec_none');
  343. {$endif EXTDEBUG}
  344. end;
  345. end;
  346. ait_datablock :
  347. begin
  348. if target_info.system=system_powerpc_darwin then
  349. begin
  350. {On Mac OS X you can't have common symbols in a shared
  351. library, since those are in the TEXT section and the text section is
  352. read-only in shared libraries (so it can be shared among different
  353. processes). The alternate code creates some kind of common symbols in
  354. the data segment. The generic code no longer uses common symbols, but
  355. this doesn't work on Mac OS X as well.}
  356. if tai_datablock(hp).is_global then
  357. begin
  358. asmwrite('.globl ');
  359. asmwriteln(tai_datablock(hp).sym.name);
  360. asmwriteln('.data');
  361. asmwrite('.zerofill __DATA, __common, ');
  362. asmwrite(tai_datablock(hp).sym.name);
  363. asmwriteln(', '+tostr(tai_datablock(hp).size)+','+tostr(last_align));
  364. if not(CurrSecType in [sec_data,sec_none]) then
  365. writesection(CurrSecType,'');
  366. end
  367. else
  368. begin
  369. asmwrite(#9'.lcomm'#9);
  370. asmwrite(tai_datablock(hp).sym.name);
  371. asmwrite(','+tostr(tai_datablock(hp).size));
  372. asmwrite(','+tostr(last_align));
  373. asmwriteln('');
  374. end
  375. end
  376. else
  377. begin
  378. if Tai_datablock(hp).is_global then
  379. begin
  380. asmwrite(#9'.globl ');
  381. asmwriteln(Tai_datablock(hp).sym.name);
  382. end;
  383. asmwrite(Tai_datablock(hp).sym.name);
  384. asmwriteln(':');
  385. asmwriteln(#9'.space '+tostr(Tai_datablock(hp).size));
  386. end;
  387. end;
  388. {$ifndef cpu64bit}
  389. ait_const_128bit :
  390. begin
  391. internalerror(200404291);
  392. end;
  393. ait_const_64bit :
  394. begin
  395. if assigned(tai_const(hp).sym) then
  396. internalerror(200404292);
  397. AsmWrite(ait_const2str[ait_const_32bit]);
  398. if target_info.endian = endian_little then
  399. begin
  400. AsmWrite(tostr(longint(lo(tai_const(hp).value))));
  401. AsmWrite(',');
  402. AsmWrite(tostr(longint(hi(tai_const(hp).value))));
  403. end
  404. else
  405. begin
  406. AsmWrite(tostr(longint(hi(tai_const(hp).value))));
  407. AsmWrite(',');
  408. AsmWrite(tostr(longint(lo(tai_const(hp).value))));
  409. end;
  410. AsmLn;
  411. end;
  412. {$endif cpu64bit}
  413. ait_const_uleb128bit,
  414. ait_const_sleb128bit,
  415. {$ifdef cpu64bit}
  416. ait_const_128bit,
  417. ait_const_64bit,
  418. {$endif cpu64bit}
  419. ait_const_32bit,
  420. ait_const_16bit,
  421. ait_const_8bit,
  422. ait_const_rva_symbol,
  423. ait_const_indirect_symbol :
  424. begin
  425. AsmWrite(ait_const2str[hp.typ]);
  426. consttyp:=hp.typ;
  427. l:=0;
  428. repeat
  429. if assigned(tai_const(hp).sym) then
  430. begin
  431. if assigned(tai_const(hp).endsym) then
  432. s:=tai_const(hp).endsym.name+'-'+tai_const(hp).sym.name
  433. else
  434. s:=tai_const(hp).sym.name;
  435. if tai_const(hp).value<>0 then
  436. s:=s+tostr_with_plus(tai_const(hp).value);
  437. end
  438. else
  439. s:=tostr(tai_const(hp).value);
  440. AsmWrite(s);
  441. inc(l,length(s));
  442. { Values with symbols are written on a single line to improve
  443. reading of the .s file (PFV) }
  444. if assigned(tai_const(hp).sym) or
  445. not(CurrSecType in [sec_data,sec_rodata]) or
  446. (l>line_length) or
  447. (hp.next=nil) or
  448. (tai(hp.next).typ<>consttyp) or
  449. assigned(tai_const(hp.next).sym) then
  450. break;
  451. hp:=tai(hp.next);
  452. AsmWrite(',');
  453. until false;
  454. AsmLn;
  455. end;
  456. {$ifdef cpuextended}
  457. ait_real_80bit :
  458. begin
  459. if do_line then
  460. AsmWriteLn(target_asm.comment+'value: '+extended2str(tai_real_80bit(hp).value));
  461. { Make sure e is a extended type, bestreal could be
  462. a different type (bestreal) !! (PFV) }
  463. e:=tai_real_80bit(hp).value;
  464. AsmWrite(#9'.byte'#9);
  465. for i:=0 to 9 do
  466. begin
  467. if i<>0 then
  468. AsmWrite(',');
  469. AsmWrite(tostr(t80bitarray(e)[i]));
  470. end;
  471. AsmLn;
  472. end;
  473. {$endif cpuextended}
  474. ait_real_64bit :
  475. begin
  476. if do_line then
  477. AsmWriteLn(target_asm.comment+'value: '+double2str(tai_real_64bit(hp).value));
  478. d:=tai_real_64bit(hp).value;
  479. { swap the values to correct endian if required }
  480. if source_info.endian <> target_info.endian then
  481. swap64bitarray(t64bitarray(d));
  482. AsmWrite(#9'.byte'#9);
  483. {$ifdef arm}
  484. { on a real arm cpu, it's already hi/lo swapped }
  485. {$ifndef cpuarm}
  486. if tai_real_64bit(hp).formatoptions=fo_hiloswapped then
  487. begin
  488. for i:=4 to 7 do
  489. begin
  490. if i<>4 then
  491. AsmWrite(',');
  492. AsmWrite(tostr(t64bitarray(d)[i]));
  493. end;
  494. for i:=0 to 3 do
  495. begin
  496. AsmWrite(',');
  497. AsmWrite(tostr(t64bitarray(d)[i]));
  498. end;
  499. end
  500. else
  501. {$endif cpuarm}
  502. {$endif arm}
  503. begin
  504. for i:=0 to 7 do
  505. begin
  506. if i<>0 then
  507. AsmWrite(',');
  508. AsmWrite(tostr(t64bitarray(d)[i]));
  509. end;
  510. end;
  511. AsmLn;
  512. end;
  513. ait_real_32bit :
  514. begin
  515. if do_line then
  516. AsmWriteLn(target_asm.comment+'value: '+single2str(tai_real_32bit(hp).value));
  517. sin:=tai_real_32bit(hp).value;
  518. { swap the values to correct endian if required }
  519. if source_info.endian <> target_info.endian then
  520. swap32bitarray(t32bitarray(sin));
  521. AsmWrite(#9'.byte'#9);
  522. for i:=0 to 3 do
  523. begin
  524. if i<>0 then
  525. AsmWrite(',');
  526. AsmWrite(tostr(t32bitarray(sin)[i]));
  527. end;
  528. AsmLn;
  529. end;
  530. ait_comp_64bit :
  531. begin
  532. if do_line then
  533. AsmWriteLn(target_asm.comment+'value: '+extended2str(tai_comp_64bit(hp).value));
  534. AsmWrite(#9'.byte'#9);
  535. {$ifdef FPC}
  536. co:=comp(tai_comp_64bit(hp).value);
  537. {$else}
  538. co:=tai_comp_64bit(hp).value;
  539. {$endif}
  540. { swap the values to correct endian if required }
  541. if source_info.endian <> target_info.endian then
  542. swap64bitarray(t64bitarray(co));
  543. for i:=0 to 7 do
  544. begin
  545. if i<>0 then
  546. AsmWrite(',');
  547. AsmWrite(tostr(t64bitarray(co)[i]));
  548. end;
  549. AsmLn;
  550. end;
  551. ait_string :
  552. begin
  553. pos:=0;
  554. for i:=1 to tai_string(hp).len do
  555. begin
  556. if pos=0 then
  557. begin
  558. AsmWrite(#9'.ascii'#9'"');
  559. pos:=20;
  560. end;
  561. ch:=tai_string(hp).str[i-1];
  562. case ch of
  563. #0, {This can't be done by range, because a bug in FPC}
  564. #1..#31,
  565. #128..#255 : s:='\'+tostr(ord(ch) shr 6)+tostr((ord(ch) and 63) shr 3)+tostr(ord(ch) and 7);
  566. '"' : s:='\"';
  567. '\' : s:='\\';
  568. else
  569. s:=ch;
  570. end;
  571. AsmWrite(s);
  572. inc(pos,length(s));
  573. if (pos>line_length) or (i=tai_string(hp).len) then
  574. begin
  575. AsmWriteLn('"');
  576. pos:=0;
  577. end;
  578. end;
  579. end;
  580. ait_label :
  581. begin
  582. if (tai_label(hp).l.is_used) then
  583. begin
  584. if tai_label(hp).l.defbind=AB_GLOBAL then
  585. begin
  586. AsmWrite('.globl'#9);
  587. AsmWriteLn(tai_label(hp).l.name);
  588. end;
  589. AsmWrite(tai_label(hp).l.name);
  590. AsmWriteLn(':');
  591. end;
  592. end;
  593. ait_symbol :
  594. begin
  595. if tai_symbol(hp).is_global then
  596. begin
  597. AsmWrite('.globl'#9);
  598. AsmWriteLn(tai_symbol(hp).sym.name);
  599. end;
  600. if target_info.system in [system_i386_linux,system_i386_beos,
  601. system_powerpc_linux,system_m68k_linux,
  602. system_sparc_linux,system_alpha_linux,
  603. system_x86_64_linux,system_arm_linux] then
  604. begin
  605. AsmWrite(#9'.type'#9);
  606. AsmWrite(tai_symbol(hp).sym.name);
  607. if assigned(tai(hp.next)) and
  608. (tai(hp.next).typ in [ait_const_rva_symbol,
  609. ait_const_32bit,ait_const_16bit,ait_const_8bit,ait_datablock,
  610. ait_real_32bit,ait_real_64bit,ait_real_80bit,ait_comp_64bit]) then
  611. begin
  612. if target_info.system = system_arm_linux then
  613. AsmWriteLn(',#object')
  614. else
  615. AsmWriteLn(',@object')
  616. end
  617. else
  618. begin
  619. if target_info.system = system_arm_linux then
  620. AsmWriteLn(',#function')
  621. else
  622. AsmWriteLn(',@function');
  623. end;
  624. if tai_symbol(hp).sym.size>0 then
  625. begin
  626. AsmWrite(#9'.size'#9);
  627. AsmWrite(tai_symbol(hp).sym.name);
  628. AsmWrite(', ');
  629. AsmWriteLn(tostr(tai_symbol(hp).sym.size));
  630. end;
  631. end;
  632. AsmWrite(tai_symbol(hp).sym.name);
  633. AsmWriteLn(':');
  634. end;
  635. ait_symbol_end :
  636. begin
  637. if tf_needs_symbol_size in target_info.flags then
  638. begin
  639. s:=target_asm.labelprefix+'e'+tostr(symendcount);
  640. inc(symendcount);
  641. AsmWriteLn(s+':');
  642. AsmWrite(#9'.size'#9);
  643. AsmWrite(tai_symbol_end(hp).sym.name);
  644. AsmWrite(', '+s+' - ');
  645. AsmWriteLn(tai_symbol_end(hp).sym.name);
  646. end;
  647. end;
  648. ait_instruction :
  649. begin
  650. WriteInstruction(hp);
  651. end;
  652. ait_stab :
  653. begin
  654. if assigned(tai_stab(hp).str) then
  655. begin
  656. AsmWrite(#9'.'+stabtypestr[tai_stab(hp).stabtype]+' ');
  657. AsmWritePChar(tai_stab(hp).str);
  658. AsmLn;
  659. end;
  660. end;
  661. ait_force_line,
  662. ait_function_name : ;
  663. ait_cutobject :
  664. begin
  665. if SmartAsm then
  666. begin
  667. { only reset buffer if nothing has changed }
  668. if AsmSize=AsmStartSize then
  669. AsmClear
  670. else
  671. begin
  672. AsmClose;
  673. DoAssemble;
  674. AsmCreate(tai_cutobject(hp).place);
  675. end;
  676. { avoid empty files }
  677. while assigned(hp.next) and (tai(hp.next).typ in [ait_cutobject,ait_section,ait_comment]) do
  678. begin
  679. if tai(hp.next).typ=ait_section then
  680. CurrSecType:=tai_section(hp.next).sectype;
  681. hp:=tai(hp.next);
  682. end;
  683. if CurrSecType<>sec_none then
  684. WriteSection(CurrSecType,'');
  685. AsmStartSize:=AsmSize;
  686. end;
  687. end;
  688. ait_marker :
  689. if tai_marker(hp).kind=InlineStart then
  690. inc(InlineLevel)
  691. else if tai_marker(hp).kind=InlineEnd then
  692. dec(InlineLevel);
  693. ait_non_lazy_symbol_pointer:
  694. AsmWriteLn('.non_lazy_symbol_pointer');
  695. else
  696. internalerror(10000);
  697. end;
  698. hp:=tai(hp.next);
  699. end;
  700. end;
  701. procedure TGNUAssembler.WriteExtraHeader;
  702. begin
  703. end;
  704. procedure TGNUAssembler.WriteAsmList;
  705. var
  706. p:dirstr;
  707. n:namestr;
  708. e:extstr;
  709. hal : tasmlist;
  710. begin
  711. {$ifdef EXTDEBUG}
  712. if assigned(current_module.mainsource) then
  713. Comment(V_Debug,'Start writing gas-styled assembler output for '+current_module.mainsource^);
  714. {$endif}
  715. CurrSecType:=sec_none;
  716. FillChar(lastfileinfo,sizeof(lastfileinfo),0);
  717. LastInfile:=nil;
  718. if assigned(current_module.mainsource) then
  719. {$IFDEF USE_SYSUTILS}
  720. begin
  721. p := SplitPath(current_module.mainsource^);
  722. n := SplitName(current_module.mainsource^);
  723. e := SplitExtension(current_module.mainsource^);
  724. end
  725. {$ELSE USE_SYSUTILS}
  726. fsplit(current_module.mainsource^,p,n,e)
  727. {$ENDIF USE_SYSUTILS}
  728. else
  729. begin
  730. p:=inputdir;
  731. n:=inputfile;
  732. e:=inputextension;
  733. end;
  734. { to get symify to work }
  735. AsmWriteLn(#9'.file "'+FixFileName(n+e)+'"');
  736. WriteExtraHeader;
  737. AsmStartSize:=AsmSize;
  738. symendcount:=0;
  739. for hal:=low(Tasmlist) to high(Tasmlist) do
  740. begin
  741. AsmWriteLn(target_asm.comment+'Begin asmlist '+TasmlistStr[hal]);
  742. writetree(asmlist[hal]);
  743. AsmWriteLn(target_asm.comment+'End asmlist '+TasmlistStr[hal]);
  744. end;
  745. AsmLn;
  746. {$ifdef EXTDEBUG}
  747. if assigned(current_module.mainsource) then
  748. Comment(V_Debug,'Done writing gas-styled assembler output for '+current_module.mainsource^);
  749. {$endif EXTDEBUG}
  750. end;
  751. end.