ag386bin.pas 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060
  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) then
  277. exit;
  278. { file changed ? (must be before line info) }
  279. if (fileinfo.fileindex<>0) and
  280. (stabslastfileinfo.fileindex<>fileinfo.fileindex) then
  281. begin
  282. infile:=current_module^.sourcefiles^.get_file(fileinfo.fileindex);
  283. if includecount=0 then
  284. curr_n:=n_sourcefile
  285. else
  286. curr_n:=n_includefile;
  287. { get symbol for this includefile }
  288. hp:=newasmsymbol('Ltext'+ToStr(IncludeCount));
  289. if currpass=1 then
  290. begin
  291. hp^.settyp(AS_LOCAL);
  292. hp^.setaddress(objectalloc^.currsec,objectalloc^.sectionsize,0);
  293. end
  294. else
  295. objectoutput^.writesymbol(hp);
  296. { emit stabs }
  297. if (infile^.path^<>'') then
  298. EmitStabs('"'+lower(BsToSlash(FixPath(infile^.path^,false)))+'",'+tostr(curr_n)+
  299. ',0,0,Ltext'+ToStr(IncludeCount));
  300. EmitStabs('"'+lower(FixFileName(infile^.name^))+'",'+tostr(curr_n)+
  301. ',0,0,Ltext'+ToStr(IncludeCount));
  302. inc(includecount);
  303. end;
  304. { line changed ? }
  305. if (stabslastfileinfo.line<>fileinfo.line) and (fileinfo.line<>0) then
  306. emitlineinfostabs(n_line,fileinfo.line);
  307. stabslastfileinfo:=fileinfo;
  308. end;
  309. procedure ti386binasmlist.StartFileLineInfo;
  310. var
  311. fileinfo : tfileposinfo;
  312. begin
  313. FillChar(stabslastfileinfo,sizeof(stabslastfileinfo),0);
  314. n_line:=n_textline;
  315. funcname:=nil;
  316. linecount:=1;
  317. includecount:=0;
  318. fileinfo.fileindex:=1;
  319. fileinfo.line:=1;
  320. WriteFileLineInfo(fileinfo);
  321. end;
  322. procedure ti386binasmlist.EndFileLineInfo;
  323. var
  324. hp : pasmsymbol;
  325. store_sec : tsection;
  326. begin
  327. if not (cs_debuginfo in aktmoduleswitches) then
  328. exit;
  329. store_sec:=objectalloc^.currsec;
  330. objectalloc^.setsection(sec_code);
  331. hp:=newasmsymbol('Letext');
  332. if currpass=1 then
  333. begin
  334. hp^.settyp(AS_LOCAL);
  335. hp^.setaddress(objectalloc^.currsec,objectalloc^.sectionsize,0);
  336. end
  337. else
  338. objectoutput^.writesymbol(hp);
  339. EmitStabs('"",'+tostr(n_sourcefile)+
  340. ',0,0,Letext');
  341. objectalloc^.setsection(store_sec);
  342. end;
  343. {$endif GDB}
  344. function ti386binasmlist.MaybeNextList(var hp:pai):boolean;
  345. begin
  346. { maybe end of list }
  347. while not assigned(hp) do
  348. begin
  349. if currlistidx<lists then
  350. begin
  351. inc(currlistidx);
  352. currlist:=list[currlistidx];
  353. hp:=pai(currlist^.first);
  354. end
  355. else
  356. begin
  357. MaybeNextList:=false;
  358. exit;
  359. end;
  360. end;
  361. MaybeNextList:=true;
  362. end;
  363. function ti386binasmlist.TreePass0(hp:pai):pai;
  364. var
  365. l : longint;
  366. begin
  367. while assigned(hp) do
  368. begin
  369. case hp^.typ of
  370. ait_align :
  371. begin
  372. { always use the maximum fillsize in this pass to avoid possible
  373. short jumps to become out of range }
  374. pai_align(hp)^.fillsize:=pai_align(hp)^.aligntype;
  375. objectalloc^.sectionalloc(pai_align(hp)^.fillsize);
  376. end;
  377. ait_datablock :
  378. begin
  379. {$ifdef EXTERNALBSS}
  380. if not SmartAsm then
  381. begin
  382. if not pai_datablock(hp)^.is_global then
  383. begin
  384. l:=pai_datablock(hp)^.size;
  385. if l>2 then
  386. objectalloc^.sectionalign(4)
  387. else if l>1 then
  388. objectalloc^.sectionalign(2);
  389. objectalloc^.sectionalloc(pai_datablock(hp)^.size);
  390. end;
  391. end
  392. else
  393. begin
  394. {$endif}
  395. l:=pai_datablock(hp)^.size;
  396. if l>2 then
  397. objectalloc^.sectionalign(4)
  398. else if l>1 then
  399. objectalloc^.sectionalign(2);
  400. objectalloc^.sectionalloc(pai_datablock(hp)^.size);
  401. end;
  402. end;
  403. ait_const_32bit :
  404. objectalloc^.sectionalloc(4);
  405. ait_const_16bit :
  406. objectalloc^.sectionalloc(2);
  407. ait_const_8bit :
  408. objectalloc^.sectionalloc(1);
  409. ait_real_80bit :
  410. objectalloc^.sectionalloc(10);
  411. ait_real_64bit :
  412. objectalloc^.sectionalloc(8);
  413. ait_real_32bit :
  414. objectalloc^.sectionalloc(4);
  415. ait_comp_64bit :
  416. objectalloc^.sectionalloc(8);
  417. ait_const_rva,
  418. ait_const_symbol :
  419. objectalloc^.sectionalloc(4);
  420. ait_section:
  421. objectalloc^.setsection(pai_section(hp)^.sec);
  422. ait_symbol :
  423. pai_symbol(hp)^.sym^.setaddress(objectalloc^.currsec,objectalloc^.sectionsize,0);
  424. ait_label :
  425. pai_label(hp)^.l^.setaddress(objectalloc^.currsec,objectalloc^.sectionsize,0);
  426. ait_string :
  427. objectalloc^.sectionalloc(pai_string(hp)^.len);
  428. ait_instruction :
  429. begin
  430. { reset instructions which could change in pass 2 }
  431. paicpu(hp)^.resetpass2;
  432. objectalloc^.sectionalloc(paicpu(hp)^.Pass1(objectalloc^.sectionsize));
  433. end;
  434. ait_cut :
  435. if SmartAsm then
  436. break;
  437. end;
  438. hp:=pai(hp^.next);
  439. end;
  440. TreePass0:=hp;
  441. end;
  442. function ti386binasmlist.TreePass1(hp:pai):pai;
  443. var
  444. l : longint;
  445. begin
  446. while assigned(hp) do
  447. begin
  448. {$ifdef GDB}
  449. { write stabs }
  450. if (cs_debuginfo in aktmoduleswitches) then
  451. begin
  452. if (objectalloc^.currsec<>sec_none) and
  453. not(hp^.typ in [
  454. ait_label,
  455. ait_regalloc,ait_tempalloc,
  456. ait_stabn,ait_stabs,ait_section,
  457. ait_cut,ait_marker,ait_align,ait_stab_function_name]) then
  458. WriteFileLineInfo(hp^.fileinfo);
  459. end;
  460. {$endif GDB}
  461. case hp^.typ of
  462. ait_align :
  463. begin
  464. { here we must determine the fillsize which is used in pass2 }
  465. pai_align(hp)^.fillsize:=align(objectalloc^.sectionsize,pai_align(hp)^.aligntype)-
  466. objectalloc^.sectionsize;
  467. objectalloc^.sectionalloc(pai_align(hp)^.fillsize);
  468. end;
  469. ait_datablock :
  470. begin
  471. if objectalloc^.currsec<>sec_bss then
  472. Message(asmw_e_alloc_data_only_in_bss);
  473. {$ifdef EXTERNALBSS}
  474. if not SmartAsm then
  475. begin
  476. if pai_datablock(hp)^.is_global then
  477. begin
  478. pai_datablock(hp)^.sym^.settyp(AS_EXTERNAL);
  479. pai_datablock(hp)^.sym^.setaddress(sec_none,pai_datablock(hp)^.size,pai_datablock(hp)^.size);
  480. end
  481. else
  482. begin
  483. l:=pai_datablock(hp)^.size;
  484. if l>2 then
  485. objectalloc^.sectionalign(4)
  486. else if l>1 then
  487. objectalloc^.sectionalign(2);
  488. pai_datablock(hp)^.sym^.settyp(AS_LOCAL);
  489. pai_datablock(hp)^.sym^.setaddress(objectalloc^.currsec,objectalloc^.sectionsize,
  490. pai_datablock(hp)^.size);
  491. objectalloc^.sectionalloc(pai_datablock(hp)^.size);
  492. end;
  493. end
  494. else
  495. {$endif}
  496. begin
  497. if pai_datablock(hp)^.is_global then
  498. pai_datablock(hp)^.sym^.settyp(AS_GLOBAL)
  499. else
  500. pai_datablock(hp)^.sym^.settyp(AS_LOCAL);
  501. l:=pai_datablock(hp)^.size;
  502. if l>2 then
  503. objectalloc^.sectionalign(4)
  504. else if l>1 then
  505. objectalloc^.sectionalign(2);
  506. pai_datablock(hp)^.sym^.setaddress(objectalloc^.currsec,objectalloc^.sectionsize,pai_datablock(hp)^.size);
  507. objectalloc^.sectionalloc(pai_datablock(hp)^.size);
  508. end;
  509. end;
  510. ait_const_32bit :
  511. objectalloc^.sectionalloc(4);
  512. ait_const_16bit :
  513. objectalloc^.sectionalloc(2);
  514. ait_const_8bit :
  515. objectalloc^.sectionalloc(1);
  516. ait_real_80bit :
  517. objectalloc^.sectionalloc(10);
  518. ait_real_64bit :
  519. objectalloc^.sectionalloc(8);
  520. ait_real_32bit :
  521. objectalloc^.sectionalloc(4);
  522. ait_comp_64bit :
  523. objectalloc^.sectionalloc(8);
  524. ait_const_rva,
  525. ait_const_symbol :
  526. objectalloc^.sectionalloc(4);
  527. ait_section:
  528. begin
  529. objectalloc^.setsection(pai_section(hp)^.sec);
  530. {$ifdef GDB}
  531. case pai_section(hp)^.sec of
  532. sec_code : n_line:=n_textline;
  533. sec_data : n_line:=n_dataline;
  534. sec_bss : n_line:=n_bssline;
  535. else
  536. n_line:=n_dataline;
  537. end;
  538. stabslastfileinfo.line:=-1;
  539. {$endif GDB}
  540. end;
  541. {$ifdef GDB}
  542. ait_stabn :
  543. convertstabs(pai_stabn(hp)^.str);
  544. ait_stabs :
  545. convertstabs(pai_stabs(hp)^.str);
  546. ait_stab_function_name :
  547. if assigned(pai_stab_function_name(hp)^.str) then
  548. funcname:=getasmsymbol(strpas(pai_stab_function_name(hp)^.str))
  549. else
  550. funcname:=nil;
  551. ait_force_line :
  552. stabslastfileinfo.line:=0;
  553. {$endif}
  554. ait_symbol :
  555. begin
  556. if pai_symbol(hp)^.is_global then
  557. pai_symbol(hp)^.sym^.settyp(AS_GLOBAL)
  558. else
  559. pai_symbol(hp)^.sym^.settyp(AS_LOCAL);
  560. pai_symbol(hp)^.sym^.setaddress(objectalloc^.currsec,objectalloc^.sectionsize,0);
  561. end;
  562. ait_label :
  563. begin
  564. if pai_label(hp)^.is_global then
  565. pai_label(hp)^.l^.settyp(AS_GLOBAL)
  566. else
  567. pai_label(hp)^.l^.settyp(AS_LOCAL);
  568. pai_label(hp)^.l^.setaddress(objectalloc^.currsec,objectalloc^.sectionsize,0);
  569. end;
  570. ait_string :
  571. objectalloc^.sectionalloc(pai_string(hp)^.len);
  572. ait_instruction :
  573. objectalloc^.sectionalloc(paicpu(hp)^.Pass1(objectalloc^.sectionsize));
  574. ait_direct :
  575. Message(asmw_f_direct_not_supported);
  576. ait_cut :
  577. if SmartAsm then
  578. break;
  579. end;
  580. hp:=pai(hp^.next);
  581. end;
  582. TreePass1:=hp;
  583. end;
  584. function ti386binasmlist.TreePass2(hp:pai):pai;
  585. var
  586. l : longint;
  587. {$ifdef I386}
  588. co : comp;
  589. {$endif I386}
  590. begin
  591. { main loop }
  592. while assigned(hp) do
  593. begin
  594. {$ifdef GDB}
  595. { write stabs }
  596. if cs_debuginfo in aktmoduleswitches then
  597. begin
  598. if (objectoutput^.currsec<>sec_none) and
  599. not(hp^.typ in [
  600. ait_label,
  601. ait_regalloc,ait_tempalloc,
  602. ait_stabn,ait_stabs,ait_section,
  603. ait_cut,ait_marker,ait_align,ait_stab_function_name]) then
  604. WriteFileLineInfo(hp^.fileinfo);
  605. end;
  606. {$endif GDB}
  607. case hp^.typ of
  608. ait_align :
  609. objectoutput^.writebytes(pai_align(hp)^.getfillbuf^,pai_align(hp)^.fillsize);
  610. ait_section :
  611. begin
  612. objectoutput^.defaultsection(pai_section(hp)^.sec);
  613. {$ifdef GDB}
  614. case pai_section(hp)^.sec of
  615. sec_code : n_line:=n_textline;
  616. sec_data : n_line:=n_dataline;
  617. sec_bss : n_line:=n_bssline;
  618. else
  619. n_line:=n_dataline;
  620. end;
  621. stabslastfileinfo.line:=-1;
  622. {$endif GDB}
  623. end;
  624. ait_symbol :
  625. objectoutput^.writesymbol(pai_symbol(hp)^.sym);
  626. ait_datablock :
  627. begin
  628. objectoutput^.writesymbol(pai_datablock(hp)^.sym);
  629. if SmartAsm
  630. {$ifdef EXTERNALBSS}
  631. or (not pai_datablock(hp)^.is_global)
  632. {$endif}
  633. then
  634. begin
  635. l:=pai_datablock(hp)^.size;
  636. if l>2 then
  637. objectoutput^.writealign(4)
  638. else if l>1 then
  639. objectoutput^.writealign(2);
  640. objectoutput^.writealloc(pai_datablock(hp)^.size);
  641. end;
  642. end;
  643. ait_const_32bit :
  644. objectoutput^.writebytes(pai_const(hp)^.value,4);
  645. ait_const_16bit :
  646. objectoutput^.writebytes(pai_const(hp)^.value,2);
  647. ait_const_8bit :
  648. objectoutput^.writebytes(pai_const(hp)^.value,1);
  649. ait_real_80bit :
  650. objectoutput^.writebytes(pai_real_80bit(hp)^.value,10);
  651. ait_real_64bit :
  652. objectoutput^.writebytes(pai_real_64bit(hp)^.value,8);
  653. ait_real_32bit :
  654. objectoutput^.writebytes(pai_real_32bit(hp)^.value,4);
  655. ait_comp_64bit :
  656. begin
  657. {$ifdef FPC}
  658. co:=comp(pai_comp_64bit(hp)^.value);
  659. {$else}
  660. co:=pai_comp_64bit(hp)^.value;
  661. {$endif}
  662. objectoutput^.writebytes(co,8);
  663. end;
  664. ait_string :
  665. objectoutput^.writebytes(pai_string(hp)^.str^,pai_string(hp)^.len);
  666. ait_const_rva :
  667. objectoutput^.writereloc(pai_const_symbol(hp)^.offset,4,
  668. pai_const_symbol(hp)^.sym,relative_rva);
  669. ait_const_symbol :
  670. objectoutput^.writereloc(pai_const_symbol(hp)^.offset,4,
  671. pai_const_symbol(hp)^.sym,relative_false);
  672. ait_label :
  673. objectoutput^.writesymbol(pai_label(hp)^.l);
  674. ait_instruction :
  675. paicpu(hp)^.Pass2;
  676. {$ifdef GDB}
  677. ait_stabn :
  678. convertstabs(pai_stabn(hp)^.str);
  679. ait_stabs :
  680. convertstabs(pai_stabs(hp)^.str);
  681. ait_stab_function_name :
  682. if assigned(pai_stab_function_name(hp)^.str) then
  683. funcname:=getasmsymbol(strpas(pai_stab_function_name(hp)^.str))
  684. else
  685. funcname:=nil;
  686. ait_force_line :
  687. stabslastfileinfo.line:=0;
  688. {$endif}
  689. ait_cut :
  690. if SmartAsm then
  691. break;
  692. end;
  693. hp:=pai(hp^.next);
  694. end;
  695. TreePass2:=hp;
  696. end;
  697. procedure ti386binasmlist.writetree;
  698. var
  699. hp : pai;
  700. begin
  701. objectalloc^.resetsections;
  702. objectalloc^.setsection(sec_code);
  703. objectoutput^.initwriting(cut_normal);
  704. objectoutput^.defaultsection(sec_code);
  705. { reset the asmsymbol list }
  706. ResetAsmsymbolList;
  707. objectoutput^.defaultsection(sec_code);
  708. {$ifdef MULTIPASS}
  709. { Pass 0 }
  710. currpass:=0;
  711. objectalloc^.setsection(sec_code);
  712. { start with list 1 }
  713. currlistidx:=1;
  714. currlist:=list[currlistidx];
  715. hp:=pai(currlist^.first);
  716. while assigned(hp) do
  717. begin
  718. hp:=TreePass0(hp);
  719. MaybeNextList(hp);
  720. end;
  721. { leave if errors have occured }
  722. if errorcount>0 then
  723. exit;
  724. {$endif}
  725. { Pass 1 }
  726. currpass:=1;
  727. objectalloc^.resetsections;
  728. objectalloc^.setsection(sec_code);
  729. {$ifdef GDB}
  730. StartFileLineInfo;
  731. {$endif GDB}
  732. { start with list 1 }
  733. currlistidx:=1;
  734. currlist:=list[currlistidx];
  735. hp:=pai(currlist^.first);
  736. while assigned(hp) do
  737. begin
  738. hp:=TreePass1(hp);
  739. MaybeNextList(hp);
  740. end;
  741. {$ifdef GDB}
  742. EndFileLineInfo;
  743. {$endif GDB}
  744. { check for undefined labels }
  745. CheckAsmSymbolListUndefined;
  746. { set section sizes }
  747. objectoutput^.setsectionsizes(objectalloc^.secsize);
  748. { leave if errors have occured }
  749. if errorcount>0 then
  750. exit;
  751. { Pass 2 }
  752. currpass:=2;
  753. {$ifdef GDB}
  754. StartFileLineInfo;
  755. {$endif GDB}
  756. { start with list 1 }
  757. currlistidx:=1;
  758. currlist:=list[currlistidx];
  759. hp:=pai(currlist^.first);
  760. while assigned(hp) do
  761. begin
  762. hp:=TreePass2(hp);
  763. MaybeNextList(hp);
  764. end;
  765. {$ifdef GDB}
  766. EndFileLineInfo;
  767. {$endif GDB}
  768. { leave if errors have occured }
  769. if errorcount>0 then
  770. exit;
  771. { write last objectfile }
  772. objectoutput^.donewriting;
  773. end;
  774. procedure ti386binasmlist.writetreesmart;
  775. var
  776. hp : pai;
  777. startsec : tsection;
  778. begin
  779. objectalloc^.resetsections;
  780. objectalloc^.setsection(sec_code);
  781. objectoutput^.initwriting(cut_normal);
  782. objectoutput^.defaultsection(sec_code);
  783. startsec:=sec_code;
  784. { start with list 1 }
  785. currlistidx:=1;
  786. currlist:=list[currlistidx];
  787. hp:=pai(currlist^.first);
  788. while assigned(hp) do
  789. begin
  790. { reset the asmsymbol list }
  791. ResetAsmsymbolList;
  792. {$ifdef MULTIPASS}
  793. { Pass 0 }
  794. currpass:=0;
  795. objectalloc^.resetsections;
  796. objectalloc^.setsection(startsec);
  797. TreePass0(hp);
  798. {$endif}
  799. { leave if errors have occured }
  800. if errorcount>0 then
  801. exit;
  802. { Pass 1 }
  803. currpass:=1;
  804. objectalloc^.resetsections;
  805. objectalloc^.setsection(startsec);
  806. {$ifdef GDB}
  807. StartFileLineInfo;
  808. {$endif GDB}
  809. TreePass1(hp);
  810. {$ifdef GDB}
  811. EndFileLineInfo;
  812. {$endif GDB}
  813. { check for undefined labels }
  814. CheckAsmSymbolListUndefined;
  815. { set section sizes }
  816. objectoutput^.setsectionsizes(objectalloc^.secsize);
  817. { leave if errors have occured }
  818. if errorcount>0 then
  819. exit;
  820. { Pass 2 }
  821. currpass:=2;
  822. objectoutput^.defaultsection(startsec);
  823. {$ifdef GDB}
  824. StartFileLineInfo;
  825. {$endif GDB}
  826. hp:=TreePass2(hp);
  827. {$ifdef GDB}
  828. EndFileLineInfo;
  829. {$endif GDB}
  830. { leave if errors have occured }
  831. if errorcount>0 then
  832. exit;
  833. { if not end then write the current objectfile }
  834. objectoutput^.donewriting;
  835. { end of lists? }
  836. if not MaybeNextList(hp) then
  837. break;
  838. { save section for next loop }
  839. { this leads to a problem if startsec is sec_none !! PM }
  840. startsec:=objectalloc^.currsec;
  841. { we will start a new objectfile so reset everything }
  842. if (hp^.typ=ait_cut) then
  843. objectoutput^.initwriting(pai_cut(hp)^.place)
  844. else
  845. objectoutput^.initwriting(cut_normal);
  846. { avoid empty files }
  847. while assigned(hp^.next) and
  848. (pai(hp^.next)^.typ in [ait_marker,ait_comment,ait_section,ait_cut]) do
  849. begin
  850. if pai(hp^.next)^.typ=ait_section then
  851. startsec:=pai_section(hp^.next)^.sec;
  852. hp:=pai(hp^.next);
  853. end;
  854. hp:=pai(hp^.next);
  855. { there is a problem if startsec is sec_none !! PM }
  856. if startsec=sec_none then
  857. startsec:=sec_code;
  858. if not MaybeNextList(hp) then
  859. break;
  860. end;
  861. end;
  862. procedure ti386binasmlist.writebin;
  863. procedure addlist(p:paasmoutput);
  864. begin
  865. inc(lists);
  866. list[lists]:=p;
  867. end;
  868. begin
  869. if cs_debuginfo in aktmoduleswitches then
  870. addlist(debuglist);
  871. addlist(codesegment);
  872. addlist(datasegment);
  873. addlist(consts);
  874. addlist(rttilist);
  875. if assigned(resourcestringlist) then
  876. addlist(resourcestringlist);
  877. addlist(bsssegment);
  878. if assigned(importssection) then
  879. addlist(importssection);
  880. if assigned(exportssection) and not UseDeffileForExport then
  881. addlist(exportssection);
  882. if assigned(resourcesection) then
  883. addlist(resourcesection);
  884. if SmartAsm then
  885. writetreesmart
  886. else
  887. writetree;
  888. end;
  889. constructor ti386binasmlist.init(t:togtype;smart:boolean);
  890. begin
  891. case t of
  892. og_none :
  893. Message(asmw_f_no_binary_writer_selected);
  894. og_dbg :
  895. objectoutput:=new(pdbgoutput,init(smart));
  896. og_coff :
  897. objectoutput:=new(pdjgppcoffoutput,init(smart));
  898. og_pecoff :
  899. objectoutput:=new(pwin32coffoutput,init(smart));
  900. end;
  901. objectalloc:=new(pobjectalloc,init);
  902. SmartAsm:=smart;
  903. currpass:=0;
  904. end;
  905. destructor ti386binasmlist.done;
  906. begin
  907. dispose(objectoutput,done);
  908. dispose(objectalloc,done);
  909. end;
  910. end.
  911. {
  912. $Log$
  913. Revision 1.41 2000-03-10 16:05:57 pierre
  914. * generate allways symbol for stabs
  915. Revision 1.40 2000/03/09 14:29:47 pierre
  916. * fix for the stab section size changes with smartlinking
  917. Revision 1.39 2000/03/09 10:07:18 pierre
  918. * fix a problem with smartlink and stabs
  919. Revision 1.38 2000/02/18 21:54:07 pierre
  920. * avoid LeText if no stabs info
  921. Revision 1.37 2000/02/18 12:31:07 pierre
  922. * Reset file name to empty at end of code section
  923. Revision 1.36 2000/02/09 13:22:43 peter
  924. * log truncated
  925. Revision 1.35 2000/01/20 00:21:49 pierre
  926. * avoid startsec=sec_none
  927. Revision 1.34 2000/01/12 10:38:17 peter
  928. * smartlinking fixes for binary writer
  929. * release alignreg code and moved instruction writing align to cpuasm,
  930. but it doesn't use the specified register yet
  931. Revision 1.33 2000/01/07 01:14:18 peter
  932. * updated copyright to 2000
  933. Revision 1.32 1999/12/24 15:22:52 peter
  934. * reset insentry/lastinsoffset so writing smartlink works correct for
  935. short jmps
  936. Revision 1.31 1999/12/22 01:01:46 peter
  937. - removed freelabel()
  938. * added undefined label detection in internal assembler, this prevents
  939. a lot of ld crashes and wrong .o files
  940. * .o files aren't written anymore if errors have occured
  941. * inlining of assembler labels is now correct
  942. Revision 1.30 1999/12/08 10:39:59 pierre
  943. + allow use of unit var in exports of DLL for win32
  944. by using direct export writing by default instead of use of DEFFILE
  945. that does not allow assembler labels that do not
  946. start with an underscore.
  947. Use -WD to force use of Deffile for Win32 DLL
  948. Revision 1.29 1999/12/01 22:05:13 pierre
  949. * problem with unused external symbol in stabs solved
  950. Revision 1.28 1999/11/30 10:40:42 peter
  951. + ttype, tsymlist
  952. Revision 1.27 1999/11/06 14:34:16 peter
  953. * truncated log to 20 revs
  954. Revision 1.26 1999/11/02 15:06:56 peter
  955. * import library fixes for win32
  956. * alignment works again
  957. Revision 1.25 1999/09/26 21:13:40 peter
  958. * short jmp with alignment problems fixed
  959. Revision 1.24 1999/08/25 11:59:33 jonas
  960. * changed pai386, paippc and paiapha (same for tai*) to paicpu (taicpu)
  961. Revision 1.23 1999/08/10 12:26:21 pierre
  962. * avoid double .edata section if using DLLTOOL
  963. Revision 1.22 1999/08/04 00:22:35 florian
  964. * renamed i386asm and i386base to cpuasm and cpubase
  965. Revision 1.21 1999/08/01 18:28:09 florian
  966. * modifications for the new code generator
  967. Revision 1.20 1999/07/31 12:33:11 peter
  968. * fixed smartlinking
  969. Revision 1.19 1999/07/22 09:37:30 florian
  970. + resourcestring implemented
  971. + start of longstring support
  972. }