ag386bin.pas 32 KB

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