aggas.pas 29 KB

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