aggas.pas 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843
  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. '__TEXT', { stubs }
  167. '.stab','.stabstr',
  168. '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
  169. '.eh_frame',
  170. '.debug_frame',
  171. 'fpc'
  172. );
  173. begin
  174. if (use_smartlink_section and
  175. (aname<>'')) or (atype=sec_fpc) then
  176. result:=secnames[atype]+'.'+aname
  177. else
  178. result:=secnames[atype];
  179. end;
  180. procedure TGNUAssembler.WriteSection(atype:tasmsectiontype;const aname:string);
  181. var
  182. s : string;
  183. begin
  184. AsmLn;
  185. case target_info.system of
  186. system_i386_OS2,
  187. system_i386_EMX : ;
  188. system_powerpc_darwin :
  189. begin
  190. if atype=sec_stub then
  191. AsmWrite('.section ');
  192. end;
  193. else
  194. AsmWrite('.section ');
  195. end;
  196. s:=sectionname(atype,aname);
  197. AsmWrite(s);
  198. case atype of
  199. sec_fpc :
  200. AsmWrite(', "a", @progbits');
  201. sec_stub :
  202. begin
  203. if target_info.system=system_powerpc_darwin then
  204. AsmWrite(',__symbol_stub1,symbol_stubs,pure_instructions,16');
  205. end;
  206. end;
  207. AsmLn;
  208. CurrSecType:=atype;
  209. end;
  210. procedure TGNUAssembler.WriteTree(p:TAAsmoutput);
  211. var
  212. ch : char;
  213. hp : tai;
  214. hp1 : tailineinfo;
  215. consttyp : taitype;
  216. s : string;
  217. i,pos,l : longint;
  218. InlineLevel : longint;
  219. last_align : longint;
  220. co : comp;
  221. sin : single;
  222. d : double;
  223. {$ifdef cpuextended}
  224. e : extended;
  225. {$endif cpuextended}
  226. do_line : boolean;
  227. begin
  228. if not assigned(p) then
  229. exit;
  230. last_align := 2;
  231. InlineLevel:=0;
  232. { lineinfo is only needed for al_procedures (PFV) }
  233. do_line:=(cs_asm_source in aktglobalswitches) or
  234. ((cs_lineinfo in aktmoduleswitches)
  235. and (p=asmlist[al_procedures]));
  236. hp:=tai(p.first);
  237. while assigned(hp) do
  238. begin
  239. if not(hp.typ in SkipLineInfo) then
  240. begin
  241. hp1 := hp as tailineinfo;
  242. aktfilepos:=hp1.fileinfo;
  243. { no line info for inlined code }
  244. if do_line and (inlinelevel=0) then
  245. begin
  246. { load infile }
  247. if lastfileinfo.fileindex<>hp1.fileinfo.fileindex then
  248. begin
  249. infile:=current_module.sourcefiles.get_file(hp1.fileinfo.fileindex);
  250. if assigned(infile) then
  251. begin
  252. { open only if needed !! }
  253. if (cs_asm_source in aktglobalswitches) then
  254. infile.open;
  255. end;
  256. { avoid unnecessary reopens of the same file !! }
  257. lastfileinfo.fileindex:=hp1.fileinfo.fileindex;
  258. { be sure to change line !! }
  259. lastfileinfo.line:=-1;
  260. end;
  261. { write source }
  262. if (cs_asm_source in aktglobalswitches) and
  263. assigned(infile) then
  264. begin
  265. if (infile<>lastinfile) then
  266. begin
  267. AsmWriteLn(target_asm.comment+'['+infile.name^+']');
  268. if assigned(lastinfile) then
  269. lastinfile.close;
  270. end;
  271. if (hp1.fileinfo.line<>lastfileinfo.line) and
  272. ((hp1.fileinfo.line<infile.maxlinebuf) or (InlineLevel>0)) then
  273. begin
  274. if (hp1.fileinfo.line<>0) and
  275. ((infile.linebuf^[hp1.fileinfo.line]>=0) or (InlineLevel>0)) then
  276. AsmWriteLn(target_asm.comment+'['+tostr(hp1.fileinfo.line)+'] '+
  277. fixline(infile.GetLineStr(hp1.fileinfo.line)));
  278. { set it to a negative value !
  279. to make that is has been read already !! PM }
  280. if (infile.linebuf^[hp1.fileinfo.line]>=0) then
  281. infile.linebuf^[hp1.fileinfo.line]:=-infile.linebuf^[hp1.fileinfo.line]-1;
  282. end;
  283. end;
  284. lastfileinfo:=hp1.fileinfo;
  285. lastinfile:=infile;
  286. end;
  287. end;
  288. case hp.typ of
  289. ait_comment :
  290. Begin
  291. AsmWrite(target_asm.comment);
  292. AsmWritePChar(tai_comment(hp).str);
  293. AsmLn;
  294. End;
  295. ait_regalloc :
  296. begin
  297. if (cs_asm_regalloc in aktglobalswitches) then
  298. begin
  299. AsmWrite(#9+target_asm.comment+'Register ');
  300. repeat
  301. AsmWrite(gas_regname(Tai_regalloc(hp).reg));
  302. if (hp.next=nil) or
  303. (tai(hp.next).typ<>ait_regalloc) or
  304. (tai_regalloc(hp.next).ratype<>tai_regalloc(hp).ratype) then
  305. break;
  306. hp:=tai(hp.next);
  307. AsmWrite(',');
  308. until false;
  309. AsmWrite(' ');
  310. AsmWriteLn(regallocstr[tai_regalloc(hp).ratype]);
  311. end;
  312. end;
  313. ait_tempalloc :
  314. begin
  315. if (cs_asm_tempalloc in aktglobalswitches) then
  316. begin
  317. {$ifdef EXTDEBUG}
  318. if assigned(tai_tempalloc(hp).problem) then
  319. AsmWriteLn(target_asm.comment+'Temp '+tostr(tai_tempalloc(hp).temppos)+','+
  320. tostr(tai_tempalloc(hp).tempsize)+' '+tai_tempalloc(hp).problem^)
  321. else
  322. {$endif EXTDEBUG}
  323. AsmWriteLn(target_asm.comment+'Temp '+tostr(tai_tempalloc(hp).temppos)+','+
  324. tostr(tai_tempalloc(hp).tempsize)+' '+tempallocstr[tai_tempalloc(hp).allocation]);
  325. end;
  326. end;
  327. ait_align :
  328. begin
  329. if tai_align(hp).aligntype>1 then
  330. begin
  331. if target_info.system <> system_powerpc_darwin then
  332. begin
  333. AsmWrite(#9'.balign '+tostr(tai_align(hp).aligntype));
  334. if tai_align(hp).use_op then
  335. AsmWrite(','+tostr(tai_align(hp).fillop))
  336. end
  337. else
  338. begin
  339. { darwin as only supports .align }
  340. if not ispowerof2(tai_align(hp).aligntype,i) then
  341. internalerror(2003010305);
  342. AsmWrite(#9'.align '+tostr(i));
  343. last_align := i;
  344. end;
  345. AsmLn;
  346. end;
  347. end;
  348. ait_section :
  349. begin
  350. if tai_section(hp).sectype<>sec_none then
  351. WriteSection(tai_section(hp).sectype,tai_section(hp).name^)
  352. else
  353. begin
  354. {$ifdef EXTDEBUG}
  355. AsmWrite(target_asm.comment);
  356. AsmWriteln(' sec_none');
  357. {$endif EXTDEBUG}
  358. end;
  359. end;
  360. ait_datablock :
  361. begin
  362. if target_info.system=system_powerpc_darwin then
  363. begin
  364. {On Mac OS X you can't have common symbols in a shared
  365. library, since those are in the TEXT section and the text section is
  366. read-only in shared libraries (so it can be shared among different
  367. processes). The alternate code creates some kind of common symbols in
  368. the data segment. The generic code no longer uses common symbols, but
  369. this doesn't work on Mac OS X as well.}
  370. if tai_datablock(hp).is_global then
  371. begin
  372. asmwrite('.globl ');
  373. asmwriteln(tai_datablock(hp).sym.name);
  374. asmwriteln('.data');
  375. asmwrite('.zerofill __DATA, __common, ');
  376. asmwrite(tai_datablock(hp).sym.name);
  377. asmwriteln(', '+tostr(tai_datablock(hp).size)+','+tostr(last_align));
  378. if not(CurrSecType in [sec_data,sec_none]) then
  379. writesection(CurrSecType,'');
  380. end
  381. else
  382. begin
  383. asmwrite(#9'.lcomm'#9);
  384. asmwrite(tai_datablock(hp).sym.name);
  385. asmwrite(','+tostr(tai_datablock(hp).size));
  386. asmwrite(','+tostr(last_align));
  387. asmwriteln('');
  388. end
  389. end
  390. else
  391. begin
  392. if Tai_datablock(hp).is_global then
  393. begin
  394. asmwrite(#9'.globl ');
  395. asmwriteln(Tai_datablock(hp).sym.name);
  396. end;
  397. asmwrite(Tai_datablock(hp).sym.name);
  398. asmwriteln(':');
  399. asmwriteln(#9'.space '+tostr(Tai_datablock(hp).size));
  400. end;
  401. end;
  402. {$ifndef cpu64bit}
  403. ait_const_128bit :
  404. begin
  405. internalerror(200404291);
  406. end;
  407. ait_const_64bit :
  408. begin
  409. if assigned(tai_const(hp).sym) then
  410. internalerror(200404292);
  411. AsmWrite(ait_const2str[ait_const_32bit]);
  412. if target_info.endian = endian_little then
  413. begin
  414. AsmWrite(tostr(longint(lo(tai_const(hp).value))));
  415. AsmWrite(',');
  416. AsmWrite(tostr(longint(hi(tai_const(hp).value))));
  417. end
  418. else
  419. begin
  420. AsmWrite(tostr(longint(hi(tai_const(hp).value))));
  421. AsmWrite(',');
  422. AsmWrite(tostr(longint(lo(tai_const(hp).value))));
  423. end;
  424. AsmLn;
  425. end;
  426. {$endif cpu64bit}
  427. ait_const_uleb128bit,
  428. ait_const_sleb128bit,
  429. {$ifdef cpu64bit}
  430. ait_const_128bit,
  431. ait_const_64bit,
  432. {$endif cpu64bit}
  433. ait_const_32bit,
  434. ait_const_16bit,
  435. ait_const_8bit,
  436. ait_const_rva_symbol,
  437. ait_const_indirect_symbol :
  438. begin
  439. AsmWrite(ait_const2str[hp.typ]);
  440. consttyp:=hp.typ;
  441. l:=0;
  442. repeat
  443. if assigned(tai_const(hp).sym) then
  444. begin
  445. if assigned(tai_const(hp).endsym) then
  446. s:=tai_const(hp).endsym.name+'-'+tai_const(hp).sym.name
  447. else
  448. s:=tai_const(hp).sym.name;
  449. if tai_const(hp).value<>0 then
  450. s:=s+tostr_with_plus(tai_const(hp).value);
  451. end
  452. else
  453. s:=tostr(tai_const(hp).value);
  454. AsmWrite(s);
  455. inc(l,length(s));
  456. { Values with symbols are written on a single line to improve
  457. reading of the .s file (PFV) }
  458. if assigned(tai_const(hp).sym) or
  459. not(CurrSecType in [sec_data,sec_rodata]) or
  460. (l>line_length) or
  461. (hp.next=nil) or
  462. (tai(hp.next).typ<>consttyp) or
  463. assigned(tai_const(hp.next).sym) then
  464. break;
  465. hp:=tai(hp.next);
  466. AsmWrite(',');
  467. until false;
  468. AsmLn;
  469. end;
  470. {$ifdef cpuextended}
  471. ait_real_80bit :
  472. begin
  473. if do_line then
  474. AsmWriteLn(target_asm.comment+'value: '+extended2str(tai_real_80bit(hp).value));
  475. { Make sure e is a extended type, bestreal could be
  476. a different type (bestreal) !! (PFV) }
  477. e:=tai_real_80bit(hp).value;
  478. AsmWrite(#9'.byte'#9);
  479. for i:=0 to 9 do
  480. begin
  481. if i<>0 then
  482. AsmWrite(',');
  483. AsmWrite(tostr(t80bitarray(e)[i]));
  484. end;
  485. AsmLn;
  486. end;
  487. {$endif cpuextended}
  488. ait_real_64bit :
  489. begin
  490. if do_line then
  491. AsmWriteLn(target_asm.comment+'value: '+double2str(tai_real_64bit(hp).value));
  492. d:=tai_real_64bit(hp).value;
  493. { swap the values to correct endian if required }
  494. if source_info.endian <> target_info.endian then
  495. swap64bitarray(t64bitarray(d));
  496. AsmWrite(#9'.byte'#9);
  497. {$ifdef arm}
  498. { on a real arm cpu, it's already hi/lo swapped }
  499. {$ifndef cpuarm}
  500. if tai_real_64bit(hp).formatoptions=fo_hiloswapped then
  501. begin
  502. for i:=4 to 7 do
  503. begin
  504. if i<>4 then
  505. AsmWrite(',');
  506. AsmWrite(tostr(t64bitarray(d)[i]));
  507. end;
  508. for i:=0 to 3 do
  509. begin
  510. AsmWrite(',');
  511. AsmWrite(tostr(t64bitarray(d)[i]));
  512. end;
  513. end
  514. else
  515. {$endif cpuarm}
  516. {$endif arm}
  517. begin
  518. for i:=0 to 7 do
  519. begin
  520. if i<>0 then
  521. AsmWrite(',');
  522. AsmWrite(tostr(t64bitarray(d)[i]));
  523. end;
  524. end;
  525. AsmLn;
  526. end;
  527. ait_real_32bit :
  528. begin
  529. if do_line then
  530. AsmWriteLn(target_asm.comment+'value: '+single2str(tai_real_32bit(hp).value));
  531. sin:=tai_real_32bit(hp).value;
  532. { swap the values to correct endian if required }
  533. if source_info.endian <> target_info.endian then
  534. swap32bitarray(t32bitarray(sin));
  535. AsmWrite(#9'.byte'#9);
  536. for i:=0 to 3 do
  537. begin
  538. if i<>0 then
  539. AsmWrite(',');
  540. AsmWrite(tostr(t32bitarray(sin)[i]));
  541. end;
  542. AsmLn;
  543. end;
  544. ait_comp_64bit :
  545. begin
  546. if do_line then
  547. AsmWriteLn(target_asm.comment+'value: '+extended2str(tai_comp_64bit(hp).value));
  548. AsmWrite(#9'.byte'#9);
  549. {$ifdef FPC}
  550. co:=comp(tai_comp_64bit(hp).value);
  551. {$else}
  552. co:=tai_comp_64bit(hp).value;
  553. {$endif}
  554. { swap the values to correct endian if required }
  555. if source_info.endian <> target_info.endian then
  556. swap64bitarray(t64bitarray(co));
  557. for i:=0 to 7 do
  558. begin
  559. if i<>0 then
  560. AsmWrite(',');
  561. AsmWrite(tostr(t64bitarray(co)[i]));
  562. end;
  563. AsmLn;
  564. end;
  565. ait_string :
  566. begin
  567. pos:=0;
  568. for i:=1 to tai_string(hp).len do
  569. begin
  570. if pos=0 then
  571. begin
  572. AsmWrite(#9'.ascii'#9'"');
  573. pos:=20;
  574. end;
  575. ch:=tai_string(hp).str[i-1];
  576. case ch of
  577. #0, {This can't be done by range, because a bug in FPC}
  578. #1..#31,
  579. #128..#255 : s:='\'+tostr(ord(ch) shr 6)+tostr((ord(ch) and 63) shr 3)+tostr(ord(ch) and 7);
  580. '"' : s:='\"';
  581. '\' : s:='\\';
  582. else
  583. s:=ch;
  584. end;
  585. AsmWrite(s);
  586. inc(pos,length(s));
  587. if (pos>line_length) or (i=tai_string(hp).len) then
  588. begin
  589. AsmWriteLn('"');
  590. pos:=0;
  591. end;
  592. end;
  593. end;
  594. ait_label :
  595. begin
  596. if (tai_label(hp).l.is_used) then
  597. begin
  598. if tai_label(hp).l.defbind=AB_GLOBAL then
  599. begin
  600. AsmWrite('.globl'#9);
  601. AsmWriteLn(tai_label(hp).l.name);
  602. end;
  603. AsmWrite(tai_label(hp).l.name);
  604. AsmWriteLn(':');
  605. end;
  606. end;
  607. ait_symbol :
  608. begin
  609. if tai_symbol(hp).is_global then
  610. begin
  611. AsmWrite('.globl'#9);
  612. AsmWriteLn(tai_symbol(hp).sym.name);
  613. end;
  614. if target_info.system in [system_i386_linux,system_i386_beos,
  615. system_powerpc_linux,system_m68k_linux,
  616. system_sparc_linux,system_alpha_linux,
  617. system_x86_64_linux,system_arm_linux] then
  618. begin
  619. AsmWrite(#9'.type'#9);
  620. AsmWrite(tai_symbol(hp).sym.name);
  621. if assigned(tai(hp.next)) and
  622. (tai(hp.next).typ in [ait_const_rva_symbol,
  623. ait_const_32bit,ait_const_16bit,ait_const_8bit,ait_datablock,
  624. ait_real_32bit,ait_real_64bit,ait_real_80bit,ait_comp_64bit]) then
  625. begin
  626. if target_info.system = system_arm_linux then
  627. AsmWriteLn(',#object')
  628. else
  629. AsmWriteLn(',@object')
  630. end
  631. else
  632. begin
  633. if target_info.system = system_arm_linux then
  634. AsmWriteLn(',#function')
  635. else
  636. AsmWriteLn(',@function');
  637. end;
  638. if tai_symbol(hp).sym.size>0 then
  639. begin
  640. AsmWrite(#9'.size'#9);
  641. AsmWrite(tai_symbol(hp).sym.name);
  642. AsmWrite(', ');
  643. AsmWriteLn(tostr(tai_symbol(hp).sym.size));
  644. end;
  645. end;
  646. AsmWrite(tai_symbol(hp).sym.name);
  647. AsmWriteLn(':');
  648. end;
  649. ait_symbol_end :
  650. begin
  651. if tf_needs_symbol_size in target_info.flags then
  652. begin
  653. s:=target_asm.labelprefix+'e'+tostr(symendcount);
  654. inc(symendcount);
  655. AsmWriteLn(s+':');
  656. AsmWrite(#9'.size'#9);
  657. AsmWrite(tai_symbol_end(hp).sym.name);
  658. AsmWrite(', '+s+' - ');
  659. AsmWriteLn(tai_symbol_end(hp).sym.name);
  660. end;
  661. end;
  662. ait_instruction :
  663. begin
  664. WriteInstruction(hp);
  665. end;
  666. ait_stab :
  667. begin
  668. if assigned(tai_stab(hp).str) then
  669. begin
  670. AsmWrite(#9'.'+stabtypestr[tai_stab(hp).stabtype]+' ');
  671. AsmWritePChar(tai_stab(hp).str);
  672. AsmLn;
  673. end;
  674. end;
  675. ait_force_line,
  676. ait_function_name : ;
  677. ait_cutobject :
  678. begin
  679. if SmartAsm then
  680. begin
  681. { only reset buffer if nothing has changed }
  682. if AsmSize=AsmStartSize then
  683. AsmClear
  684. else
  685. begin
  686. AsmClose;
  687. DoAssemble;
  688. AsmCreate(tai_cutobject(hp).place);
  689. end;
  690. { avoid empty files }
  691. while assigned(hp.next) and (tai(hp.next).typ in [ait_cutobject,ait_section,ait_comment]) do
  692. begin
  693. if tai(hp.next).typ=ait_section then
  694. CurrSecType:=tai_section(hp.next).sectype;
  695. hp:=tai(hp.next);
  696. end;
  697. if CurrSecType<>sec_none then
  698. WriteSection(CurrSecType,'');
  699. AsmStartSize:=AsmSize;
  700. end;
  701. end;
  702. ait_marker :
  703. if tai_marker(hp).kind=InlineStart then
  704. inc(InlineLevel)
  705. else if tai_marker(hp).kind=InlineEnd then
  706. dec(InlineLevel);
  707. ait_directive :
  708. begin
  709. AsmWrite('.'+directivestr[tai_directive(hp).directive]+' ');
  710. if assigned(tai_directive(hp).name) then
  711. AsmWrite(tai_directive(hp).name^);
  712. AsmLn;
  713. end;
  714. else
  715. internalerror(10000);
  716. end;
  717. hp:=tai(hp.next);
  718. end;
  719. end;
  720. procedure TGNUAssembler.WriteExtraHeader;
  721. begin
  722. end;
  723. procedure TGNUAssembler.WriteAsmList;
  724. var
  725. p:dirstr;
  726. n:namestr;
  727. e:extstr;
  728. hal : tasmlist;
  729. begin
  730. {$ifdef EXTDEBUG}
  731. if assigned(current_module.mainsource) then
  732. Comment(V_Debug,'Start writing gas-styled assembler output for '+current_module.mainsource^);
  733. {$endif}
  734. CurrSecType:=sec_none;
  735. FillChar(lastfileinfo,sizeof(lastfileinfo),0);
  736. LastInfile:=nil;
  737. if assigned(current_module.mainsource) then
  738. {$IFDEF USE_SYSUTILS}
  739. begin
  740. p := SplitPath(current_module.mainsource^);
  741. n := SplitName(current_module.mainsource^);
  742. e := SplitExtension(current_module.mainsource^);
  743. end
  744. {$ELSE USE_SYSUTILS}
  745. fsplit(current_module.mainsource^,p,n,e)
  746. {$ENDIF USE_SYSUTILS}
  747. else
  748. begin
  749. p:=inputdir;
  750. n:=inputfile;
  751. e:=inputextension;
  752. end;
  753. { to get symify to work }
  754. AsmWriteLn(#9'.file "'+FixFileName(n+e)+'"');
  755. WriteExtraHeader;
  756. AsmStartSize:=AsmSize;
  757. symendcount:=0;
  758. for hal:=low(Tasmlist) to high(Tasmlist) do
  759. begin
  760. AsmWriteLn(target_asm.comment+'Begin asmlist '+TasmlistStr[hal]);
  761. writetree(asmlist[hal]);
  762. AsmWriteLn(target_asm.comment+'End asmlist '+TasmlistStr[hal]);
  763. end;
  764. AsmLn;
  765. {$ifdef EXTDEBUG}
  766. if assigned(current_module.mainsource) then
  767. Comment(V_Debug,'Done writing gas-styled assembler output for '+current_module.mainsource^);
  768. {$endif EXTDEBUG}
  769. end;
  770. end.