ag386bin.pas 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Peter Vreman
  4. This unit implements an binary assembler output class
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. {$ifdef TP}
  19. {$N+,E+}
  20. {$endif}
  21. unit ag386bin;
  22. {$define MULTIPASS}
  23. {$define EXTERNALBSS}
  24. interface
  25. uses
  26. cpubase,cobjects,aasm,files,assemble;
  27. type
  28. togtype=(og_none,og_dbg,og_coff,og_pecoff);
  29. pi386binasmlist=^ti386binasmlist;
  30. ti386binasmlist=object
  31. SmartAsm : boolean;
  32. constructor init(t:togtype;smart:boolean);
  33. destructor done;
  34. procedure WriteBin;
  35. private
  36. { the aasmoutput lists that need to be processed }
  37. lists : byte;
  38. list : array[1..maxoutputlists] of paasmoutput;
  39. { current processing }
  40. currlistidx : byte;
  41. currlist : paasmoutput;
  42. currpass : byte;
  43. {$ifdef GDB}
  44. n_line : byte; { different types of source lines }
  45. linecount,
  46. includecount : longint;
  47. funcname : pasmsymbol;
  48. stabslastfileinfo : tfileposinfo;
  49. procedure convertstabs(p:pchar);
  50. {$ifdef unused}
  51. procedure emitsymbolstabs(s : string;nidx,nother,line : longint;firstasm,secondasm : pasmsymbol);
  52. {$endif}
  53. procedure emitlineinfostabs(nidx,line : longint);
  54. procedure emitstabs(s:string);
  55. procedure WriteFileLineInfo(var fileinfo : tfileposinfo);
  56. procedure StartFileLineInfo;
  57. procedure EndFileLineInfo;
  58. {$endif}
  59. function MaybeNextList(var hp:pai):boolean;
  60. function TreePass0(hp:pai):pai;
  61. function TreePass1(hp:pai):pai;
  62. function TreePass2(hp:pai):pai;
  63. procedure writetree;
  64. procedure writetreesmart;
  65. end;
  66. implementation
  67. uses
  68. strings,
  69. globtype,globals,systems,verbose,
  70. cpuasm,
  71. {$ifdef GDB}
  72. gdb,
  73. {$endif}
  74. og386,og386dbg,og386cff;
  75. {$ifdef GDB}
  76. procedure ti386binasmlist.convertstabs(p:pchar);
  77. var
  78. ofs,
  79. nidx,nother,ii,i,line,j : longint;
  80. code : integer;
  81. hp : pchar;
  82. reloc : boolean;
  83. sec : tsection;
  84. ps : pasmsymbol;
  85. s : string;
  86. begin
  87. ofs:=0;
  88. reloc:=true;
  89. ps:=nil;
  90. sec:=sec_none;
  91. if p[0]='"' then
  92. begin
  93. i:=1;
  94. { we can have \" inside the string !! PM }
  95. while not ((p[i]='"') and (p[i-1]<>'\')) do
  96. inc(i);
  97. p[i]:=#0;
  98. ii:=i;
  99. hp:=@p[1];
  100. s:=StrPas(@P[i+2]);
  101. end
  102. else
  103. begin
  104. hp:=nil;
  105. s:=StrPas(P);
  106. i:=-2; {needed below (PM) }
  107. end;
  108. { When in pass 1 then only alloc and leave }
  109. if currpass=1 then
  110. begin
  111. objectalloc^.staballoc(hp);
  112. if assigned(hp) then
  113. p[i]:='"';
  114. exit;
  115. end;
  116. { Parse the rest of the stabs }
  117. if s='' then
  118. internalerror(33000);
  119. j:=pos(',',s);
  120. if j=0 then
  121. internalerror(33001);
  122. Val(Copy(s,1,j-1),nidx,code);
  123. if code<>0 then
  124. internalerror(33002);
  125. i:=i+2+j;
  126. Delete(s,1,j);
  127. j:=pos(',',s);
  128. if (j=0) then
  129. internalerror(33003);
  130. Val(Copy(s,1,j-1),nother,code);
  131. if code<>0 then
  132. internalerror(33004);
  133. i:=i+j;
  134. Delete(s,1,j);
  135. j:=pos(',',s);
  136. if j=0 then
  137. begin
  138. j:=256;
  139. ofs:=-1;
  140. end;
  141. Val(Copy(s,1,j-1),line,code);
  142. if code<>0 then
  143. internalerror(33005);
  144. if ofs=0 then
  145. begin
  146. Delete(s,1,j);
  147. i:=i+j;
  148. Val(s,ofs,code);
  149. if code=0 then
  150. reloc:=false
  151. else
  152. begin
  153. ofs:=0;
  154. s:=strpas(@p[i]);
  155. { handle asmsymbol or
  156. asmsymbol - asmsymbol }
  157. j:=pos(' ',s);
  158. if j=0 then
  159. j:=pos('-',s);
  160. { single asmsymbol }
  161. if j=0 then
  162. j:=256;
  163. { the symbol can be external
  164. so we must use newasmsymbol and
  165. not getasmsymbol !! PM }
  166. ps:=newasmsymbol(copy(s,1,j-1));
  167. if not assigned(ps) then
  168. internalerror(33006)
  169. else
  170. begin
  171. sec:=ps^.section;
  172. ofs:=ps^.address;
  173. reloc:=true;
  174. end;
  175. if j<256 then
  176. begin
  177. i:=i+j;
  178. s:=strpas(@p[i]);
  179. if (s<>'') and (s[1]=' ') then
  180. begin
  181. j:=0;
  182. while (s[j+1]=' ') do
  183. inc(j);
  184. i:=i+j;
  185. s:=strpas(@p[i]);
  186. end;
  187. ps:=getasmsymbol(s);
  188. if not assigned(ps) then
  189. internalerror(33007)
  190. else
  191. begin
  192. if ps^.section<>sec then
  193. internalerror(33008);
  194. ofs:=ofs-ps^.address;
  195. reloc:=false;
  196. end;
  197. end;
  198. end;
  199. end;
  200. { external bss need speical handling (PM) }
  201. if assigned(ps) and (ps^.section=sec_none) then
  202. begin
  203. if currpass<>1 then
  204. objectoutput^.writesymbol(ps);
  205. objectoutput^.WriteSymStabs(sec,ofs,hp,ps,nidx,nother,line,reloc)
  206. end
  207. else
  208. objectoutput^.WriteStabs(sec,ofs,hp,nidx,nother,line,reloc);
  209. if assigned(hp) then
  210. p[ii]:='"';
  211. end;
  212. {$ifdef unused}
  213. procedure ti386binasmlist.emitsymbolstabs(s : string;nidx,nother,line : longint;
  214. firstasm,secondasm : pasmsymbol);
  215. var
  216. hp : pchar;
  217. begin
  218. if s='' then
  219. hp:=nil
  220. else
  221. begin
  222. s:=s+#0;
  223. hp:=@s[1];
  224. end;
  225. if not assigned(secondasm) then
  226. begin
  227. if not assigned(firstasm) then
  228. internalerror(33009);
  229. objectoutput^.WriteStabs(firstasm^.section,firstasm^.address,hp,nidx,nother,line,true);
  230. end
  231. else
  232. begin
  233. if firstasm^.section<>secondasm^.section then
  234. internalerror(33010);
  235. objectoutput^.WriteStabs(firstasm^.section,firstasm^.address-secondasm^.address,
  236. hp,nidx,nother,line,false);
  237. end;
  238. end;
  239. {$endif}
  240. procedure ti386binasmlist.emitlineinfostabs(nidx,line : longint);
  241. var
  242. sec : tsection;
  243. begin
  244. if currpass=1 then
  245. begin
  246. objectalloc^.staballoc(nil);
  247. exit;
  248. end;
  249. if (nidx=n_textline) and assigned(funcname) and
  250. (target_os.use_function_relative_addresses) then
  251. objectoutput^.WriteStabs(sec_code,pgenericcoffoutput(objectoutput)^.sects[sec_code]^.len-funcname^.address,
  252. nil,nidx,0,line,false)
  253. else
  254. begin
  255. if nidx=n_textline then
  256. sec:=sec_code
  257. else if nidx=n_dataline then
  258. sec:=sec_data
  259. else
  260. sec:=sec_bss;
  261. objectoutput^.WriteStabs(sec,pgenericcoffoutput(objectoutput)^.sects[sec]^.len,
  262. nil,nidx,0,line,true);
  263. end;
  264. end;
  265. procedure ti386binasmlist.emitstabs(s:string);
  266. begin
  267. s:=s+#0;
  268. ConvertStabs(@s[1]);
  269. end;
  270. procedure ti386binasmlist.WriteFileLineInfo(var fileinfo : tfileposinfo);
  271. var
  272. curr_n : byte;
  273. hp : pasmsymbol;
  274. infile : pinputfile;
  275. begin
  276. if not ((cs_debuginfo in aktmoduleswitches) or
  277. (cs_gdb_lineinfo in aktglobalswitches)) then
  278. exit;
  279. { file changed ? (must be before line info) }
  280. if (fileinfo.fileindex<>0) and
  281. (stabslastfileinfo.fileindex<>fileinfo.fileindex) then
  282. begin
  283. infile:=current_module^.sourcefiles^.get_file(fileinfo.fileindex);
  284. if includecount=0 then
  285. curr_n:=n_sourcefile
  286. else
  287. curr_n:=n_includefile;
  288. { get symbol for this includefile }
  289. hp:=newasmsymbol('Ltext'+ToStr(IncludeCount));
  290. if currpass=1 then
  291. begin
  292. hp^.settyp(AS_LOCAL);
  293. hp^.setaddress(objectalloc^.currsec,objectalloc^.sectionsize,0);
  294. end
  295. else
  296. objectoutput^.writesymbol(hp);
  297. { emit stabs }
  298. if (infile^.path^<>'') then
  299. EmitStabs('"'+lower(BsToSlash(FixPath(infile^.path^,false)))+'",'+tostr(curr_n)+
  300. ',0,0,Ltext'+ToStr(IncludeCount));
  301. EmitStabs('"'+lower(FixFileName(infile^.name^))+'",'+tostr(curr_n)+
  302. ',0,0,Ltext'+ToStr(IncludeCount));
  303. inc(includecount);
  304. end;
  305. { line changed ? }
  306. if (stabslastfileinfo.line<>fileinfo.line) and (fileinfo.line<>0) then
  307. emitlineinfostabs(n_line,fileinfo.line);
  308. stabslastfileinfo:=fileinfo;
  309. end;
  310. procedure ti386binasmlist.StartFileLineInfo;
  311. var
  312. fileinfo : tfileposinfo;
  313. begin
  314. FillChar(stabslastfileinfo,sizeof(stabslastfileinfo),0);
  315. n_line:=n_textline;
  316. funcname:=nil;
  317. linecount:=1;
  318. includecount:=0;
  319. fileinfo.fileindex:=1;
  320. fileinfo.line:=1;
  321. WriteFileLineInfo(fileinfo);
  322. end;
  323. procedure ti386binasmlist.EndFileLineInfo;
  324. var
  325. hp : pasmsymbol;
  326. store_sec : tsection;
  327. begin
  328. if not (cs_debuginfo in aktmoduleswitches) then
  329. exit;
  330. store_sec:=objectalloc^.currsec;
  331. objectalloc^.setsection(sec_code);
  332. hp:=newasmsymbol('Letext');
  333. if currpass=1 then
  334. begin
  335. hp^.settyp(AS_LOCAL);
  336. hp^.setaddress(objectalloc^.currsec,objectalloc^.sectionsize,0);
  337. end
  338. else
  339. objectoutput^.writesymbol(hp);
  340. EmitStabs('"",'+tostr(n_sourcefile)+
  341. ',0,0,Letext');
  342. objectalloc^.setsection(store_sec);
  343. end;
  344. {$endif GDB}
  345. function ti386binasmlist.MaybeNextList(var hp:pai):boolean;
  346. begin
  347. { maybe end of list }
  348. while not assigned(hp) do
  349. begin
  350. if currlistidx<lists then
  351. begin
  352. inc(currlistidx);
  353. currlist:=list[currlistidx];
  354. hp:=pai(currlist^.first);
  355. end
  356. else
  357. begin
  358. MaybeNextList:=false;
  359. exit;
  360. end;
  361. end;
  362. MaybeNextList:=true;
  363. end;
  364. function ti386binasmlist.TreePass0(hp:pai):pai;
  365. var
  366. l : longint;
  367. begin
  368. while assigned(hp) do
  369. begin
  370. case hp^.typ of
  371. ait_align :
  372. begin
  373. { always use the maximum fillsize in this pass to avoid possible
  374. short jumps to become out of range }
  375. pai_align(hp)^.fillsize:=pai_align(hp)^.aligntype;
  376. objectalloc^.sectionalloc(pai_align(hp)^.fillsize);
  377. end;
  378. ait_datablock :
  379. begin
  380. {$ifdef EXTERNALBSS}
  381. if not SmartAsm then
  382. begin
  383. if not pai_datablock(hp)^.is_global then
  384. begin
  385. l:=pai_datablock(hp)^.size;
  386. if l>2 then
  387. objectalloc^.sectionalign(4)
  388. else if l>1 then
  389. objectalloc^.sectionalign(2);
  390. objectalloc^.sectionalloc(pai_datablock(hp)^.size);
  391. end;
  392. end
  393. else
  394. begin
  395. {$endif}
  396. l:=pai_datablock(hp)^.size;
  397. if l>2 then
  398. objectalloc^.sectionalign(4)
  399. else if l>1 then
  400. objectalloc^.sectionalign(2);
  401. objectalloc^.sectionalloc(pai_datablock(hp)^.size);
  402. end;
  403. end;
  404. ait_const_32bit :
  405. objectalloc^.sectionalloc(4);
  406. ait_const_16bit :
  407. objectalloc^.sectionalloc(2);
  408. ait_const_8bit :
  409. objectalloc^.sectionalloc(1);
  410. ait_real_80bit :
  411. objectalloc^.sectionalloc(10);
  412. ait_real_64bit :
  413. objectalloc^.sectionalloc(8);
  414. ait_real_32bit :
  415. objectalloc^.sectionalloc(4);
  416. ait_comp_64bit :
  417. objectalloc^.sectionalloc(8);
  418. ait_const_rva,
  419. ait_const_symbol :
  420. objectalloc^.sectionalloc(4);
  421. ait_section:
  422. objectalloc^.setsection(pai_section(hp)^.sec);
  423. ait_symbol :
  424. pai_symbol(hp)^.sym^.setaddress(objectalloc^.currsec,objectalloc^.sectionsize,0);
  425. ait_label :
  426. pai_label(hp)^.l^.setaddress(objectalloc^.currsec,objectalloc^.sectionsize,0);
  427. ait_string :
  428. objectalloc^.sectionalloc(pai_string(hp)^.len);
  429. ait_instruction :
  430. begin
  431. { reset instructions which could change in pass 2 }
  432. paicpu(hp)^.resetpass2;
  433. objectalloc^.sectionalloc(paicpu(hp)^.Pass1(objectalloc^.sectionsize));
  434. end;
  435. ait_cut :
  436. if SmartAsm then
  437. break;
  438. end;
  439. hp:=pai(hp^.next);
  440. end;
  441. TreePass0:=hp;
  442. end;
  443. function ti386binasmlist.TreePass1(hp:pai):pai;
  444. var
  445. l : longint;
  446. begin
  447. while assigned(hp) do
  448. begin
  449. {$ifdef GDB}
  450. { write stabs }
  451. if ((cs_debuginfo in aktmoduleswitches) or
  452. (cs_gdb_lineinfo in aktglobalswitches)) then
  453. begin
  454. if (objectalloc^.currsec<>sec_none) and
  455. not(hp^.typ in [
  456. ait_label,
  457. ait_regalloc,ait_tempalloc,
  458. ait_stabn,ait_stabs,ait_section,
  459. ait_cut,ait_marker,ait_align,ait_stab_function_name]) then
  460. WriteFileLineInfo(hp^.fileinfo);
  461. end;
  462. {$endif GDB}
  463. case hp^.typ of
  464. ait_align :
  465. begin
  466. { here we must determine the fillsize which is used in pass2 }
  467. pai_align(hp)^.fillsize:=align(objectalloc^.sectionsize,pai_align(hp)^.aligntype)-
  468. objectalloc^.sectionsize;
  469. objectalloc^.sectionalloc(pai_align(hp)^.fillsize);
  470. end;
  471. ait_datablock :
  472. begin
  473. if objectalloc^.currsec<>sec_bss then
  474. Message(asmw_e_alloc_data_only_in_bss);
  475. {$ifdef EXTERNALBSS}
  476. if not SmartAsm then
  477. begin
  478. if pai_datablock(hp)^.is_global then
  479. begin
  480. pai_datablock(hp)^.sym^.settyp(AS_EXTERNAL);
  481. pai_datablock(hp)^.sym^.setaddress(sec_none,pai_datablock(hp)^.size,pai_datablock(hp)^.size);
  482. end
  483. else
  484. begin
  485. l:=pai_datablock(hp)^.size;
  486. if l>2 then
  487. objectalloc^.sectionalign(4)
  488. else if l>1 then
  489. objectalloc^.sectionalign(2);
  490. pai_datablock(hp)^.sym^.settyp(AS_LOCAL);
  491. pai_datablock(hp)^.sym^.setaddress(objectalloc^.currsec,objectalloc^.sectionsize,
  492. pai_datablock(hp)^.size);
  493. objectalloc^.sectionalloc(pai_datablock(hp)^.size);
  494. end;
  495. end
  496. else
  497. {$endif}
  498. begin
  499. if pai_datablock(hp)^.is_global then
  500. pai_datablock(hp)^.sym^.settyp(AS_GLOBAL)
  501. else
  502. pai_datablock(hp)^.sym^.settyp(AS_LOCAL);
  503. l:=pai_datablock(hp)^.size;
  504. if l>2 then
  505. objectalloc^.sectionalign(4)
  506. else if l>1 then
  507. objectalloc^.sectionalign(2);
  508. pai_datablock(hp)^.sym^.setaddress(objectalloc^.currsec,objectalloc^.sectionsize,pai_datablock(hp)^.size);
  509. objectalloc^.sectionalloc(pai_datablock(hp)^.size);
  510. end;
  511. end;
  512. ait_const_32bit :
  513. objectalloc^.sectionalloc(4);
  514. ait_const_16bit :
  515. objectalloc^.sectionalloc(2);
  516. ait_const_8bit :
  517. objectalloc^.sectionalloc(1);
  518. ait_real_80bit :
  519. objectalloc^.sectionalloc(10);
  520. ait_real_64bit :
  521. objectalloc^.sectionalloc(8);
  522. ait_real_32bit :
  523. objectalloc^.sectionalloc(4);
  524. ait_comp_64bit :
  525. objectalloc^.sectionalloc(8);
  526. ait_const_rva,
  527. ait_const_symbol :
  528. objectalloc^.sectionalloc(4);
  529. ait_section:
  530. begin
  531. objectalloc^.setsection(pai_section(hp)^.sec);
  532. {$ifdef GDB}
  533. case pai_section(hp)^.sec of
  534. sec_code : n_line:=n_textline;
  535. sec_data : n_line:=n_dataline;
  536. sec_bss : n_line:=n_bssline;
  537. else
  538. n_line:=n_dataline;
  539. end;
  540. stabslastfileinfo.line:=-1;
  541. {$endif GDB}
  542. end;
  543. {$ifdef GDB}
  544. ait_stabn :
  545. convertstabs(pai_stabn(hp)^.str);
  546. ait_stabs :
  547. convertstabs(pai_stabs(hp)^.str);
  548. ait_stab_function_name :
  549. if assigned(pai_stab_function_name(hp)^.str) then
  550. funcname:=getasmsymbol(strpas(pai_stab_function_name(hp)^.str))
  551. else
  552. funcname:=nil;
  553. ait_force_line :
  554. stabslastfileinfo.line:=0;
  555. {$endif}
  556. ait_symbol :
  557. begin
  558. if pai_symbol(hp)^.is_global then
  559. pai_symbol(hp)^.sym^.settyp(AS_GLOBAL)
  560. else
  561. pai_symbol(hp)^.sym^.settyp(AS_LOCAL);
  562. pai_symbol(hp)^.sym^.setaddress(objectalloc^.currsec,objectalloc^.sectionsize,0);
  563. end;
  564. ait_label :
  565. begin
  566. if pai_label(hp)^.is_global then
  567. pai_label(hp)^.l^.settyp(AS_GLOBAL)
  568. else
  569. pai_label(hp)^.l^.settyp(AS_LOCAL);
  570. pai_label(hp)^.l^.setaddress(objectalloc^.currsec,objectalloc^.sectionsize,0);
  571. end;
  572. ait_string :
  573. objectalloc^.sectionalloc(pai_string(hp)^.len);
  574. ait_instruction :
  575. objectalloc^.sectionalloc(paicpu(hp)^.Pass1(objectalloc^.sectionsize));
  576. ait_direct :
  577. Message(asmw_f_direct_not_supported);
  578. ait_cut :
  579. if SmartAsm then
  580. break;
  581. end;
  582. hp:=pai(hp^.next);
  583. end;
  584. TreePass1:=hp;
  585. end;
  586. function ti386binasmlist.TreePass2(hp:pai):pai;
  587. var
  588. l : longint;
  589. {$ifdef I386}
  590. co : comp;
  591. {$endif I386}
  592. begin
  593. { main loop }
  594. while assigned(hp) do
  595. begin
  596. {$ifdef GDB}
  597. { write stabs }
  598. if ((cs_debuginfo in aktmoduleswitches) or
  599. (cs_gdb_lineinfo in aktglobalswitches)) then
  600. begin
  601. if (objectoutput^.currsec<>sec_none) and
  602. not(hp^.typ in [
  603. ait_label,
  604. ait_regalloc,ait_tempalloc,
  605. ait_stabn,ait_stabs,ait_section,
  606. ait_cut,ait_marker,ait_align,ait_stab_function_name]) then
  607. WriteFileLineInfo(hp^.fileinfo);
  608. end;
  609. {$endif GDB}
  610. case hp^.typ of
  611. ait_align :
  612. objectoutput^.writebytes(pai_align(hp)^.getfillbuf^,pai_align(hp)^.fillsize);
  613. ait_section :
  614. begin
  615. objectoutput^.defaultsection(pai_section(hp)^.sec);
  616. {$ifdef GDB}
  617. case pai_section(hp)^.sec of
  618. sec_code : n_line:=n_textline;
  619. sec_data : n_line:=n_dataline;
  620. sec_bss : n_line:=n_bssline;
  621. else
  622. n_line:=n_dataline;
  623. end;
  624. stabslastfileinfo.line:=-1;
  625. {$endif GDB}
  626. end;
  627. ait_symbol :
  628. objectoutput^.writesymbol(pai_symbol(hp)^.sym);
  629. ait_datablock :
  630. begin
  631. objectoutput^.writesymbol(pai_datablock(hp)^.sym);
  632. if SmartAsm
  633. {$ifdef EXTERNALBSS}
  634. or (not pai_datablock(hp)^.is_global)
  635. {$endif}
  636. then
  637. begin
  638. l:=pai_datablock(hp)^.size;
  639. if l>2 then
  640. objectoutput^.writealign(4)
  641. else if l>1 then
  642. objectoutput^.writealign(2);
  643. objectoutput^.writealloc(pai_datablock(hp)^.size);
  644. end;
  645. end;
  646. ait_const_32bit :
  647. objectoutput^.writebytes(pai_const(hp)^.value,4);
  648. ait_const_16bit :
  649. objectoutput^.writebytes(pai_const(hp)^.value,2);
  650. ait_const_8bit :
  651. objectoutput^.writebytes(pai_const(hp)^.value,1);
  652. ait_real_80bit :
  653. objectoutput^.writebytes(pai_real_80bit(hp)^.value,10);
  654. ait_real_64bit :
  655. objectoutput^.writebytes(pai_real_64bit(hp)^.value,8);
  656. ait_real_32bit :
  657. objectoutput^.writebytes(pai_real_32bit(hp)^.value,4);
  658. ait_comp_64bit :
  659. begin
  660. {$ifdef FPC}
  661. co:=comp(pai_comp_64bit(hp)^.value);
  662. {$else}
  663. co:=pai_comp_64bit(hp)^.value;
  664. {$endif}
  665. objectoutput^.writebytes(co,8);
  666. end;
  667. ait_string :
  668. objectoutput^.writebytes(pai_string(hp)^.str^,pai_string(hp)^.len);
  669. ait_const_rva :
  670. objectoutput^.writereloc(pai_const_symbol(hp)^.offset,4,
  671. pai_const_symbol(hp)^.sym,relative_rva);
  672. ait_const_symbol :
  673. objectoutput^.writereloc(pai_const_symbol(hp)^.offset,4,
  674. pai_const_symbol(hp)^.sym,relative_false);
  675. ait_label :
  676. objectoutput^.writesymbol(pai_label(hp)^.l);
  677. ait_instruction :
  678. paicpu(hp)^.Pass2;
  679. {$ifdef GDB}
  680. ait_stabn :
  681. convertstabs(pai_stabn(hp)^.str);
  682. ait_stabs :
  683. convertstabs(pai_stabs(hp)^.str);
  684. ait_stab_function_name :
  685. if assigned(pai_stab_function_name(hp)^.str) then
  686. funcname:=getasmsymbol(strpas(pai_stab_function_name(hp)^.str))
  687. else
  688. funcname:=nil;
  689. ait_force_line :
  690. stabslastfileinfo.line:=0;
  691. {$endif}
  692. ait_cut :
  693. if SmartAsm then
  694. break;
  695. end;
  696. hp:=pai(hp^.next);
  697. end;
  698. TreePass2:=hp;
  699. end;
  700. procedure ti386binasmlist.writetree;
  701. var
  702. hp : pai;
  703. begin
  704. objectalloc^.resetsections;
  705. objectalloc^.setsection(sec_code);
  706. objectoutput^.initwriting(cut_normal);
  707. objectoutput^.defaultsection(sec_code);
  708. { reset the asmsymbol list }
  709. ResetAsmsymbolList;
  710. objectoutput^.defaultsection(sec_code);
  711. {$ifdef MULTIPASS}
  712. { Pass 0 }
  713. currpass:=0;
  714. objectalloc^.setsection(sec_code);
  715. { start with list 1 }
  716. currlistidx:=1;
  717. currlist:=list[currlistidx];
  718. hp:=pai(currlist^.first);
  719. while assigned(hp) do
  720. begin
  721. hp:=TreePass0(hp);
  722. MaybeNextList(hp);
  723. end;
  724. { leave if errors have occured }
  725. if errorcount>0 then
  726. exit;
  727. {$endif}
  728. { Pass 1 }
  729. currpass:=1;
  730. objectalloc^.resetsections;
  731. objectalloc^.setsection(sec_code);
  732. {$ifdef GDB}
  733. StartFileLineInfo;
  734. {$endif GDB}
  735. { start with list 1 }
  736. currlistidx:=1;
  737. currlist:=list[currlistidx];
  738. hp:=pai(currlist^.first);
  739. while assigned(hp) do
  740. begin
  741. hp:=TreePass1(hp);
  742. MaybeNextList(hp);
  743. end;
  744. {$ifdef GDB}
  745. EndFileLineInfo;
  746. {$endif GDB}
  747. { check for undefined labels }
  748. CheckAsmSymbolListUndefined;
  749. { set section sizes }
  750. objectoutput^.setsectionsizes(objectalloc^.secsize);
  751. { leave if errors have occured }
  752. if errorcount>0 then
  753. exit;
  754. { Pass 2 }
  755. currpass:=2;
  756. {$ifdef GDB}
  757. StartFileLineInfo;
  758. {$endif GDB}
  759. { start with list 1 }
  760. currlistidx:=1;
  761. currlist:=list[currlistidx];
  762. hp:=pai(currlist^.first);
  763. while assigned(hp) do
  764. begin
  765. hp:=TreePass2(hp);
  766. MaybeNextList(hp);
  767. end;
  768. {$ifdef GDB}
  769. EndFileLineInfo;
  770. {$endif GDB}
  771. { leave if errors have occured }
  772. if errorcount>0 then
  773. exit;
  774. { write last objectfile }
  775. objectoutput^.donewriting;
  776. end;
  777. procedure ti386binasmlist.writetreesmart;
  778. var
  779. hp : pai;
  780. startsec : tsection;
  781. begin
  782. objectalloc^.resetsections;
  783. objectalloc^.setsection(sec_code);
  784. objectoutput^.initwriting(cut_normal);
  785. objectoutput^.defaultsection(sec_code);
  786. startsec:=sec_code;
  787. { start with list 1 }
  788. currlistidx:=1;
  789. currlist:=list[currlistidx];
  790. hp:=pai(currlist^.first);
  791. while assigned(hp) do
  792. begin
  793. { reset the asmsymbol list }
  794. ResetAsmsymbolList;
  795. {$ifdef MULTIPASS}
  796. { Pass 0 }
  797. currpass:=0;
  798. objectalloc^.resetsections;
  799. objectalloc^.setsection(startsec);
  800. TreePass0(hp);
  801. {$endif}
  802. { leave if errors have occured }
  803. if errorcount>0 then
  804. exit;
  805. { Pass 1 }
  806. currpass:=1;
  807. objectalloc^.resetsections;
  808. objectalloc^.setsection(startsec);
  809. {$ifdef GDB}
  810. StartFileLineInfo;
  811. {$endif GDB}
  812. TreePass1(hp);
  813. {$ifdef GDB}
  814. EndFileLineInfo;
  815. {$endif GDB}
  816. { check for undefined labels }
  817. CheckAsmSymbolListUndefined;
  818. { set section sizes }
  819. objectoutput^.setsectionsizes(objectalloc^.secsize);
  820. { leave if errors have occured }
  821. if errorcount>0 then
  822. exit;
  823. { Pass 2 }
  824. currpass:=2;
  825. objectoutput^.defaultsection(startsec);
  826. {$ifdef GDB}
  827. StartFileLineInfo;
  828. {$endif GDB}
  829. hp:=TreePass2(hp);
  830. {$ifdef GDB}
  831. EndFileLineInfo;
  832. {$endif GDB}
  833. { leave if errors have occured }
  834. if errorcount>0 then
  835. exit;
  836. { if not end then write the current objectfile }
  837. objectoutput^.donewriting;
  838. { end of lists? }
  839. if not MaybeNextList(hp) then
  840. break;
  841. { save section for next loop }
  842. { this leads to a problem if startsec is sec_none !! PM }
  843. startsec:=objectalloc^.currsec;
  844. { we will start a new objectfile so reset everything }
  845. if (hp^.typ=ait_cut) then
  846. objectoutput^.initwriting(pai_cut(hp)^.place)
  847. else
  848. objectoutput^.initwriting(cut_normal);
  849. { avoid empty files }
  850. while assigned(hp^.next) and
  851. (pai(hp^.next)^.typ in [ait_marker,ait_comment,ait_section,ait_cut]) do
  852. begin
  853. if pai(hp^.next)^.typ=ait_section then
  854. startsec:=pai_section(hp^.next)^.sec;
  855. hp:=pai(hp^.next);
  856. end;
  857. hp:=pai(hp^.next);
  858. { there is a problem if startsec is sec_none !! PM }
  859. if startsec=sec_none then
  860. startsec:=sec_code;
  861. if not MaybeNextList(hp) then
  862. break;
  863. end;
  864. end;
  865. procedure ti386binasmlist.writebin;
  866. procedure addlist(p:paasmoutput);
  867. begin
  868. inc(lists);
  869. list[lists]:=p;
  870. end;
  871. begin
  872. if cs_debuginfo in aktmoduleswitches then
  873. addlist(debuglist);
  874. addlist(codesegment);
  875. addlist(datasegment);
  876. addlist(consts);
  877. addlist(rttilist);
  878. if assigned(resourcestringlist) then
  879. addlist(resourcestringlist);
  880. addlist(bsssegment);
  881. if assigned(importssection) then
  882. addlist(importssection);
  883. if assigned(exportssection) and not UseDeffileForExport then
  884. addlist(exportssection);
  885. if assigned(resourcesection) then
  886. addlist(resourcesection);
  887. if SmartAsm then
  888. writetreesmart
  889. else
  890. writetree;
  891. end;
  892. constructor ti386binasmlist.init(t:togtype;smart:boolean);
  893. begin
  894. case t of
  895. og_none :
  896. Message(asmw_f_no_binary_writer_selected);
  897. og_dbg :
  898. objectoutput:=new(pdbgoutput,init(smart));
  899. og_coff :
  900. objectoutput:=new(pdjgppcoffoutput,init(smart));
  901. og_pecoff :
  902. objectoutput:=new(pwin32coffoutput,init(smart));
  903. end;
  904. objectalloc:=new(pobjectalloc,init);
  905. SmartAsm:=smart;
  906. currpass:=0;
  907. end;
  908. destructor ti386binasmlist.done;
  909. begin
  910. dispose(objectoutput,done);
  911. dispose(objectalloc,done);
  912. end;
  913. end.
  914. {
  915. $Log$
  916. Revision 1.42 2000-04-06 07:04:51 pierre
  917. + generate line stabs if cs_gdb_lineinfo is aktglobalswitches
  918. Revision 1.41 2000/03/10 16:05:57 pierre
  919. * generate allways symbol for stabs
  920. Revision 1.40 2000/03/09 14:29:47 pierre
  921. * fix for the stab section size changes with smartlinking
  922. Revision 1.39 2000/03/09 10:07:18 pierre
  923. * fix a problem with smartlink and stabs
  924. Revision 1.38 2000/02/18 21:54:07 pierre
  925. * avoid LeText if no stabs info
  926. Revision 1.37 2000/02/18 12:31:07 pierre
  927. * Reset file name to empty at end of code section
  928. Revision 1.36 2000/02/09 13:22:43 peter
  929. * log truncated
  930. Revision 1.35 2000/01/20 00:21:49 pierre
  931. * avoid startsec=sec_none
  932. Revision 1.34 2000/01/12 10:38:17 peter
  933. * smartlinking fixes for binary writer
  934. * release alignreg code and moved instruction writing align to cpuasm,
  935. but it doesn't use the specified register yet
  936. Revision 1.33 2000/01/07 01:14:18 peter
  937. * updated copyright to 2000
  938. Revision 1.32 1999/12/24 15:22:52 peter
  939. * reset insentry/lastinsoffset so writing smartlink works correct for
  940. short jmps
  941. Revision 1.31 1999/12/22 01:01:46 peter
  942. - removed freelabel()
  943. * added undefined label detection in internal assembler, this prevents
  944. a lot of ld crashes and wrong .o files
  945. * .o files aren't written anymore if errors have occured
  946. * inlining of assembler labels is now correct
  947. Revision 1.30 1999/12/08 10:39:59 pierre
  948. + allow use of unit var in exports of DLL for win32
  949. by using direct export writing by default instead of use of DEFFILE
  950. that does not allow assembler labels that do not
  951. start with an underscore.
  952. Use -WD to force use of Deffile for Win32 DLL
  953. Revision 1.29 1999/12/01 22:05:13 pierre
  954. * problem with unused external symbol in stabs solved
  955. Revision 1.28 1999/11/30 10:40:42 peter
  956. + ttype, tsymlist
  957. Revision 1.27 1999/11/06 14:34:16 peter
  958. * truncated log to 20 revs
  959. Revision 1.26 1999/11/02 15:06:56 peter
  960. * import library fixes for win32
  961. * alignment works again
  962. Revision 1.25 1999/09/26 21:13:40 peter
  963. * short jmp with alignment problems fixed
  964. Revision 1.24 1999/08/25 11:59:33 jonas
  965. * changed pai386, paippc and paiapha (same for tai*) to paicpu (taicpu)
  966. Revision 1.23 1999/08/10 12:26:21 pierre
  967. * avoid double .edata section if using DLLTOOL
  968. Revision 1.22 1999/08/04 00:22:35 florian
  969. * renamed i386asm and i386base to cpuasm and cpubase
  970. Revision 1.21 1999/08/01 18:28:09 florian
  971. * modifications for the new code generator
  972. Revision 1.20 1999/07/31 12:33:11 peter
  973. * fixed smartlinking
  974. Revision 1.19 1999/07/22 09:37:30 florian
  975. + resourcestring implemented
  976. + start of longstring support
  977. }