assemble.pas 49 KB

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