aggas.pas 29 KB

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