aggas.pas 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890
  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. asmwriteln(#9'.type '+Tai_datablock(hp).sym.name+',@object');
  424. asmwriteln(#9'.size '+Tai_datablock(hp).sym.name+','+tostr(Tai_datablock(hp).size));
  425. asmwrite(Tai_datablock(hp).sym.name);
  426. asmwriteln(':');
  427. asmwriteln(#9'.zero '+tostr(Tai_datablock(hp).size));
  428. end;
  429. end;
  430. {$ifndef cpu64bit}
  431. ait_const_128bit :
  432. begin
  433. internalerror(200404291);
  434. end;
  435. ait_const_64bit :
  436. begin
  437. if assigned(tai_const(hp).sym) then
  438. internalerror(200404292);
  439. AsmWrite(ait_const2str[ait_const_32bit]);
  440. if target_info.endian = endian_little then
  441. begin
  442. AsmWrite(tostr(longint(lo(tai_const(hp).value))));
  443. AsmWrite(',');
  444. AsmWrite(tostr(longint(hi(tai_const(hp).value))));
  445. end
  446. else
  447. begin
  448. AsmWrite(tostr(longint(hi(tai_const(hp).value))));
  449. AsmWrite(',');
  450. AsmWrite(tostr(longint(lo(tai_const(hp).value))));
  451. end;
  452. AsmLn;
  453. end;
  454. {$endif cpu64bit}
  455. ait_const_uleb128bit,
  456. ait_const_sleb128bit,
  457. {$ifdef cpu64bit}
  458. ait_const_128bit,
  459. ait_const_64bit,
  460. {$endif cpu64bit}
  461. ait_const_32bit,
  462. ait_const_16bit,
  463. ait_const_8bit,
  464. ait_const_rva_symbol,
  465. ait_const_indirect_symbol :
  466. begin
  467. AsmWrite(ait_const2str[hp.typ]);
  468. consttyp:=hp.typ;
  469. l:=0;
  470. repeat
  471. if assigned(tai_const(hp).sym) then
  472. begin
  473. if assigned(tai_const(hp).endsym) then
  474. s:=tai_const(hp).endsym.name+'-'+tai_const(hp).sym.name
  475. else
  476. s:=tai_const(hp).sym.name;
  477. if tai_const(hp).value<>0 then
  478. s:=s+tostr_with_plus(tai_const(hp).value);
  479. end
  480. else
  481. s:=tostr(tai_const(hp).value);
  482. AsmWrite(s);
  483. inc(l,length(s));
  484. { Values with symbols are written on a single line to improve
  485. reading of the .s file (PFV) }
  486. if assigned(tai_const(hp).sym) or
  487. not(CurrSecType in [sec_data,sec_rodata]) or
  488. (l>line_length) or
  489. (hp.next=nil) or
  490. (tai(hp.next).typ<>consttyp) or
  491. assigned(tai_const(hp.next).sym) then
  492. break;
  493. hp:=tai(hp.next);
  494. AsmWrite(',');
  495. until false;
  496. AsmLn;
  497. end;
  498. {$ifdef cpuextended}
  499. ait_real_80bit :
  500. begin
  501. if do_line then
  502. AsmWriteLn(target_asm.comment+'value: '+extended2str(tai_real_80bit(hp).value));
  503. { Make sure e is a extended type, bestreal could be
  504. a different type (bestreal) !! (PFV) }
  505. e:=tai_real_80bit(hp).value;
  506. AsmWrite(#9'.byte'#9);
  507. for i:=0 to 9 do
  508. begin
  509. if i<>0 then
  510. AsmWrite(',');
  511. AsmWrite(tostr(t80bitarray(e)[i]));
  512. end;
  513. AsmLn;
  514. end;
  515. {$endif cpuextended}
  516. ait_real_64bit :
  517. begin
  518. if do_line then
  519. AsmWriteLn(target_asm.comment+'value: '+double2str(tai_real_64bit(hp).value));
  520. d:=tai_real_64bit(hp).value;
  521. { swap the values to correct endian if required }
  522. if source_info.endian <> target_info.endian then
  523. swap64bitarray(t64bitarray(d));
  524. AsmWrite(#9'.byte'#9);
  525. {$ifdef arm}
  526. { on a real arm cpu, it's already hi/lo swapped }
  527. {$ifndef cpuarm}
  528. if tai_real_64bit(hp).formatoptions=fo_hiloswapped then
  529. begin
  530. for i:=4 to 7 do
  531. begin
  532. if i<>4 then
  533. AsmWrite(',');
  534. AsmWrite(tostr(t64bitarray(d)[i]));
  535. end;
  536. for i:=0 to 3 do
  537. begin
  538. AsmWrite(',');
  539. AsmWrite(tostr(t64bitarray(d)[i]));
  540. end;
  541. end
  542. else
  543. {$endif cpuarm}
  544. {$endif arm}
  545. begin
  546. for i:=0 to 7 do
  547. begin
  548. if i<>0 then
  549. AsmWrite(',');
  550. AsmWrite(tostr(t64bitarray(d)[i]));
  551. end;
  552. end;
  553. AsmLn;
  554. end;
  555. ait_real_32bit :
  556. begin
  557. if do_line then
  558. AsmWriteLn(target_asm.comment+'value: '+single2str(tai_real_32bit(hp).value));
  559. sin:=tai_real_32bit(hp).value;
  560. { swap the values to correct endian if required }
  561. if source_info.endian <> target_info.endian then
  562. swap32bitarray(t32bitarray(sin));
  563. AsmWrite(#9'.byte'#9);
  564. for i:=0 to 3 do
  565. begin
  566. if i<>0 then
  567. AsmWrite(',');
  568. AsmWrite(tostr(t32bitarray(sin)[i]));
  569. end;
  570. AsmLn;
  571. end;
  572. ait_comp_64bit :
  573. begin
  574. if do_line then
  575. AsmWriteLn(target_asm.comment+'value: '+extended2str(tai_comp_64bit(hp).value));
  576. AsmWrite(#9'.byte'#9);
  577. {$ifdef FPC}
  578. co:=comp(tai_comp_64bit(hp).value);
  579. {$else}
  580. co:=tai_comp_64bit(hp).value;
  581. {$endif}
  582. { swap the values to correct endian if required }
  583. if source_info.endian <> target_info.endian then
  584. swap64bitarray(t64bitarray(co));
  585. for i:=0 to 7 do
  586. begin
  587. if i<>0 then
  588. AsmWrite(',');
  589. AsmWrite(tostr(t64bitarray(co)[i]));
  590. end;
  591. AsmLn;
  592. end;
  593. ait_string :
  594. begin
  595. pos:=0;
  596. for i:=1 to tai_string(hp).len do
  597. begin
  598. if pos=0 then
  599. begin
  600. AsmWrite(#9'.ascii'#9'"');
  601. pos:=20;
  602. end;
  603. ch:=tai_string(hp).str[i-1];
  604. case ch of
  605. #0, {This can't be done by range, because a bug in FPC}
  606. #1..#31,
  607. #128..#255 : s:='\'+tostr(ord(ch) shr 6)+tostr((ord(ch) and 63) shr 3)+tostr(ord(ch) and 7);
  608. '"' : s:='\"';
  609. '\' : s:='\\';
  610. else
  611. s:=ch;
  612. end;
  613. AsmWrite(s);
  614. inc(pos,length(s));
  615. if (pos>line_length) or (i=tai_string(hp).len) then
  616. begin
  617. AsmWriteLn('"');
  618. pos:=0;
  619. end;
  620. end;
  621. end;
  622. ait_label :
  623. begin
  624. if (tai_label(hp).l.is_used) then
  625. begin
  626. if tai_label(hp).l.defbind=AB_GLOBAL then
  627. begin
  628. AsmWrite('.globl'#9);
  629. AsmWriteLn(tai_label(hp).l.name);
  630. end;
  631. AsmWrite(tai_label(hp).l.name);
  632. AsmWriteLn(':');
  633. end;
  634. end;
  635. ait_symbol :
  636. begin
  637. if tai_symbol(hp).is_global then
  638. begin
  639. AsmWrite('.globl'#9);
  640. AsmWriteLn(tai_symbol(hp).sym.name);
  641. end;
  642. if (target_info.system = system_powerpc64_linux) and
  643. (tai_symbol(hp).sym.typ = AT_FUNCTION) then
  644. begin
  645. AsmWriteLn('.section "opd", "aw"');
  646. AsmWriteLn('.align 3');
  647. AsmWriteLn(tai_symbol(hp).sym.name + ':');
  648. AsmWriteLn('.quad .' + tai_symbol(hp).sym.name + ', .TOC.@tocbase, 0');
  649. AsmWriteLn('.previous');
  650. AsmWriteLn('.size ' + tai_symbol(hp).sym.name + ', 24');
  651. AsmWriteLn('.globl .' + tai_symbol(hp).sym.name);
  652. AsmWriteLn('.type .' + tai_symbol(hp).sym.name + ', @function');
  653. { the dotted name is the name of the actual function }
  654. AsmWrite('.');
  655. end
  656. else
  657. begin
  658. if (target_info.system <> system_arm_linux) then
  659. begin
  660. sepChar := '@';
  661. end
  662. else
  663. begin
  664. sepChar := '#';
  665. end;
  666. if (tf_needs_symbol_type in target_info.flags) then
  667. begin
  668. AsmWrite(#9'.type'#9 + tai_symbol(hp).sym.name);
  669. if (needsObject(tai_symbol(hp))) then
  670. begin
  671. AsmWriteLn(',' + sepChar + 'object');
  672. end
  673. else
  674. begin
  675. AsmWriteLn(',' + sepChar + 'function');
  676. end;
  677. end;
  678. if (tf_needs_symbol_size in target_info.flags) and (tai_symbol(hp).sym.size > 0) then begin
  679. AsmWriteLn(#9'.size'#9 + tai_symbol(hp).sym.name + ', ' + tostr(tai_symbol(hp).sym.size));
  680. end;
  681. end;
  682. AsmWriteLn(tai_symbol(hp).sym.name + ':');
  683. end;
  684. ait_symbol_end :
  685. begin
  686. if tf_needs_symbol_size in target_info.flags then
  687. begin
  688. s:=target_asm.labelprefix+'e'+tostr(symendcount);
  689. inc(symendcount);
  690. AsmWriteLn(s+':');
  691. AsmWrite(#9'.size'#9);
  692. if (target_info.system = system_powerpc64_linux) and (tai_symbol_end(hp).sym.typ = AT_FUNCTION) then
  693. begin
  694. AsmWrite('.');
  695. end;
  696. AsmWrite(tai_symbol_end(hp).sym.name);
  697. AsmWrite(', '+s+' - ');
  698. if (target_info.system = system_powerpc64_linux) and (tai_symbol_end(hp).sym.typ = AT_FUNCTION) then
  699. begin
  700. AsmWrite('.');
  701. end;
  702. AsmWriteLn(tai_symbol_end(hp).sym.name);
  703. end;
  704. end;
  705. ait_instruction :
  706. begin
  707. WriteInstruction(hp);
  708. end;
  709. ait_stab :
  710. begin
  711. if assigned(tai_stab(hp).str) then
  712. begin
  713. AsmWrite(#9'.'+stabtypestr[tai_stab(hp).stabtype]+' ');
  714. AsmWritePChar(tai_stab(hp).str);
  715. AsmLn;
  716. end;
  717. end;
  718. ait_force_line,
  719. ait_function_name : ;
  720. ait_cutobject :
  721. begin
  722. if SmartAsm then
  723. begin
  724. { only reset buffer if nothing has changed }
  725. if AsmSize=AsmStartSize then
  726. AsmClear
  727. else
  728. begin
  729. AsmClose;
  730. DoAssemble;
  731. AsmCreate(tai_cutobject(hp).place);
  732. end;
  733. { avoid empty files }
  734. while assigned(hp.next) and (tai(hp.next).typ in [ait_cutobject,ait_section,ait_comment]) do
  735. begin
  736. if tai(hp.next).typ=ait_section then
  737. CurrSecType:=tai_section(hp.next).sectype;
  738. hp:=tai(hp.next);
  739. end;
  740. if CurrSecType<>sec_none then
  741. WriteSection(CurrSecType,'');
  742. AsmStartSize:=AsmSize;
  743. end;
  744. end;
  745. ait_marker :
  746. if tai_marker(hp).kind=InlineStart then
  747. inc(InlineLevel)
  748. else if tai_marker(hp).kind=InlineEnd then
  749. dec(InlineLevel);
  750. ait_directive :
  751. begin
  752. AsmWrite('.'+directivestr[tai_directive(hp).directive]+' ');
  753. if assigned(tai_directive(hp).name) then
  754. AsmWrite(tai_directive(hp).name^);
  755. AsmLn;
  756. end;
  757. else
  758. internalerror(10000);
  759. end;
  760. hp:=tai(hp.next);
  761. end;
  762. end;
  763. procedure TGNUAssembler.WriteExtraHeader;
  764. begin
  765. end;
  766. procedure TGNUAssembler.WriteAsmList;
  767. var
  768. p:dirstr;
  769. n:namestr;
  770. e:extstr;
  771. hal : tasmlist;
  772. begin
  773. {$ifdef EXTDEBUG}
  774. if assigned(current_module.mainsource) then
  775. Comment(V_Debug,'Start writing gas-styled assembler output for '+current_module.mainsource^);
  776. {$endif}
  777. CurrSecType:=sec_none;
  778. FillChar(lastfileinfo,sizeof(lastfileinfo),0);
  779. LastInfile:=nil;
  780. if assigned(current_module.mainsource) then
  781. {$IFDEF USE_SYSUTILS}
  782. begin
  783. p := SplitPath(current_module.mainsource^);
  784. n := SplitName(current_module.mainsource^);
  785. e := SplitExtension(current_module.mainsource^);
  786. end
  787. {$ELSE USE_SYSUTILS}
  788. fsplit(current_module.mainsource^,p,n,e)
  789. {$ENDIF USE_SYSUTILS}
  790. else
  791. begin
  792. p:=inputdir;
  793. n:=inputfile;
  794. e:=inputextension;
  795. end;
  796. { to get symify to work }
  797. AsmWriteLn(#9'.file "'+FixFileName(n+e)+'"');
  798. WriteExtraHeader;
  799. AsmStartSize:=AsmSize;
  800. symendcount:=0;
  801. for hal:=low(Tasmlist) to high(Tasmlist) do
  802. begin
  803. AsmWriteLn(target_asm.comment+'Begin asmlist '+TasmlistStr[hal]);
  804. writetree(asmlist[hal]);
  805. AsmWriteLn(target_asm.comment+'End asmlist '+TasmlistStr[hal]);
  806. end;
  807. AsmLn;
  808. {$ifdef EXTDEBUG}
  809. if assigned(current_module.mainsource) then
  810. Comment(V_Debug,'Done writing gas-styled assembler output for '+current_module.mainsource^);
  811. {$endif EXTDEBUG}
  812. end;
  813. end.