assemble.pas 52 KB

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