ag386bin.pas 32 KB

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