ag386bin.pas 33 KB

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