aggas.pas 29 KB

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