assemble.pas 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Peter Vreman
  4. This unit handles the assemblerfile write and assembler calls of FPC
  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. unit assemble;
  19. {$i defines.inc}
  20. interface
  21. { Use multiple passes in the internal assembler to optimize jumps }
  22. {$define MULTIPASS}
  23. uses
  24. {$ifdef Delphi}
  25. sysutils,
  26. dmisc,
  27. {$else Delphi}
  28. strings,
  29. dos,
  30. {$endif Delphi}
  31. systems,globtype,globals,aasm,ogbase;
  32. const
  33. AsmOutSize=32768;
  34. type
  35. TAssembler=class
  36. public
  37. {filenames}
  38. path : pathstr;
  39. name : namestr;
  40. asmfile, { current .s and .o file }
  41. objfile : string;
  42. SmartAsm : boolean;
  43. SmartFilesCount,
  44. SmartHeaderCount : longint;
  45. Constructor Create(smart:boolean);virtual;
  46. Destructor Destroy;override;
  47. procedure NextSmartName(place:tcutplace);
  48. procedure MakeObject;virtual;abstract;
  49. end;
  50. TExternalAssembler=class(TAssembler)
  51. private
  52. procedure CreateSmartLinkPath(const s:string);
  53. protected
  54. {outfile}
  55. AsmSize,
  56. AsmStartSize,
  57. outcnt : longint;
  58. outbuf : array[0..AsmOutSize-1] of char;
  59. outfile : file;
  60. public
  61. Function FindAssembler:string;
  62. Function CallAssembler(const command,para:string):Boolean;
  63. Function DoAssemble:boolean;virtual;
  64. Procedure RemoveAsm;
  65. Procedure AsmFlush;
  66. Procedure AsmClear;
  67. Procedure AsmWrite(const s:string);
  68. Procedure AsmWritePChar(p:pchar);
  69. Procedure AsmWriteLn(const s:string);
  70. Procedure AsmLn;
  71. procedure AsmCreate(Aplace:tcutplace);
  72. procedure AsmClose;
  73. procedure WriteTree(p:TAAsmoutput);virtual;
  74. procedure WriteAsmList;virtual;
  75. public
  76. Constructor Create(smart:boolean);override;
  77. procedure MakeObject;override;
  78. end;
  79. TInternalAssembler=class(TAssembler)
  80. public
  81. constructor create(smart:boolean);override;
  82. destructor destroy;override;
  83. procedure MakeObject;override;
  84. protected
  85. { object alloc and output }
  86. objectalloc : tobjectalloc;
  87. objectoutput : tobjectoutput;
  88. private
  89. { the aasmoutput lists that need to be processed }
  90. lists : byte;
  91. list : array[1..maxoutputlists] of TAAsmoutput;
  92. { current processing }
  93. currlistidx : byte;
  94. currlist : TAAsmoutput;
  95. currpass : byte;
  96. {$ifdef GDB}
  97. n_line : byte; { different types of source lines }
  98. linecount,
  99. includecount : longint;
  100. funcname : tasmsymbol;
  101. stabslastfileinfo : tfileposinfo;
  102. procedure convertstabs(p:pchar);
  103. procedure emitlineinfostabs(nidx,line : longint);
  104. procedure emitstabs(s:string);
  105. procedure WriteFileLineInfo(var fileinfo : tfileposinfo);
  106. procedure StartFileLineInfo;
  107. procedure EndFileLineInfo;
  108. {$endif}
  109. function MaybeNextList(var hp:Tai):boolean;
  110. function TreePass0(hp:Tai):Tai;
  111. function TreePass1(hp:Tai):Tai;
  112. function TreePass2(hp:Tai):Tai;
  113. procedure writetree;
  114. procedure writetreesmart;
  115. end;
  116. TAssemblerClass = class of TAssembler;
  117. Procedure GenerateAsm(smart:boolean);
  118. Procedure OnlyAsm;
  119. procedure RegisterAssembler(const r:tasminfo;c:TAssemblerClass);
  120. procedure InitAssembler;
  121. procedure DoneAssembler;
  122. Implementation
  123. uses
  124. {$ifdef unix}
  125. {$ifdef ver1_0}
  126. linux,
  127. {$else}
  128. unix,
  129. {$endif}
  130. {$endif}
  131. cutils,script,finput,fmodule,verbose,
  132. {$ifdef GDB}
  133. gdb,
  134. {$endif GDB}
  135. cpubase,cpuasm
  136. ;
  137. var
  138. CAssembler : array[tasm] of TAssemblerClass;
  139. {*****************************************************************************
  140. TAssembler
  141. *****************************************************************************}
  142. Constructor TAssembler.Create(smart:boolean);
  143. begin
  144. { load start values }
  145. asmfile:=current_module.asmfilename^;
  146. objfile:=current_module.objfilename^;
  147. name:=Lower(current_module.modulename^);
  148. path:=current_module.outputpath^;
  149. SmartAsm:=smart;
  150. SmartFilesCount:=0;
  151. SmartHeaderCount:=0;
  152. SmartLinkOFiles.Clear;
  153. end;
  154. Destructor TAssembler.Destroy;
  155. begin
  156. end;
  157. procedure TAssembler.NextSmartName(place:tcutplace);
  158. var
  159. s : string;
  160. begin
  161. inc(SmartFilesCount);
  162. if SmartFilesCount>999999 then
  163. Message(asmw_f_too_many_asm_files);
  164. case place of
  165. cut_begin :
  166. begin
  167. inc(SmartHeaderCount);
  168. s:=current_module.asmprefix^+tostr(SmartHeaderCount)+'h';
  169. end;
  170. cut_normal :
  171. s:=current_module.asmprefix^+tostr(SmartHeaderCount)+'s';
  172. cut_end :
  173. s:=current_module.asmprefix^+tostr(SmartHeaderCount)+'t';
  174. end;
  175. AsmFile:=Path+FixFileName(s+tostr(SmartFilesCount)+target_info.asmext);
  176. ObjFile:=Path+FixFileName(s+tostr(SmartFilesCount)+target_info.objext);
  177. { insert in container so it can be cleared after the linking }
  178. SmartLinkOFiles.Insert(Objfile);
  179. end;
  180. {*****************************************************************************
  181. TExternalAssembler
  182. *****************************************************************************}
  183. Function DoPipe:boolean;
  184. begin
  185. DoPipe:=(cs_asm_pipe in aktglobalswitches) and
  186. not(cs_asm_leave in aktglobalswitches)
  187. {$ifdef i386}
  188. and (aktoutputformat=as_i386_as)
  189. {$endif i386}
  190. {$ifdef m68k}
  191. and (aktoutputformat=as_m68k_as);
  192. {$endif m68k}
  193. end;
  194. Constructor TExternalAssembler.Create(smart:boolean);
  195. begin
  196. inherited Create(smart);
  197. if SmartAsm then
  198. begin
  199. path:=FixPath(current_module.outputpath^+FixFileName(current_module.modulename^)+target_info.smartext,false);
  200. CreateSmartLinkPath(path);
  201. end;
  202. Outcnt:=0;
  203. end;
  204. procedure TExternalAssembler.CreateSmartLinkPath(const s:string);
  205. var
  206. dir : searchrec;
  207. hs : string;
  208. begin
  209. if PathExists(s) then
  210. begin
  211. { the path exists, now we clean only all the .o and .s files }
  212. { .o files }
  213. findfirst(s+dirsep+'*'+target_info.objext,anyfile,dir);
  214. while (doserror=0) do
  215. begin
  216. RemoveFile(s+dirsep+dir.name);
  217. findnext(dir);
  218. end;
  219. findclose(dir);
  220. { .s files }
  221. findfirst(s+dirsep+'*'+target_info.asmext,anyfile,dir);
  222. while (doserror=0) do
  223. begin
  224. RemoveFile(s+dirsep+dir.name);
  225. findnext(dir);
  226. end;
  227. findclose(dir);
  228. end
  229. else
  230. begin
  231. hs:=s;
  232. if hs[length(hs)] in ['/','\'] then
  233. delete(hs,length(hs),1);
  234. {$I-}
  235. mkdir(hs);
  236. {$I+}
  237. if ioresult<>0 then;
  238. end;
  239. end;
  240. const
  241. lastas : byte=255;
  242. var
  243. LastASBin : pathstr;
  244. Function TExternalAssembler.FindAssembler:string;
  245. var
  246. asfound : boolean;
  247. UtilExe : string;
  248. begin
  249. asfound:=false;
  250. UtilExe:=AddExtension(target_asm.asmbin,source_info.exeext);
  251. if lastas<>ord(target_asm.id) then
  252. begin
  253. lastas:=ord(target_asm.id);
  254. { is an assembler passed ? }
  255. if utilsdirectory<>'' then
  256. asfound:=FindFile(UtilExe,utilsdirectory,LastASBin);
  257. if not AsFound then
  258. asfound:=FindExe(UtilExe,LastASBin);
  259. if (not asfound) and not(cs_asm_extern in aktglobalswitches) then
  260. begin
  261. Message1(exec_w_assembler_not_found,LastASBin);
  262. aktglobalswitches:=aktglobalswitches+[cs_asm_extern];
  263. end;
  264. if asfound then
  265. Message1(exec_t_using_assembler,LastASBin);
  266. end;
  267. FindAssembler:=LastASBin;
  268. end;
  269. Function TExternalAssembler.CallAssembler(const command,para:string):Boolean;
  270. begin
  271. callassembler:=true;
  272. if not(cs_asm_extern in aktglobalswitches) then
  273. begin
  274. swapvectors;
  275. exec(command,para);
  276. swapvectors;
  277. if (doserror<>0) then
  278. begin
  279. Message1(exec_w_cant_call_assembler,tostr(doserror));
  280. aktglobalswitches:=aktglobalswitches+[cs_asm_extern];
  281. callassembler:=false;
  282. end
  283. else
  284. if (dosexitcode<>0) then
  285. begin
  286. Message1(exec_w_error_while_assembling,tostr(dosexitcode));
  287. callassembler:=false;
  288. end;
  289. end
  290. else
  291. AsmRes.AddAsmCommand(command,para,name);
  292. end;
  293. procedure TExternalAssembler.RemoveAsm;
  294. var
  295. g : file;
  296. begin
  297. if cs_asm_leave in aktglobalswitches then
  298. exit;
  299. if cs_asm_extern in aktglobalswitches then
  300. AsmRes.AddDeleteCommand(AsmFile)
  301. else
  302. begin
  303. assign(g,AsmFile);
  304. {$I-}
  305. erase(g);
  306. {$I+}
  307. if ioresult<>0 then;
  308. end;
  309. end;
  310. Function TExternalAssembler.DoAssemble:boolean;
  311. var
  312. s : string;
  313. begin
  314. DoAssemble:=true;
  315. if DoPipe then
  316. exit;
  317. if not(cs_asm_extern in aktglobalswitches) then
  318. begin
  319. if SmartAsm then
  320. begin
  321. if (SmartFilesCount<=1) then
  322. Message1(exec_i_assembling_smart,name);
  323. end
  324. else
  325. Message1(exec_i_assembling,name);
  326. end;
  327. s:=target_asm.asmcmd;
  328. Replace(s,'$ASM',AsmFile);
  329. Replace(s,'$OBJ',ObjFile);
  330. if CallAssembler(FindAssembler,s) then
  331. RemoveAsm
  332. else
  333. begin
  334. DoAssemble:=false;
  335. GenerateError;
  336. end;
  337. end;
  338. Procedure TExternalAssembler.AsmFlush;
  339. begin
  340. if outcnt>0 then
  341. begin
  342. BlockWrite(outfile,outbuf,outcnt);
  343. outcnt:=0;
  344. end;
  345. end;
  346. Procedure TExternalAssembler.AsmClear;
  347. begin
  348. outcnt:=0;
  349. end;
  350. Procedure TExternalAssembler.AsmWrite(const s:string);
  351. begin
  352. if OutCnt+length(s)>=AsmOutSize then
  353. AsmFlush;
  354. Move(s[1],OutBuf[OutCnt],length(s));
  355. inc(OutCnt,length(s));
  356. inc(AsmSize,length(s));
  357. end;
  358. Procedure TExternalAssembler.AsmWriteLn(const s:string);
  359. begin
  360. AsmWrite(s);
  361. AsmLn;
  362. end;
  363. Procedure TExternalAssembler.AsmWritePChar(p:pchar);
  364. var
  365. i,j : longint;
  366. begin
  367. i:=StrLen(p);
  368. j:=i;
  369. while j>0 do
  370. begin
  371. i:=min(j,AsmOutSize);
  372. if OutCnt+i>=AsmOutSize then
  373. AsmFlush;
  374. Move(p[0],OutBuf[OutCnt],i);
  375. inc(OutCnt,i);
  376. inc(AsmSize,i);
  377. dec(j,i);
  378. p:=pchar(@p[i]);
  379. end;
  380. end;
  381. Procedure TExternalAssembler.AsmLn;
  382. begin
  383. if OutCnt>=AsmOutSize-2 then
  384. AsmFlush;
  385. OutBuf[OutCnt]:=target_info.newline[1];
  386. inc(OutCnt);
  387. inc(AsmSize);
  388. if length(target_info.newline)>1 then
  389. begin
  390. OutBuf[OutCnt]:=target_info.newline[2];
  391. inc(OutCnt);
  392. inc(AsmSize);
  393. end;
  394. end;
  395. procedure TExternalAssembler.AsmCreate(Aplace:tcutplace);
  396. begin
  397. if SmartAsm then
  398. NextSmartName(Aplace);
  399. {$ifdef unix}
  400. if DoPipe then
  401. begin
  402. Message1(exec_i_assembling_pipe,asmfile);
  403. POpen(outfile,'as -o '+objfile,'W');
  404. end
  405. else
  406. {$endif}
  407. begin
  408. Assign(outfile,asmfile);
  409. {$I-}
  410. Rewrite(outfile,1);
  411. {$I+}
  412. if ioresult<>0 then
  413. Message1(exec_d_cant_create_asmfile,asmfile);
  414. end;
  415. outcnt:=0;
  416. AsmSize:=0;
  417. AsmStartSize:=0;
  418. end;
  419. procedure TExternalAssembler.AsmClose;
  420. var
  421. f : file;
  422. l : longint;
  423. begin
  424. AsmFlush;
  425. {$ifdef unix}
  426. if DoPipe then
  427. PClose(outfile)
  428. else
  429. {$endif}
  430. begin
  431. {Touch Assembler time to ppu time is there is a ppufilename}
  432. if Assigned(current_module.ppufilename) then
  433. begin
  434. Assign(f,current_module.ppufilename^);
  435. {$I-}
  436. reset(f,1);
  437. {$I+}
  438. if ioresult=0 then
  439. begin
  440. getftime(f,l);
  441. close(f);
  442. reset(outfile,1);
  443. setftime(outfile,l);
  444. end;
  445. end;
  446. close(outfile);
  447. end;
  448. end;
  449. procedure TExternalAssembler.WriteTree(p:TAAsmoutput);
  450. begin
  451. end;
  452. procedure TExternalAssembler.WriteAsmList;
  453. begin
  454. end;
  455. procedure TExternalAssembler.MakeObject;
  456. begin
  457. AsmCreate(cut_normal);
  458. WriteAsmList;
  459. AsmClose;
  460. DoAssemble;
  461. end;
  462. {*****************************************************************************
  463. TInternalAssembler
  464. *****************************************************************************}
  465. constructor TInternalAssembler.create(smart:boolean);
  466. begin
  467. inherited create(smart);
  468. objectoutput:=nil;
  469. objectalloc:=tobjectalloc.create;
  470. SmartAsm:=smart;
  471. currpass:=0;
  472. end;
  473. destructor TInternalAssembler.destroy;
  474. {$ifdef MEMDEBUG}
  475. var
  476. d : tmemdebug;
  477. {$endif}
  478. begin
  479. {$ifdef MEMDEBUG}
  480. d.init('agbin');
  481. {$endif}
  482. objectoutput.free;
  483. objectalloc.free;
  484. {$ifdef MEMDEBUG}
  485. d.free;
  486. {$endif}
  487. end;
  488. {$ifdef GDB}
  489. procedure TInternalAssembler.convertstabs(p:pchar);
  490. var
  491. ofs,
  492. nidx,nother,ii,i,line,j : longint;
  493. code : integer;
  494. hp : pchar;
  495. reloc : boolean;
  496. sec : tsection;
  497. ps : tasmsymbol;
  498. s : string;
  499. begin
  500. ofs:=0;
  501. reloc:=true;
  502. ps:=nil;
  503. sec:=sec_none;
  504. if p[0]='"' then
  505. begin
  506. i:=1;
  507. { we can have \" inside the string !! PM }
  508. while not ((p[i]='"') and (p[i-1]<>'\')) do
  509. inc(i);
  510. p[i]:=#0;
  511. ii:=i;
  512. hp:=@p[1];
  513. s:=StrPas(@P[i+2]);
  514. end
  515. else
  516. begin
  517. hp:=nil;
  518. s:=StrPas(P);
  519. i:=-2; {needed below (PM) }
  520. end;
  521. { When in pass 1 then only alloc and leave }
  522. if currpass=1 then
  523. begin
  524. objectalloc.staballoc(hp);
  525. if assigned(hp) then
  526. p[i]:='"';
  527. exit;
  528. end;
  529. { Parse the rest of the stabs }
  530. if s='' then
  531. internalerror(33000);
  532. j:=pos(',',s);
  533. if j=0 then
  534. internalerror(33001);
  535. Val(Copy(s,1,j-1),nidx,code);
  536. if code<>0 then
  537. internalerror(33002);
  538. i:=i+2+j;
  539. Delete(s,1,j);
  540. j:=pos(',',s);
  541. if (j=0) then
  542. internalerror(33003);
  543. Val(Copy(s,1,j-1),nother,code);
  544. if code<>0 then
  545. internalerror(33004);
  546. i:=i+j;
  547. Delete(s,1,j);
  548. j:=pos(',',s);
  549. if j=0 then
  550. begin
  551. j:=256;
  552. ofs:=-1;
  553. end;
  554. Val(Copy(s,1,j-1),line,code);
  555. if code<>0 then
  556. internalerror(33005);
  557. if ofs=0 then
  558. begin
  559. Delete(s,1,j);
  560. i:=i+j;
  561. Val(s,ofs,code);
  562. if code=0 then
  563. reloc:=false
  564. else
  565. begin
  566. ofs:=0;
  567. s:=strpas(@p[i]);
  568. { handle asmsymbol or
  569. asmsymbol - asmsymbol }
  570. j:=pos(' ',s);
  571. if j=0 then
  572. j:=pos('-',s);
  573. { single asmsymbol }
  574. if j=0 then
  575. j:=256;
  576. { the symbol can be external
  577. so we must use newasmsymbol and
  578. not getasmsymbol !! PM }
  579. ps:=newasmsymbol(copy(s,1,j-1));
  580. if not assigned(ps) then
  581. internalerror(33006)
  582. else
  583. begin
  584. sec:=ps.section;
  585. ofs:=ps.address;
  586. reloc:=true;
  587. UsedAsmSymbolListInsert(ps);
  588. end;
  589. if j<256 then
  590. begin
  591. i:=i+j;
  592. s:=strpas(@p[i]);
  593. if (s<>'') and (s[1]=' ') then
  594. begin
  595. j:=0;
  596. while (s[j+1]=' ') do
  597. inc(j);
  598. i:=i+j;
  599. s:=strpas(@p[i]);
  600. end;
  601. ps:=getasmsymbol(s);
  602. if not assigned(ps) then
  603. internalerror(33007)
  604. else
  605. begin
  606. if ps.section<>sec then
  607. internalerror(33008);
  608. ofs:=ofs-ps.address;
  609. reloc:=false;
  610. UsedAsmSymbolListInsert(ps);
  611. end;
  612. end;
  613. end;
  614. end;
  615. { external bss need speical handling (PM) }
  616. if assigned(ps) and (ps.section=sec_none) then
  617. begin
  618. if currpass=2 then
  619. begin
  620. objectdata.writesymbol(ps);
  621. objectoutput.exportsymbol(ps);
  622. end;
  623. objectdata.WriteSymStabs(sec,ofs,hp,ps,nidx,nother,line,reloc)
  624. end
  625. else
  626. objectdata.WriteStabs(sec,ofs,hp,nidx,nother,line,reloc);
  627. if assigned(hp) then
  628. p[ii]:='"';
  629. end;
  630. procedure TInternalAssembler.emitlineinfostabs(nidx,line : longint);
  631. var
  632. sec : tsection;
  633. begin
  634. if currpass=1 then
  635. begin
  636. objectalloc.staballoc(nil);
  637. exit;
  638. end;
  639. if (nidx=n_textline) and assigned(funcname) and
  640. (target_info.use_function_relative_addresses) then
  641. objectdata.WriteStabs(sec_code,objectdata.sectionsize(sec_code)-funcname.address,
  642. nil,nidx,0,line,false)
  643. else
  644. begin
  645. if nidx=n_textline then
  646. sec:=sec_code
  647. else if nidx=n_dataline then
  648. sec:=sec_data
  649. else
  650. sec:=sec_bss;
  651. objectdata.WriteStabs(sec,objectdata.sectionsize(sec),
  652. nil,nidx,0,line,true);
  653. end;
  654. end;
  655. procedure TInternalAssembler.emitstabs(s:string);
  656. begin
  657. s:=s+#0;
  658. ConvertStabs(@s[1]);
  659. end;
  660. procedure TInternalAssembler.WriteFileLineInfo(var fileinfo : tfileposinfo);
  661. var
  662. curr_n : byte;
  663. hp : tasmsymbol;
  664. infile : tinputfile;
  665. begin
  666. if not ((cs_debuginfo in aktmoduleswitches) or
  667. (cs_gdb_lineinfo in aktglobalswitches)) then
  668. exit;
  669. { file changed ? (must be before line info) }
  670. if (fileinfo.fileindex<>0) and
  671. (stabslastfileinfo.fileindex<>fileinfo.fileindex) then
  672. begin
  673. infile:=current_module.sourcefiles.get_file(fileinfo.fileindex);
  674. if includecount=0 then
  675. curr_n:=n_sourcefile
  676. else
  677. curr_n:=n_includefile;
  678. { get symbol for this includefile }
  679. hp:=newasmsymboltype('Ltext'+ToStr(IncludeCount),AB_LOCAL,AT_FUNCTION);
  680. if currpass=1 then
  681. begin
  682. hp.setaddress(objectalloc.currsec,objectalloc.sectionsize,0);
  683. UsedAsmSymbolListInsert(hp);
  684. end
  685. else
  686. objectdata.writesymbol(hp);
  687. { emit stabs }
  688. if (infile.path^<>'') then
  689. EmitStabs('"'+lower(BsToSlash(FixPath(infile.path^,false)))+'",'+tostr(curr_n)+
  690. ',0,0,Ltext'+ToStr(IncludeCount));
  691. EmitStabs('"'+lower(FixFileName(infile.name^))+'",'+tostr(curr_n)+
  692. ',0,0,Ltext'+ToStr(IncludeCount));
  693. inc(includecount);
  694. end;
  695. { line changed ? }
  696. if (stabslastfileinfo.line<>fileinfo.line) and (fileinfo.line<>0) then
  697. emitlineinfostabs(n_line,fileinfo.line);
  698. stabslastfileinfo:=fileinfo;
  699. end;
  700. procedure TInternalAssembler.StartFileLineInfo;
  701. var
  702. fileinfo : tfileposinfo;
  703. begin
  704. FillChar(stabslastfileinfo,sizeof(stabslastfileinfo),0);
  705. n_line:=n_textline;
  706. funcname:=nil;
  707. linecount:=1;
  708. includecount:=0;
  709. fileinfo.fileindex:=1;
  710. fileinfo.line:=1;
  711. WriteFileLineInfo(fileinfo);
  712. end;
  713. procedure TInternalAssembler.EndFileLineInfo;
  714. var
  715. hp : tasmsymbol;
  716. store_sec : tsection;
  717. begin
  718. if not ((cs_debuginfo in aktmoduleswitches) or
  719. (cs_gdb_lineinfo in aktglobalswitches)) then
  720. exit;
  721. store_sec:=objectalloc.currsec;
  722. objectalloc.setsection(sec_code);
  723. hp:=newasmsymboltype('Letext',AB_LOCAL,AT_FUNCTION);
  724. if currpass=1 then
  725. begin
  726. hp.setaddress(objectalloc.currsec,objectalloc.sectionsize,0);
  727. UsedAsmSymbolListInsert(hp);
  728. end
  729. else
  730. objectdata.writesymbol(hp);
  731. EmitStabs('"",'+tostr(n_sourcefile)+',0,0,Letext');
  732. objectalloc.setsection(store_sec);
  733. end;
  734. {$endif GDB}
  735. function TInternalAssembler.MaybeNextList(var hp:Tai):boolean;
  736. begin
  737. { maybe end of list }
  738. while not assigned(hp) do
  739. begin
  740. if currlistidx<lists then
  741. begin
  742. inc(currlistidx);
  743. currlist:=list[currlistidx];
  744. hp:=Tai(currList.first);
  745. end
  746. else
  747. begin
  748. MaybeNextList:=false;
  749. exit;
  750. end;
  751. end;
  752. MaybeNextList:=true;
  753. end;
  754. function TInternalAssembler.TreePass0(hp:Tai):Tai;
  755. var
  756. l : longint;
  757. begin
  758. while assigned(hp) do
  759. begin
  760. case hp.typ of
  761. ait_align :
  762. begin
  763. { always use the maximum fillsize in this pass to avoid possible
  764. short jumps to become out of range }
  765. Tai_align(hp).fillsize:=Tai_align(hp).aligntype;
  766. objectalloc.sectionalloc(Tai_align(hp).fillsize);
  767. end;
  768. ait_datablock :
  769. begin
  770. if not SmartAsm then
  771. begin
  772. if not Tai_datablock(hp).is_global then
  773. begin
  774. l:=Tai_datablock(hp).size;
  775. if l>2 then
  776. objectalloc.sectionalign(4)
  777. else if l>1 then
  778. objectalloc.sectionalign(2);
  779. objectalloc.sectionalloc(Tai_datablock(hp).size);
  780. end;
  781. end
  782. else
  783. begin
  784. l:=Tai_datablock(hp).size;
  785. if l>2 then
  786. objectalloc.sectionalign(4)
  787. else if l>1 then
  788. objectalloc.sectionalign(2);
  789. objectalloc.sectionalloc(Tai_datablock(hp).size);
  790. end;
  791. end;
  792. ait_const_32bit :
  793. objectalloc.sectionalloc(4);
  794. ait_const_16bit :
  795. objectalloc.sectionalloc(2);
  796. ait_const_8bit :
  797. objectalloc.sectionalloc(1);
  798. ait_real_80bit :
  799. objectalloc.sectionalloc(10);
  800. ait_real_64bit :
  801. objectalloc.sectionalloc(8);
  802. ait_real_32bit :
  803. objectalloc.sectionalloc(4);
  804. ait_comp_64bit :
  805. objectalloc.sectionalloc(8);
  806. ait_const_rva,
  807. ait_const_symbol :
  808. objectalloc.sectionalloc(4);
  809. ait_section:
  810. objectalloc.setsection(Tai_section(hp).sec);
  811. ait_symbol :
  812. Tai_symbol(hp).sym.setaddress(objectalloc.currsec,objectalloc.sectionsize,0);
  813. ait_label :
  814. Tai_label(hp).l.setaddress(objectalloc.currsec,objectalloc.sectionsize,0);
  815. ait_string :
  816. objectalloc.sectionalloc(Tai_string(hp).len);
  817. ait_instruction :
  818. begin
  819. { reset instructions which could change in pass 2 }
  820. Taicpu(hp).resetpass2;
  821. objectalloc.sectionalloc(Taicpu(hp).Pass1(objectalloc.sectionsize));
  822. end;
  823. ait_cut :
  824. if SmartAsm then
  825. break;
  826. end;
  827. hp:=Tai(hp.next);
  828. end;
  829. TreePass0:=hp;
  830. end;
  831. function TInternalAssembler.TreePass1(hp:Tai):Tai;
  832. var
  833. i,l : longint;
  834. begin
  835. while assigned(hp) do
  836. begin
  837. {$ifdef GDB}
  838. { write stabs }
  839. if ((cs_debuginfo in aktmoduleswitches) or
  840. (cs_gdb_lineinfo in aktglobalswitches)) then
  841. begin
  842. if (objectalloc.currsec<>sec_none) and
  843. not(hp.typ in [
  844. ait_label,
  845. ait_regalloc,ait_tempalloc,
  846. ait_stabn,ait_stabs,ait_section,
  847. ait_cut,ait_marker,ait_align,ait_stab_function_name]) then
  848. WriteFileLineInfo(hp.fileinfo);
  849. end;
  850. {$endif GDB}
  851. case hp.typ of
  852. ait_align :
  853. begin
  854. { here we must determine the fillsize which is used in pass2 }
  855. Tai_align(hp).fillsize:=align(objectalloc.sectionsize,Tai_align(hp).aligntype)-
  856. objectalloc.sectionsize;
  857. objectalloc.sectionalloc(Tai_align(hp).fillsize);
  858. end;
  859. ait_datablock :
  860. begin
  861. if objectalloc.currsec<>sec_bss then
  862. Message(asmw_e_alloc_data_only_in_bss);
  863. if not SmartAsm then
  864. begin
  865. if Tai_datablock(hp).is_global then
  866. begin
  867. Tai_datablock(hp).sym.setaddress(sec_none,Tai_datablock(hp).size,Tai_datablock(hp).size);
  868. { force to be common/external, must be after setaddress as that would
  869. set it to AS_GLOBAL }
  870. Tai_datablock(hp).sym.bind:=AB_COMMON;
  871. end
  872. else
  873. begin
  874. l:=Tai_datablock(hp).size;
  875. if l>2 then
  876. objectalloc.sectionalign(4)
  877. else if l>1 then
  878. objectalloc.sectionalign(2);
  879. Tai_datablock(hp).sym.setaddress(objectalloc.currsec,objectalloc.sectionsize,
  880. Tai_datablock(hp).size);
  881. objectalloc.sectionalloc(Tai_datablock(hp).size);
  882. end;
  883. end
  884. else
  885. begin
  886. l:=Tai_datablock(hp).size;
  887. if l>2 then
  888. objectalloc.sectionalign(4)
  889. else if l>1 then
  890. objectalloc.sectionalign(2);
  891. Tai_datablock(hp).sym.setaddress(objectalloc.currsec,objectalloc.sectionsize,Tai_datablock(hp).size);
  892. objectalloc.sectionalloc(Tai_datablock(hp).size);
  893. end;
  894. UsedAsmSymbolListInsert(Tai_datablock(hp).sym);
  895. end;
  896. ait_const_32bit :
  897. objectalloc.sectionalloc(4);
  898. ait_const_16bit :
  899. objectalloc.sectionalloc(2);
  900. ait_const_8bit :
  901. objectalloc.sectionalloc(1);
  902. ait_real_80bit :
  903. objectalloc.sectionalloc(10);
  904. ait_real_64bit :
  905. objectalloc.sectionalloc(8);
  906. ait_real_32bit :
  907. objectalloc.sectionalloc(4);
  908. ait_comp_64bit :
  909. objectalloc.sectionalloc(8);
  910. ait_const_rva,
  911. ait_const_symbol :
  912. begin
  913. objectalloc.sectionalloc(4);
  914. UsedAsmSymbolListInsert(Tai_const_symbol(hp).sym);
  915. end;
  916. ait_section:
  917. begin
  918. objectalloc.setsection(Tai_section(hp).sec);
  919. {$ifdef GDB}
  920. case Tai_section(hp).sec of
  921. sec_code : n_line:=n_textline;
  922. sec_data : n_line:=n_dataline;
  923. sec_bss : n_line:=n_bssline;
  924. else
  925. n_line:=n_dataline;
  926. end;
  927. stabslastfileinfo.line:=-1;
  928. {$endif GDB}
  929. end;
  930. {$ifdef GDB}
  931. ait_stabn :
  932. convertstabs(Tai_stabn(hp).str);
  933. ait_stabs :
  934. convertstabs(Tai_stabs(hp).str);
  935. ait_stab_function_name :
  936. begin
  937. if assigned(Tai_stab_function_name(hp).str) then
  938. begin
  939. funcname:=getasmsymbol(strpas(Tai_stab_function_name(hp).str));
  940. UsedAsmSymbolListInsert(funcname);
  941. end
  942. else
  943. funcname:=nil;
  944. end;
  945. ait_force_line :
  946. stabslastfileinfo.line:=0;
  947. {$endif}
  948. ait_symbol :
  949. begin
  950. Tai_symbol(hp).sym.setaddress(objectalloc.currsec,objectalloc.sectionsize,0);
  951. UsedAsmSymbolListInsert(Tai_symbol(hp).sym);
  952. end;
  953. ait_symbol_end :
  954. begin
  955. if target_info.target=target_i386_linux then
  956. begin
  957. Tai_symbol(hp).sym.size:=objectalloc.sectionsize-Tai_symbol(hp).sym.address;
  958. UsedAsmSymbolListInsert(Tai_symbol(hp).sym);
  959. end;
  960. end;
  961. ait_label :
  962. begin
  963. Tai_label(hp).l.setaddress(objectalloc.currsec,objectalloc.sectionsize,0);
  964. UsedAsmSymbolListInsert(Tai_label(hp).l);
  965. end;
  966. ait_string :
  967. objectalloc.sectionalloc(Tai_string(hp).len);
  968. ait_instruction :
  969. begin
  970. objectalloc.sectionalloc(Taicpu(hp).Pass1(objectalloc.sectionsize));
  971. { fixup the references }
  972. for i:=1 to Taicpu(hp).ops do
  973. begin
  974. with Taicpu(hp).oper[i-1] do
  975. begin
  976. case typ of
  977. top_ref :
  978. begin
  979. if assigned(ref^.symbol) then
  980. UsedAsmSymbolListInsert(ref^.symbol);
  981. end;
  982. top_symbol :
  983. begin
  984. if sym=nil then
  985. sym:=sym;
  986. UsedAsmSymbolListInsert(sym);
  987. end;
  988. end;
  989. end;
  990. end;
  991. end;
  992. ait_direct :
  993. Message(asmw_f_direct_not_supported);
  994. ait_cut :
  995. if SmartAsm then
  996. break;
  997. end;
  998. hp:=Tai(hp.next);
  999. end;
  1000. TreePass1:=hp;
  1001. end;
  1002. function TInternalAssembler.TreePass2(hp:Tai):Tai;
  1003. var
  1004. l : longint;
  1005. {$ifdef I386}
  1006. co : comp;
  1007. {$endif I386}
  1008. begin
  1009. { main loop }
  1010. while assigned(hp) do
  1011. begin
  1012. {$ifdef GDB}
  1013. { write stabs }
  1014. if ((cs_debuginfo in aktmoduleswitches) or
  1015. (cs_gdb_lineinfo in aktglobalswitches)) then
  1016. begin
  1017. if (objectdata.currsec<>sec_none) and
  1018. not(hp.typ in [
  1019. ait_label,
  1020. ait_regalloc,ait_tempalloc,
  1021. ait_stabn,ait_stabs,ait_section,
  1022. ait_cut,ait_marker,ait_align,ait_stab_function_name]) then
  1023. WriteFileLineInfo(hp.fileinfo);
  1024. end;
  1025. {$endif GDB}
  1026. case hp.typ of
  1027. ait_align :
  1028. begin
  1029. if objectdata.currsec=sec_bss then
  1030. objectdata.alloc(Tai_align(hp).fillsize)
  1031. else
  1032. objectdata.writebytes(Tai_align(hp).getfillbuf^,Tai_align(hp).fillsize);
  1033. end;
  1034. ait_section :
  1035. begin
  1036. objectdata.defaultsection(Tai_section(hp).sec);
  1037. {$ifdef GDB}
  1038. case Tai_section(hp).sec of
  1039. sec_code : n_line:=n_textline;
  1040. sec_data : n_line:=n_dataline;
  1041. sec_bss : n_line:=n_bssline;
  1042. else
  1043. n_line:=n_dataline;
  1044. end;
  1045. stabslastfileinfo.line:=-1;
  1046. {$endif GDB}
  1047. end;
  1048. ait_symbol :
  1049. begin
  1050. objectdata.writesymbol(Tai_symbol(hp).sym);
  1051. objectoutput.exportsymbol(Tai_symbol(hp).sym);
  1052. end;
  1053. ait_datablock :
  1054. begin
  1055. objectdata.writesymbol(Tai_datablock(hp).sym);
  1056. objectoutput.exportsymbol(Tai_datablock(hp).sym);
  1057. if SmartAsm or (not Tai_datablock(hp).is_global) then
  1058. begin
  1059. l:=Tai_datablock(hp).size;
  1060. if l>2 then
  1061. objectdata.allocalign(4)
  1062. else if l>1 then
  1063. objectdata.allocalign(2);
  1064. objectdata.alloc(Tai_datablock(hp).size);
  1065. end;
  1066. end;
  1067. ait_const_32bit :
  1068. objectdata.writebytes(Tai_const(hp).value,4);
  1069. ait_const_16bit :
  1070. objectdata.writebytes(Tai_const(hp).value,2);
  1071. ait_const_8bit :
  1072. objectdata.writebytes(Tai_const(hp).value,1);
  1073. ait_real_80bit :
  1074. objectdata.writebytes(Tai_real_80bit(hp).value,10);
  1075. ait_real_64bit :
  1076. objectdata.writebytes(Tai_real_64bit(hp).value,8);
  1077. ait_real_32bit :
  1078. objectdata.writebytes(Tai_real_32bit(hp).value,4);
  1079. ait_comp_64bit :
  1080. begin
  1081. {$ifdef FPC}
  1082. co:=comp(Tai_comp_64bit(hp).value);
  1083. {$else}
  1084. co:=Tai_comp_64bit(hp).value;
  1085. {$endif}
  1086. objectdata.writebytes(co,8);
  1087. end;
  1088. ait_string :
  1089. objectdata.writebytes(Tai_string(hp).str^,Tai_string(hp).len);
  1090. ait_const_rva :
  1091. objectdata.writereloc(Tai_const_symbol(hp).offset,4,
  1092. Tai_const_symbol(hp).sym,relative_rva);
  1093. ait_const_symbol :
  1094. objectdata.writereloc(Tai_const_symbol(hp).offset,4,
  1095. Tai_const_symbol(hp).sym,relative_false);
  1096. ait_label :
  1097. begin
  1098. objectdata.writesymbol(Tai_label(hp).l);
  1099. { exporting shouldn't be necessary as labels are local,
  1100. but it's better to be on the safe side (PFV) }
  1101. objectoutput.exportsymbol(Tai_label(hp).l);
  1102. end;
  1103. ait_instruction :
  1104. Taicpu(hp).Pass2;
  1105. {$ifdef GDB}
  1106. ait_stabn :
  1107. convertstabs(Tai_stabn(hp).str);
  1108. ait_stabs :
  1109. convertstabs(Tai_stabs(hp).str);
  1110. ait_stab_function_name :
  1111. if assigned(Tai_stab_function_name(hp).str) then
  1112. funcname:=getasmsymbol(strpas(Tai_stab_function_name(hp).str))
  1113. else
  1114. funcname:=nil;
  1115. ait_force_line :
  1116. stabslastfileinfo.line:=0;
  1117. {$endif}
  1118. ait_cut :
  1119. if SmartAsm then
  1120. break;
  1121. end;
  1122. hp:=Tai(hp.next);
  1123. end;
  1124. TreePass2:=hp;
  1125. end;
  1126. procedure TInternalAssembler.writetree;
  1127. var
  1128. hp : Tai;
  1129. label
  1130. doexit;
  1131. begin
  1132. objectalloc.resetsections;
  1133. objectalloc.setsection(sec_code);
  1134. objectoutput.initwriting(ObjFile);
  1135. objectdata:=objectoutput.data;
  1136. objectdata.defaultsection(sec_code);
  1137. { reset the asmsymbol list }
  1138. CreateUsedAsmsymbolList;
  1139. {$ifdef MULTIPASS}
  1140. { Pass 0 }
  1141. currpass:=0;
  1142. objectalloc.setsection(sec_code);
  1143. { start with list 1 }
  1144. currlistidx:=1;
  1145. currlist:=list[currlistidx];
  1146. hp:=Tai(currList.first);
  1147. while assigned(hp) do
  1148. begin
  1149. hp:=TreePass0(hp);
  1150. MaybeNextList(hp);
  1151. end;
  1152. { leave if errors have occured }
  1153. if errorcount>0 then
  1154. goto doexit;
  1155. {$endif}
  1156. { Pass 1 }
  1157. currpass:=1;
  1158. objectalloc.resetsections;
  1159. objectalloc.setsection(sec_code);
  1160. {$ifdef GDB}
  1161. StartFileLineInfo;
  1162. {$endif GDB}
  1163. { start with list 1 }
  1164. currlistidx:=1;
  1165. currlist:=list[currlistidx];
  1166. hp:=Tai(currList.first);
  1167. while assigned(hp) do
  1168. begin
  1169. hp:=TreePass1(hp);
  1170. MaybeNextList(hp);
  1171. end;
  1172. {$ifdef GDB}
  1173. EndFileLineInfo;
  1174. {$endif GDB}
  1175. { check for undefined labels and reset }
  1176. UsedAsmSymbolListCheckUndefined;
  1177. { set section sizes }
  1178. objectdata.setsectionsizes(objectalloc.secsize);
  1179. { leave if errors have occured }
  1180. if errorcount>0 then
  1181. goto doexit;
  1182. { Pass 2 }
  1183. currpass:=2;
  1184. {$ifdef GDB}
  1185. StartFileLineInfo;
  1186. {$endif GDB}
  1187. { start with list 1 }
  1188. currlistidx:=1;
  1189. currlist:=list[currlistidx];
  1190. hp:=Tai(currList.first);
  1191. while assigned(hp) do
  1192. begin
  1193. hp:=TreePass2(hp);
  1194. MaybeNextList(hp);
  1195. end;
  1196. {$ifdef GDB}
  1197. EndFileLineInfo;
  1198. {$endif GDB}
  1199. { leave if errors have occured }
  1200. if errorcount>0 then
  1201. goto doexit;
  1202. { write last objectfile }
  1203. objectoutput.donewriting;
  1204. objectdata:=nil;
  1205. doexit:
  1206. { reset the used symbols back, must be after the .o has been
  1207. written }
  1208. UsedAsmsymbolListReset;
  1209. DestroyUsedAsmsymbolList;
  1210. end;
  1211. procedure TInternalAssembler.writetreesmart;
  1212. var
  1213. hp : Tai;
  1214. startsec : tsection;
  1215. place: tcutplace;
  1216. begin
  1217. objectalloc.resetsections;
  1218. objectalloc.setsection(sec_code);
  1219. NextSmartName(cut_normal);
  1220. objectoutput.initwriting(ObjFile);
  1221. objectdata:=objectoutput.data;
  1222. objectdata.defaultsection(sec_code);
  1223. startsec:=sec_code;
  1224. { start with list 1 }
  1225. currlistidx:=1;
  1226. currlist:=list[currlistidx];
  1227. hp:=Tai(currList.first);
  1228. while assigned(hp) do
  1229. begin
  1230. { reset the asmsymbol list }
  1231. CreateUsedAsmSymbolList;
  1232. {$ifdef MULTIPASS}
  1233. { Pass 0 }
  1234. currpass:=0;
  1235. objectalloc.resetsections;
  1236. objectalloc.setsection(startsec);
  1237. TreePass0(hp);
  1238. { leave if errors have occured }
  1239. if errorcount>0 then
  1240. exit;
  1241. {$endif MULTIPASS}
  1242. { Pass 1 }
  1243. currpass:=1;
  1244. objectalloc.resetsections;
  1245. objectalloc.setsection(startsec);
  1246. {$ifdef GDB}
  1247. StartFileLineInfo;
  1248. {$endif GDB}
  1249. TreePass1(hp);
  1250. {$ifdef GDB}
  1251. EndFileLineInfo;
  1252. {$endif GDB}
  1253. { check for undefined labels }
  1254. UsedAsmSymbolListCheckUndefined;
  1255. { set section sizes }
  1256. objectdata.setsectionsizes(objectalloc.secsize);
  1257. { leave if errors have occured }
  1258. if errorcount>0 then
  1259. exit;
  1260. { Pass 2 }
  1261. currpass:=2;
  1262. objectdata.defaultsection(startsec);
  1263. {$ifdef GDB}
  1264. StartFileLineInfo;
  1265. {$endif GDB}
  1266. hp:=TreePass2(hp);
  1267. {$ifdef GDB}
  1268. EndFileLineInfo;
  1269. {$endif GDB}
  1270. { leave if errors have occured }
  1271. if errorcount>0 then
  1272. exit;
  1273. { if not end then write the current objectfile }
  1274. objectoutput.donewriting;
  1275. objectdata:=nil;
  1276. { reset the used symbols back, must be after the .o has been
  1277. written }
  1278. UsedAsmsymbolListReset;
  1279. DestroyUsedAsmsymbolList;
  1280. { end of lists? }
  1281. if not MaybeNextList(hp) then
  1282. break;
  1283. { save section for next loop }
  1284. { this leads to a problem if startsec is sec_none !! PM }
  1285. startsec:=objectalloc.currsec;
  1286. { we will start a new objectfile so reset everything }
  1287. { The place can still change in the next while loop, so don't init }
  1288. { the writer yet (JM) }
  1289. if (hp.typ=ait_cut) then
  1290. place := Tai_cut(hp).place
  1291. else
  1292. place := cut_normal;
  1293. { avoid empty files }
  1294. while assigned(hp) and
  1295. (Tai(hp).typ in [ait_marker,ait_comment,ait_section,ait_cut]) do
  1296. begin
  1297. if Tai(hp).typ=ait_section then
  1298. startsec:=Tai_section(hp).sec
  1299. else if (Tai(hp).typ=ait_cut) then
  1300. place := Tai_cut(hp).place;
  1301. hp:=Tai(hp.next);
  1302. end;
  1303. NextSmartName(place);
  1304. objectoutput.initwriting(ObjFile);
  1305. objectdata:=objectoutput.data;
  1306. { there is a problem if startsec is sec_none !! PM }
  1307. if startsec=sec_none then
  1308. startsec:=sec_code;
  1309. if not MaybeNextList(hp) then
  1310. break;
  1311. end;
  1312. end;
  1313. procedure TInternalAssembler.MakeObject;
  1314. procedure addlist(p:TAAsmoutput);
  1315. begin
  1316. inc(lists);
  1317. list[lists]:=p;
  1318. end;
  1319. begin
  1320. if cs_debuginfo in aktmoduleswitches then
  1321. addlist(debuglist);
  1322. addlist(codesegment);
  1323. addlist(datasegment);
  1324. addlist(consts);
  1325. addlist(rttilist);
  1326. if assigned(resourcestringlist) then
  1327. addlist(resourcestringlist);
  1328. addlist(bsssegment);
  1329. if assigned(importssection) then
  1330. addlist(importssection);
  1331. if assigned(exportssection) and not UseDeffileForExport then
  1332. addlist(exportssection);
  1333. if assigned(resourcesection) then
  1334. addlist(resourcesection);
  1335. if SmartAsm then
  1336. writetreesmart
  1337. else
  1338. writetree;
  1339. end;
  1340. {*****************************************************************************
  1341. Generate Assembler Files Main Procedure
  1342. *****************************************************************************}
  1343. Procedure GenerateAsm(smart:boolean);
  1344. var
  1345. a : TAssembler;
  1346. begin
  1347. if not assigned(CAssembler[target_asm.id]) then
  1348. Message(asmw_f_assembler_output_not_supported);
  1349. a:=CAssembler[target_asm.id].Create(smart);
  1350. a.MakeObject;
  1351. a.Free;
  1352. end;
  1353. Procedure OnlyAsm;
  1354. var
  1355. a : TExternalAssembler;
  1356. begin
  1357. a:=TExternalAssembler.Create(false);
  1358. a.DoAssemble;
  1359. a.Free;
  1360. end;
  1361. {*****************************************************************************
  1362. Init/Done
  1363. *****************************************************************************}
  1364. procedure RegisterAssembler(const r:tasminfo;c:TAssemblerClass);
  1365. var
  1366. t : tasm;
  1367. begin
  1368. t:=r.id;
  1369. if assigned(asminfos[t]) then
  1370. writeln('Warning: Assembler is already registered!')
  1371. else
  1372. Getmem(asminfos[t],sizeof(tasminfo));
  1373. asminfos[t]^:=r;
  1374. CAssembler[t]:=c;
  1375. end;
  1376. procedure InitAssembler;
  1377. begin
  1378. { target_asm is already set by readarguments }
  1379. initoutputformat:=target_asm.id;
  1380. aktoutputformat:=target_asm.id;
  1381. end;
  1382. procedure DoneAssembler;
  1383. begin
  1384. end;
  1385. end.
  1386. {
  1387. $Log$
  1388. Revision 1.22 2001-07-01 20:16:15 peter
  1389. * alignmentinfo record added
  1390. * -Oa argument supports more alignment settings that can be specified
  1391. per type: PROC,LOOP,VARMIN,VARMAX,CONSTMIN,CONSTMAX,RECORDMIN
  1392. RECORDMAX,LOCALMIN,LOCALMAX. It is possible to set the mimimum
  1393. required alignment and the maximum usefull alignment. The final
  1394. alignment will be choosen per variable size dependent on these
  1395. settings
  1396. Revision 1.21 2001/06/18 20:36:23 peter
  1397. * -Ur switch (merged)
  1398. * masm fixes (merged)
  1399. * quoted filenames for go32v2 and win32
  1400. Revision 1.20 2001/06/13 18:31:57 peter
  1401. * smartlink with dll fixed (merged)
  1402. Revision 1.19 2001/04/21 15:34:49 peter
  1403. * used target_asm.id instead of target_info.assem
  1404. Revision 1.18 2001/04/18 22:01:53 peter
  1405. * registration of targets and assemblers
  1406. Revision 1.17 2001/04/13 01:22:06 peter
  1407. * symtable change to classes
  1408. * range check generation and errors fixed, make cycle DEBUG=1 works
  1409. * memory leaks fixed
  1410. Revision 1.16 2001/03/13 18:42:39 peter
  1411. * don't create temporary smartlink dir for internalassembler
  1412. Revision 1.15 2001/03/05 21:39:11 peter
  1413. * changed to class with common TAssembler also for internal assembler
  1414. Revision 1.14 2001/02/26 08:08:16 michael
  1415. * bug correction: pipes must be closed by pclose (not close);
  1416. There was too many not closed processes under Linux before patch.
  1417. Test this by making a compiler under Linux with command
  1418. OPT="-P" make
  1419. and check a list of processes in another shell with
  1420. ps -xa
  1421. Revision 1.13 2001/02/20 21:36:39 peter
  1422. * tasm/masm fixes merged
  1423. Revision 1.12 2001/02/09 23:06:17 peter
  1424. * fixed uninited var
  1425. Revision 1.11 2001/02/05 20:46:59 peter
  1426. * support linux unit for ver1_0 compilers
  1427. Revision 1.10 2001/01/21 20:32:45 marco
  1428. * Renamefest. Compiler part. Not that hard.
  1429. Revision 1.9 2001/01/12 19:19:44 peter
  1430. * fixed searching for utils
  1431. Revision 1.8 2000/12/25 00:07:25 peter
  1432. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  1433. tlinkedlist objects)
  1434. Revision 1.7 2000/11/13 15:26:12 marco
  1435. * Renamefest
  1436. Revision 1.6 2000/10/01 19:48:23 peter
  1437. * lot of compile updates for cg11
  1438. Revision 1.5 2000/09/24 15:06:11 peter
  1439. * use defines.inc
  1440. Revision 1.4 2000/08/27 16:11:49 peter
  1441. * moved some util functions from globals,cobjects to cutils
  1442. * splitted files into finput,fmodule
  1443. Revision 1.3 2000/07/13 12:08:24 michael
  1444. + patched to 1.1.0 with former 1.09patch from peter
  1445. Revision 1.2 2000/07/13 11:32:32 michael
  1446. + removed logs
  1447. }