ag386bin.pas 33 KB

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