assemble.pas 51 KB

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