aggas.pas 28 KB

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