assemble.pas 51 KB

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