ag386bin.pas 32 KB

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