assemble.pas 49 KB

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