assemble.pas 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495
  1. {
  2. Copyright (c) 1998-2004 by Peter Vreman
  3. This unit handles the assemblerfile write and assembler calls of FPC
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. {# @abstract(This unit handles the assembler file write and assembler calls of FPC)
  18. Handles the calls to the actual external assemblers, as well as the generation
  19. of object files for smart linking. Also contains the base class for writing
  20. the assembler statements to file.
  21. }
  22. unit assemble;
  23. {$i fpcdefs.inc}
  24. interface
  25. uses
  26. SysUtils,
  27. systems,globtype,globals,aasmbase,aasmtai,aasmdata,ogbase,finput;
  28. const
  29. { maximum of aasmoutput lists there will be }
  30. maxoutputlists = 20;
  31. { buffer size for writing the .s file }
  32. AsmOutSize=32768*4;
  33. type
  34. TAssembler=class(TAbstractAssembler)
  35. public
  36. {filenames}
  37. path : string;
  38. name : string;
  39. AsmFileName, { current .s and .o file }
  40. ObjFileName,
  41. ppufilename : string;
  42. asmprefix : string;
  43. SmartAsm : boolean;
  44. SmartFilesCount,
  45. SmartHeaderCount : longint;
  46. Constructor Create(smart:boolean);virtual;
  47. Destructor Destroy;override;
  48. procedure NextSmartName(place:tcutplace);
  49. procedure MakeObject;virtual;abstract;
  50. end;
  51. {# This is the base class which should be overriden for each each
  52. assembler writer. It is used to actually assembler a file,
  53. and write the output to the assembler file.
  54. }
  55. TExternalAssembler=class(TAssembler)
  56. private
  57. procedure CreateSmartLinkPath(const s:string);
  58. protected
  59. {outfile}
  60. AsmSize,
  61. AsmStartSize,
  62. outcnt : longint;
  63. outbuf : array[0..AsmOutSize-1] of char;
  64. outfile : file;
  65. ioerror : boolean;
  66. {input source info}
  67. lastfileinfo : tfileposinfo;
  68. infile,
  69. lastinfile : tinputfile;
  70. {last section type written}
  71. lastsectype : TAsmSectionType;
  72. public
  73. {# Returns the complete path and executable name of the assembler
  74. program.
  75. It first tries looking in the UTIL directory if specified,
  76. otherwise it searches in the free pascal binary directory, in
  77. the current working directory and then in the directories
  78. in the $PATH environment.}
  79. Function FindAssembler:string;
  80. {# Actually does the call to the assembler file. Returns false
  81. if the assembling of the file failed.}
  82. Function CallAssembler(const command:string; const para:TCmdStr):Boolean;
  83. Function DoAssemble:boolean;virtual;
  84. Procedure RemoveAsm;
  85. Procedure AsmFlush;
  86. Procedure AsmClear;
  87. {# Write a string to the assembler file }
  88. Procedure AsmWrite(const s:string);
  89. {# Write a string to the assembler file }
  90. Procedure AsmWritePChar(p:pchar);
  91. {# Write a string to the assembler file followed by a new line }
  92. Procedure AsmWriteLn(const s:string);
  93. {# Write a new line to the assembler file }
  94. Procedure AsmLn;
  95. procedure AsmCreate(Aplace:tcutplace);
  96. procedure AsmClose;
  97. {# This routine should be overriden for each assembler, it is used
  98. to actually write the abstract assembler stream to file.}
  99. procedure WriteTree(p:TAsmList);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. procedure WriteAsmList;virtual;
  104. {# Constructs the command line for calling the assembler }
  105. function MakeCmdLine: TCmdStr; virtual;
  106. public
  107. Constructor Create(smart:boolean);override;
  108. procedure MakeObject;override;
  109. end;
  110. TInternalAssembler=class(TAssembler)
  111. private
  112. FCObjOutput : TObjOutputclass;
  113. { the aasmoutput lists that need to be processed }
  114. lists : byte;
  115. list : array[1..maxoutputlists] of TAsmList;
  116. { current processing }
  117. currlistidx : byte;
  118. currlist : TAsmList;
  119. procedure WriteStab(p:pchar);
  120. function MaybeNextList(var hp:Tai):boolean;
  121. function TreePass0(hp:Tai):Tai;
  122. function TreePass1(hp:Tai):Tai;
  123. function TreePass2(hp:Tai):Tai;
  124. procedure writetree;
  125. procedure writetreesmart;
  126. protected
  127. ObjData : TObjData;
  128. ObjOutput : tObjOutput;
  129. property CObjOutput:TObjOutputclass read FCObjOutput write FCObjOutput;
  130. public
  131. constructor create(smart:boolean);override;
  132. destructor destroy;override;
  133. procedure MakeObject;override;
  134. end;
  135. TAssemblerClass = class of TAssembler;
  136. Procedure GenerateAsm(smart:boolean);
  137. Procedure OnlyAsm;
  138. procedure RegisterAssembler(const r:tasminfo;c:TAssemblerClass);
  139. Implementation
  140. uses
  141. {$ifdef hasunix}
  142. unix,
  143. {$endif}
  144. cutils,cfileutl,
  145. {$ifdef memdebug}
  146. cclasses,
  147. {$endif memdebug}
  148. script,fmodule,verbose,
  149. {$if defined(m68k) or defined(arm)}
  150. cpuinfo,
  151. {$endif m68k or arm}
  152. aasmcpu,
  153. owbase,owar
  154. ;
  155. var
  156. CAssembler : array[tasm] of TAssemblerClass;
  157. {*****************************************************************************
  158. TAssembler
  159. *****************************************************************************}
  160. Constructor TAssembler.Create(smart:boolean);
  161. begin
  162. { load start values }
  163. AsmFileName:=current_module.AsmFilename^;
  164. ObjFileName:=current_module.ObjFileName^;
  165. name:=Lower(current_module.modulename^);
  166. path:=current_module.outputpath^;
  167. asmprefix := current_module.asmprefix^;
  168. if not assigned(current_module.outputpath) then
  169. ppufilename := ''
  170. else
  171. ppufilename := current_module.ppufilename^;
  172. SmartAsm:=smart;
  173. SmartFilesCount:=0;
  174. SmartHeaderCount:=0;
  175. SmartLinkOFiles.Clear;
  176. end;
  177. Destructor TAssembler.Destroy;
  178. begin
  179. end;
  180. procedure TAssembler.NextSmartName(place:tcutplace);
  181. var
  182. s : string;
  183. begin
  184. inc(SmartFilesCount);
  185. if SmartFilesCount>999999 then
  186. Message(asmw_f_too_many_asm_files);
  187. case place of
  188. cut_begin :
  189. begin
  190. inc(SmartHeaderCount);
  191. s:=asmprefix+tostr(SmartHeaderCount)+'h';
  192. end;
  193. cut_normal :
  194. s:=asmprefix+tostr(SmartHeaderCount)+'s';
  195. cut_end :
  196. s:=asmprefix+tostr(SmartHeaderCount)+'t';
  197. end;
  198. AsmFileName:=Path+FixFileName(s+tostr(SmartFilesCount)+target_info.asmext);
  199. ObjFileName:=Path+FixFileName(s+tostr(SmartFilesCount)+target_info.objext);
  200. { insert in container so it can be cleared after the linking }
  201. SmartLinkOFiles.Insert(ObjFileName);
  202. end;
  203. {*****************************************************************************
  204. TExternalAssembler
  205. *****************************************************************************}
  206. Function DoPipe:boolean;
  207. begin
  208. DoPipe:=(cs_asm_pipe in current_settings.globalswitches) and
  209. (([cs_asm_leave,cs_link_on_target] * current_settings.globalswitches) = []) and
  210. ((target_asm.id in [as_gas,as_ggas,as_darwin]));
  211. end;
  212. Constructor TExternalAssembler.Create(smart:boolean);
  213. begin
  214. inherited Create(smart);
  215. if SmartAsm then
  216. begin
  217. path:=FixPath(ChangeFileExt(AsmFileName,target_info.smartext),false);
  218. CreateSmartLinkPath(path);
  219. end;
  220. Outcnt:=0;
  221. end;
  222. procedure TExternalAssembler.CreateSmartLinkPath(const s:string);
  223. procedure DeleteFilesWithExt(const AExt:string);
  224. var
  225. dir : TSearchRec;
  226. begin
  227. if findfirst(s+source_info.dirsep+'*'+AExt,faAnyFile,dir) = 0 then
  228. begin
  229. repeat
  230. DeleteFile(s+source_info.dirsep+dir.name);
  231. until findnext(dir) <> 0;
  232. end;
  233. findclose(dir);
  234. end;
  235. var
  236. hs : string;
  237. begin
  238. if PathExists(s,false) then
  239. begin
  240. { the path exists, now we clean only all the .o and .s files }
  241. DeleteFilesWithExt(target_info.objext);
  242. DeleteFilesWithExt(target_info.asmext);
  243. end
  244. else
  245. begin
  246. hs:=s;
  247. if hs[length(hs)] in ['/','\'] then
  248. delete(hs,length(hs),1);
  249. {$I-}
  250. mkdir(hs);
  251. {$I+}
  252. if ioresult<>0 then;
  253. end;
  254. end;
  255. const
  256. lastas : byte=255;
  257. var
  258. LastASBin : TCmdStr;
  259. Function TExternalAssembler.FindAssembler:string;
  260. var
  261. asfound : boolean;
  262. UtilExe : string;
  263. begin
  264. asfound:=false;
  265. if cs_link_on_target in current_settings.globalswitches then
  266. begin
  267. { If linking on target, don't add any path PM }
  268. FindAssembler:=utilsprefix+ChangeFileExt(target_asm.asmbin,target_info.exeext);
  269. exit;
  270. end
  271. else
  272. UtilExe:=utilsprefix+ChangeFileExt(target_asm.asmbin,source_info.exeext);
  273. if lastas<>ord(target_asm.id) then
  274. begin
  275. lastas:=ord(target_asm.id);
  276. { is an assembler passed ? }
  277. if utilsdirectory<>'' then
  278. asfound:=FindFile(UtilExe,utilsdirectory,false,LastASBin);
  279. if not AsFound then
  280. asfound:=FindExe(UtilExe,false,LastASBin);
  281. if (not asfound) and not(cs_asm_extern in current_settings.globalswitches) then
  282. begin
  283. Message1(exec_e_assembler_not_found,LastASBin);
  284. current_settings.globalswitches:=current_settings.globalswitches+[cs_asm_extern];
  285. end;
  286. if asfound then
  287. Message1(exec_t_using_assembler,LastASBin);
  288. end;
  289. FindAssembler:=LastASBin;
  290. end;
  291. Function TExternalAssembler.CallAssembler(const command:string; const para:TCmdStr):Boolean;
  292. var
  293. DosExitCode : Integer;
  294. begin
  295. result:=true;
  296. if (cs_asm_extern in current_settings.globalswitches) then
  297. begin
  298. AsmRes.AddAsmCommand(command,para,name);
  299. exit;
  300. end;
  301. try
  302. FlushOutput;
  303. DosExitCode := ExecuteProcess(command,para);
  304. if DosExitCode <>0
  305. then begin
  306. Message1(exec_e_error_while_assembling,tostr(dosexitcode));
  307. result:=false;
  308. end;
  309. except on E:EOSError do
  310. begin
  311. Message1(exec_e_cant_call_assembler,tostr(E.ErrorCode));
  312. current_settings.globalswitches:=current_settings.globalswitches+[cs_asm_extern];
  313. result:=false;
  314. end;
  315. end;
  316. end;
  317. procedure TExternalAssembler.RemoveAsm;
  318. var
  319. g : file;
  320. begin
  321. if cs_asm_leave in current_settings.globalswitches then
  322. exit;
  323. if cs_asm_extern in current_settings.globalswitches then
  324. AsmRes.AddDeleteCommand(AsmFileName)
  325. else
  326. begin
  327. assign(g,AsmFileName);
  328. {$I-}
  329. erase(g);
  330. {$I+}
  331. if ioresult<>0 then;
  332. end;
  333. end;
  334. Function TExternalAssembler.DoAssemble:boolean;
  335. begin
  336. DoAssemble:=true;
  337. if DoPipe then
  338. exit;
  339. if not(cs_asm_extern in current_settings.globalswitches) then
  340. begin
  341. if SmartAsm then
  342. begin
  343. if (SmartFilesCount<=1) then
  344. Message1(exec_i_assembling_smart,name);
  345. end
  346. else
  347. Message1(exec_i_assembling,name);
  348. end;
  349. if CallAssembler(FindAssembler,MakeCmdLine) then
  350. RemoveAsm
  351. else
  352. begin
  353. DoAssemble:=false;
  354. GenerateError;
  355. end;
  356. end;
  357. Procedure TExternalAssembler.AsmFlush;
  358. begin
  359. if outcnt>0 then
  360. begin
  361. { suppress i/o error }
  362. {$i-}
  363. BlockWrite(outfile,outbuf,outcnt);
  364. {$i+}
  365. ioerror:=ioerror or (ioresult<>0);
  366. outcnt:=0;
  367. end;
  368. end;
  369. Procedure TExternalAssembler.AsmClear;
  370. begin
  371. outcnt:=0;
  372. end;
  373. Procedure TExternalAssembler.AsmWrite(const s:string);
  374. begin
  375. if OutCnt+length(s)>=AsmOutSize then
  376. AsmFlush;
  377. Move(s[1],OutBuf[OutCnt],length(s));
  378. inc(OutCnt,length(s));
  379. inc(AsmSize,length(s));
  380. end;
  381. Procedure TExternalAssembler.AsmWriteLn(const s:string);
  382. begin
  383. AsmWrite(s);
  384. AsmLn;
  385. end;
  386. Procedure TExternalAssembler.AsmWritePChar(p:pchar);
  387. var
  388. i,j : longint;
  389. begin
  390. i:=StrLen(p);
  391. j:=i;
  392. while j>0 do
  393. begin
  394. i:=min(j,AsmOutSize);
  395. if OutCnt+i>=AsmOutSize then
  396. AsmFlush;
  397. Move(p[0],OutBuf[OutCnt],i);
  398. inc(OutCnt,i);
  399. inc(AsmSize,i);
  400. dec(j,i);
  401. p:=pchar(@p[i]);
  402. end;
  403. end;
  404. Procedure TExternalAssembler.AsmLn;
  405. begin
  406. if OutCnt>=AsmOutSize-2 then
  407. AsmFlush;
  408. if (cs_link_on_target in current_settings.globalswitches) then
  409. begin
  410. OutBuf[OutCnt]:=target_info.newline[1];
  411. inc(OutCnt);
  412. inc(AsmSize);
  413. if length(target_info.newline)>1 then
  414. begin
  415. OutBuf[OutCnt]:=target_info.newline[2];
  416. inc(OutCnt);
  417. inc(AsmSize);
  418. end;
  419. end
  420. else
  421. begin
  422. OutBuf[OutCnt]:=source_info.newline[1];
  423. inc(OutCnt);
  424. inc(AsmSize);
  425. if length(source_info.newline)>1 then
  426. begin
  427. OutBuf[OutCnt]:=source_info.newline[2];
  428. inc(OutCnt);
  429. inc(AsmSize);
  430. end;
  431. end;
  432. end;
  433. function TExternalAssembler.MakeCmdLine: TCmdStr;
  434. begin
  435. result:=target_asm.asmcmd;
  436. {$ifdef m68k}
  437. if current_settings.cputype = cpu_MC68020 then
  438. result:='-m68020 '+result
  439. else
  440. result:='-m68000 '+result;
  441. {$endif}
  442. {$ifdef arm}
  443. if current_settings.fputype = fpu_soft then
  444. result:='-mfpu=softvfp '+result;
  445. {$endif arm}
  446. if (cs_link_on_target in current_settings.globalswitches) then
  447. begin
  448. Replace(result,'$ASM',maybequoted(ScriptFixFileName(AsmFileName)));
  449. Replace(result,'$OBJ',maybequoted(ScriptFixFileName(ObjFileName)));
  450. end
  451. else
  452. begin
  453. {$ifdef hasunix}
  454. if DoPipe then
  455. Replace(result,'$ASM','')
  456. else
  457. {$endif}
  458. Replace(result,'$ASM',maybequoted(AsmFileName));
  459. Replace(result,'$OBJ',maybequoted(ObjFileName));
  460. end;
  461. end;
  462. procedure TExternalAssembler.AsmCreate(Aplace:tcutplace);
  463. begin
  464. if SmartAsm then
  465. NextSmartName(Aplace);
  466. {$ifdef hasunix}
  467. if DoPipe then
  468. begin
  469. if SmartAsm then
  470. begin
  471. if (SmartFilesCount<=1) then
  472. Message1(exec_i_assembling_smart,name);
  473. end
  474. else
  475. Message1(exec_i_assembling_pipe,AsmFileName);
  476. POpen(outfile,FindAssembler+' '+MakeCmdLine,'W');
  477. end
  478. else
  479. {$endif}
  480. begin
  481. Assign(outfile,AsmFileName);
  482. {$I-}
  483. Rewrite(outfile,1);
  484. {$I+}
  485. if ioresult<>0 then
  486. begin
  487. ioerror:=true;
  488. Message1(exec_d_cant_create_asmfile,AsmFileName);
  489. end;
  490. end;
  491. outcnt:=0;
  492. AsmSize:=0;
  493. AsmStartSize:=0;
  494. end;
  495. procedure TExternalAssembler.AsmClose;
  496. var
  497. f : file;
  498. FileAge : longint;
  499. begin
  500. AsmFlush;
  501. {$ifdef hasunix}
  502. if DoPipe then
  503. begin
  504. if PClose(outfile) <> 0 then
  505. GenerateError;
  506. end
  507. else
  508. {$endif}
  509. begin
  510. {Touch Assembler time to ppu time is there is a ppufilename}
  511. if ppufilename<>'' then
  512. begin
  513. Assign(f,ppufilename);
  514. {$I-}
  515. reset(f,1);
  516. {$I+}
  517. if ioresult=0 then
  518. begin
  519. FileAge := FileGetDate(GetFileHandle(f));
  520. close(f);
  521. reset(outfile,1);
  522. FileSetDate(GetFileHandle(outFile),FileAge);
  523. end;
  524. end;
  525. close(outfile);
  526. end;
  527. end;
  528. procedure TExternalAssembler.WriteTree(p:TAsmList);
  529. begin
  530. end;
  531. procedure TExternalAssembler.WriteAsmList;
  532. begin
  533. end;
  534. procedure TExternalAssembler.MakeObject;
  535. begin
  536. AsmCreate(cut_normal);
  537. FillChar(lastfileinfo, sizeof(lastfileinfo), 0);
  538. lastfileinfo.line := -1;
  539. lastinfile := nil;
  540. lastsectype := sec_none;
  541. WriteAsmList;
  542. AsmClose;
  543. if not(ioerror) then
  544. DoAssemble;
  545. end;
  546. {*****************************************************************************
  547. TInternalAssembler
  548. *****************************************************************************}
  549. constructor TInternalAssembler.create(smart:boolean);
  550. begin
  551. inherited create(smart);
  552. ObjOutput:=nil;
  553. ObjData:=nil;
  554. SmartAsm:=smart;
  555. end;
  556. destructor TInternalAssembler.destroy;
  557. begin
  558. if assigned(ObjData) then
  559. ObjData.free;
  560. if assigned(ObjOutput) then
  561. ObjOutput.free;
  562. end;
  563. procedure TInternalAssembler.WriteStab(p:pchar);
  564. function consumecomma(var p:pchar):boolean;
  565. begin
  566. while (p^=' ') do
  567. inc(p);
  568. result:=(p^=',');
  569. inc(p);
  570. end;
  571. function consumenumber(var p:pchar;out value:longint):boolean;
  572. var
  573. hs : string;
  574. len,
  575. code : integer;
  576. begin
  577. value:=0;
  578. while (p^=' ') do
  579. inc(p);
  580. len:=0;
  581. while (p^ in ['0'..'9']) do
  582. begin
  583. inc(len);
  584. hs[len]:=p^;
  585. inc(p);
  586. end;
  587. if len>0 then
  588. begin
  589. hs[0]:=chr(len);
  590. val(hs,value,code);
  591. end
  592. else
  593. code:=-1;
  594. result:=(code=0);
  595. end;
  596. function consumeoffset(var p:pchar;out relocsym:tobjsymbol;out value:longint):boolean;
  597. var
  598. hs : string;
  599. len,
  600. code : integer;
  601. pstart : pchar;
  602. sym : tobjsymbol;
  603. exprvalue : longint;
  604. gotmin,
  605. have_first_symbol,
  606. have_second_symbol,
  607. dosub : boolean;
  608. begin
  609. result:=false;
  610. value:=0;
  611. relocsym:=nil;
  612. gotmin:=false;
  613. have_first_symbol:=false;
  614. have_second_symbol:=false;
  615. repeat
  616. dosub:=false;
  617. exprvalue:=0;
  618. if gotmin then
  619. begin
  620. dosub:=true;
  621. gotmin:=false;
  622. end;
  623. while (p^=' ') do
  624. inc(p);
  625. case p^ of
  626. #0 :
  627. break;
  628. ' ' :
  629. inc(p);
  630. '0'..'9' :
  631. begin
  632. len:=0;
  633. while (p^ in ['0'..'9']) do
  634. begin
  635. inc(len);
  636. hs[len]:=p^;
  637. inc(p);
  638. end;
  639. hs[0]:=chr(len);
  640. val(hs,exprvalue,code);
  641. if code<>0 then
  642. internalerror(200702251);
  643. end;
  644. '.','_',
  645. 'A'..'Z',
  646. 'a'..'z' :
  647. begin
  648. pstart:=p;
  649. while not(p^ in [#0,' ','-','+']) do
  650. inc(p);
  651. len:=p-pstart;
  652. if len>255 then
  653. internalerror(200509187);
  654. move(pstart^,hs[1],len);
  655. hs[0]:=chr(len);
  656. sym:=objdata.symbolref(hs);
  657. have_first_symbol:=true;
  658. { Second symbol? }
  659. if assigned(relocsym) then
  660. begin
  661. if have_second_symbol then
  662. internalerror(2007032201);
  663. have_second_symbol:=true;
  664. if not have_first_symbol then
  665. internalerror(2007032202);
  666. { second symbol should substracted to first }
  667. if not dosub then
  668. internalerror(2007032203);
  669. if (relocsym.objsection<>sym.objsection) then
  670. internalerror(2005091810);
  671. exprvalue:=relocsym.address-sym.address;
  672. relocsym:=nil;
  673. dosub:=false;
  674. end
  675. else
  676. begin
  677. relocsym:=sym;
  678. if assigned(sym.objsection) then
  679. begin
  680. { first symbol should be + }
  681. if not have_first_symbol and dosub then
  682. internalerror(2007032204);
  683. have_first_symbol:=true;
  684. end;
  685. end;
  686. end;
  687. '+' :
  688. begin
  689. { nothing, by default addition is done }
  690. inc(p);
  691. end;
  692. '-' :
  693. begin
  694. gotmin:=true;
  695. inc(p);
  696. end;
  697. else
  698. internalerror(200509189);
  699. end;
  700. if dosub then
  701. dec(value,exprvalue)
  702. else
  703. inc(value,exprvalue);
  704. until false;
  705. result:=true;
  706. end;
  707. var
  708. stabstrlen,
  709. ofs,
  710. nline,
  711. nidx,
  712. nother,
  713. i : longint;
  714. stab : TObjStabEntry;
  715. relocsym : TObjSymbol;
  716. pstr,
  717. pcurr,
  718. pendquote : pchar;
  719. oldsec : TObjSection;
  720. begin
  721. pcurr:=nil;
  722. pstr:=nil;
  723. pendquote:=nil;
  724. relocsym:=nil;
  725. ofs:=0;
  726. { Parse string part }
  727. if (p[0]='"') then
  728. begin
  729. pstr:=@p[1];
  730. { Ignore \" inside the string }
  731. i:=1;
  732. while not((p[i]='"') and (p[i-1]<>'\')) and
  733. (p[i]<>#0) do
  734. inc(i);
  735. pendquote:=@p[i];
  736. pendquote^:=#0;
  737. pcurr:=@p[i+1];
  738. if not consumecomma(pcurr) then
  739. internalerror(200509181);
  740. end
  741. else
  742. pcurr:=p;
  743. { When in pass 1 then only alloc and leave }
  744. if ObjData.currpass=1 then
  745. begin
  746. ObjData.StabsSec.Alloc(sizeof(TObjStabEntry));
  747. if assigned(pstr) and (pstr[0]<>#0) then
  748. ObjData.StabStrSec.Alloc(strlen(pstr)+1);
  749. end
  750. else
  751. begin
  752. { Stabs format: nidx,nother,nline[,offset] }
  753. if not consumenumber(pcurr,nidx) then
  754. internalerror(200509182);
  755. if not consumecomma(pcurr) then
  756. internalerror(200509183);
  757. if not consumenumber(pcurr,nother) then
  758. internalerror(200509184);
  759. if not consumecomma(pcurr) then
  760. internalerror(200509185);
  761. if not consumenumber(pcurr,nline) then
  762. internalerror(200509186);
  763. if consumecomma(pcurr) then
  764. consumeoffset(pcurr,relocsym,ofs);
  765. { Generate stab entry }
  766. if assigned(pstr) and (pstr[0]<>#0) then
  767. begin
  768. stabstrlen:=strlen(pstr);
  769. {$ifdef optimizestabs}
  770. StabStrEntry:=nil;
  771. if (nidx=N_SourceFile) or (nidx=N_IncludeFile) then
  772. begin
  773. hs:=strpas(pstr);
  774. StabstrEntry:=StabStrDict.Find(hs);
  775. if not assigned(StabstrEntry) then
  776. begin
  777. StabstrEntry:=TStabStrEntry.Create(hs);
  778. StabstrEntry:=StabStrSec.Size;
  779. StabStrDict.Insert(StabstrEntry);
  780. { generate new stab }
  781. StabstrEntry:=nil;
  782. end;
  783. end;
  784. if assigned(StabstrEntry) then
  785. stab.strpos:=StabstrEntry.strpos
  786. else
  787. {$endif optimizestabs}
  788. begin
  789. stab.strpos:=ObjData.StabStrSec.Size;
  790. ObjData.StabStrSec.write(pstr^,stabstrlen+1);
  791. end;
  792. end
  793. else
  794. stab.strpos:=0;
  795. stab.ntype:=byte(nidx);
  796. stab.ndesc:=word(nline);
  797. stab.nother:=byte(nother);
  798. stab.nvalue:=ofs;
  799. { Write the stab first without the value field. Then
  800. write a the value field with relocation }
  801. oldsec:=ObjData.CurrObjSec;
  802. ObjData.SetSection(ObjData.StabsSec);
  803. ObjData.Writebytes(stab,sizeof(TObjStabEntry)-4);
  804. ObjData.Writereloc(stab.nvalue,4,relocsym,RELOC_ABSOLUTE);
  805. ObjData.setsection(oldsec);
  806. end;
  807. if assigned(pendquote) then
  808. pendquote^:='"';
  809. end;
  810. function TInternalAssembler.MaybeNextList(var hp:Tai):boolean;
  811. begin
  812. { maybe end of list }
  813. while not assigned(hp) do
  814. begin
  815. if currlistidx<lists then
  816. begin
  817. inc(currlistidx);
  818. currlist:=list[currlistidx];
  819. hp:=Tai(currList.first);
  820. end
  821. else
  822. begin
  823. MaybeNextList:=false;
  824. exit;
  825. end;
  826. end;
  827. MaybeNextList:=true;
  828. end;
  829. function TInternalAssembler.TreePass0(hp:Tai):Tai;
  830. var
  831. objsym,
  832. objsymend : TObjSymbol;
  833. begin
  834. while assigned(hp) do
  835. begin
  836. case hp.typ of
  837. ait_align :
  838. begin
  839. if tai_align_abstract(hp).aligntype>1 then
  840. begin
  841. { always use the maximum fillsize in this pass to avoid possible
  842. short jumps to become out of range }
  843. Tai_align_abstract(hp).fillsize:=Tai_align_abstract(hp).aligntype;
  844. ObjData.alloc(Tai_align_abstract(hp).fillsize);
  845. end
  846. else
  847. Tai_align_abstract(hp).fillsize:=0;
  848. end;
  849. ait_datablock :
  850. begin
  851. {$ifdef USE_COMM_IN_BSS}
  852. if writingpackages and
  853. Tai_datablock(hp).is_global then
  854. ObjData.SymbolDefine(Tai_datablock(hp).sym)
  855. else
  856. {$endif USE_COMM_IN_BSS}
  857. begin
  858. ObjData.allocalign(used_align(size_2_align(Tai_datablock(hp).size),0,ObjData.CurrObjSec.secalign));
  859. ObjData.SymbolDefine(Tai_datablock(hp).sym);
  860. ObjData.alloc(Tai_datablock(hp).size);
  861. end;
  862. end;
  863. ait_real_80bit :
  864. ObjData.alloc(10);
  865. ait_real_64bit :
  866. ObjData.alloc(8);
  867. ait_real_32bit :
  868. ObjData.alloc(4);
  869. ait_comp_64bit :
  870. ObjData.alloc(8);
  871. ait_const:
  872. begin
  873. { if symbols are provided we can calculate the value for relative symbols.
  874. This is required for length calculation of leb128 constants }
  875. if assigned(tai_const(hp).sym) then
  876. begin
  877. objsym:=Objdata.SymbolRef(tai_const(hp).sym);
  878. if assigned(tai_const(hp).endsym) then
  879. begin
  880. objsymend:=Objdata.SymbolRef(tai_const(hp).endsym);
  881. if objsymend.objsection<>objsym.objsection then
  882. internalerror(200404124);
  883. Tai_const(hp).value:=objsymend.address-objsym.address+Tai_const(hp).symofs;
  884. end;
  885. end;
  886. ObjData.alloc(tai_const(hp).size);
  887. end;
  888. ait_section:
  889. begin
  890. ObjData.CreateSection(Tai_section(hp).sectype,Tai_section(hp).name^,Tai_section(hp).secorder);
  891. Tai_section(hp).sec:=ObjData.CurrObjSec;
  892. end;
  893. ait_symbol :
  894. ObjData.SymbolDefine(Tai_symbol(hp).sym);
  895. ait_label :
  896. ObjData.SymbolDefine(Tai_label(hp).labsym);
  897. ait_string :
  898. ObjData.alloc(Tai_string(hp).len);
  899. ait_instruction :
  900. begin
  901. { reset instructions which could change in pass 2 }
  902. Taicpu(hp).resetpass2;
  903. ObjData.alloc(Taicpu(hp).Pass1(ObjData));
  904. end;
  905. ait_cutobject :
  906. if SmartAsm then
  907. break;
  908. end;
  909. hp:=Tai(hp.next);
  910. end;
  911. TreePass0:=hp;
  912. end;
  913. function TInternalAssembler.TreePass1(hp:Tai):Tai;
  914. var
  915. objsym,
  916. objsymend : TObjSymbol;
  917. begin
  918. while assigned(hp) do
  919. begin
  920. case hp.typ of
  921. ait_align :
  922. begin
  923. if tai_align_abstract(hp).aligntype>1 then
  924. begin
  925. { here we must determine the fillsize which is used in pass2 }
  926. Tai_align_abstract(hp).fillsize:=align(ObjData.CurrObjSec.Size,Tai_align_abstract(hp).aligntype)-
  927. ObjData.CurrObjSec.Size;
  928. ObjData.alloc(Tai_align_abstract(hp).fillsize);
  929. end;
  930. end;
  931. ait_datablock :
  932. begin
  933. if (oso_data in ObjData.CurrObjSec.secoptions) then
  934. Message(asmw_e_alloc_data_only_in_bss);
  935. {$ifdef USE_COMM_IN_BSS}
  936. if writingpackages and
  937. Tai_datablock(hp).is_global then
  938. begin
  939. objsym:=ObjData.SymbolDefine(Tai_datablock(hp).sym);
  940. objsym.size:=Tai_datablock(hp).size;
  941. objsym.bind:=AB_COMMON;
  942. objsym.alignment:=needtowritealignmentalsoforELF;
  943. end
  944. else
  945. {$endif USE_COMM_IN_BSS}
  946. begin
  947. ObjData.allocalign(used_align(size_2_align(Tai_datablock(hp).size),0,ObjData.CurrObjSec.secalign));
  948. objsym:=ObjData.SymbolDefine(Tai_datablock(hp).sym);
  949. objsym.size:=Tai_datablock(hp).size;
  950. ObjData.alloc(Tai_datablock(hp).size);
  951. end;
  952. end;
  953. ait_real_80bit :
  954. ObjData.alloc(10);
  955. ait_real_64bit :
  956. ObjData.alloc(8);
  957. ait_real_32bit :
  958. ObjData.alloc(4);
  959. ait_comp_64bit :
  960. ObjData.alloc(8);
  961. ait_const:
  962. begin
  963. { Recalculate relative symbols, all checks are done in treepass0 }
  964. if assigned(tai_const(hp).sym) and
  965. assigned(tai_const(hp).endsym) then
  966. begin
  967. objsym:=Objdata.SymbolRef(tai_const(hp).sym);
  968. objsymend:=Objdata.SymbolRef(tai_const(hp).endsym);
  969. Tai_const(hp).value:=objsymend.address-objsym.address+Tai_const(hp).symofs;
  970. end;
  971. ObjData.alloc(tai_const(hp).size);
  972. end;
  973. ait_section:
  974. begin
  975. { use cached value }
  976. ObjData.setsection(Tai_section(hp).sec);
  977. end;
  978. ait_stab :
  979. begin
  980. if assigned(Tai_stab(hp).str) then
  981. WriteStab(Tai_stab(hp).str);
  982. end;
  983. ait_symbol :
  984. ObjData.SymbolDefine(Tai_symbol(hp).sym);
  985. ait_symbol_end :
  986. begin
  987. objsym:=ObjData.SymbolRef(Tai_symbol_end(hp).sym);
  988. objsym.size:=ObjData.CurrObjSec.Size-objsym.offset;
  989. end;
  990. ait_label :
  991. ObjData.SymbolDefine(Tai_label(hp).labsym);
  992. ait_string :
  993. ObjData.alloc(Tai_string(hp).len);
  994. ait_instruction :
  995. ObjData.alloc(Taicpu(hp).Pass1(ObjData));
  996. ait_cutobject :
  997. if SmartAsm then
  998. break;
  999. end;
  1000. hp:=Tai(hp.next);
  1001. end;
  1002. TreePass1:=hp;
  1003. end;
  1004. function TInternalAssembler.TreePass2(hp:Tai):Tai;
  1005. var
  1006. fillbuffer : tfillbuffer;
  1007. {$ifdef x86}
  1008. co : comp;
  1009. {$endif x86}
  1010. leblen : byte;
  1011. lebbuf : array[0..63] of byte;
  1012. objsym,
  1013. objsymend : TObjSymbol;
  1014. begin
  1015. { main loop }
  1016. while assigned(hp) do
  1017. begin
  1018. case hp.typ of
  1019. ait_align :
  1020. begin
  1021. if (oso_data in ObjData.CurrObjSec.secoptions) then
  1022. ObjData.writebytes(Tai_align_abstract(hp).calculatefillbuf(fillbuffer)^,Tai_align_abstract(hp).fillsize)
  1023. else
  1024. ObjData.alloc(Tai_align_abstract(hp).fillsize);
  1025. end;
  1026. ait_section :
  1027. begin
  1028. { use cached value }
  1029. ObjData.setsection(Tai_section(hp).sec);
  1030. end;
  1031. ait_symbol :
  1032. begin
  1033. ObjOutput.exportsymbol(ObjData.SymbolRef(Tai_symbol(hp).sym));
  1034. end;
  1035. ait_datablock :
  1036. begin
  1037. ObjOutput.exportsymbol(ObjData.SymbolRef(Tai_datablock(hp).sym));
  1038. {$ifdef USE_COMM_IN_BSS}
  1039. if not(writingpackages and
  1040. Tai_datablock(hp).is_global) then
  1041. {$endif USE_COMM_IN_BSS}
  1042. begin
  1043. ObjData.allocalign(used_align(size_2_align(Tai_datablock(hp).size),0,ObjData.CurrObjSec.secalign));
  1044. ObjData.alloc(Tai_datablock(hp).size);
  1045. end;
  1046. end;
  1047. ait_real_80bit :
  1048. ObjData.writebytes(Tai_real_80bit(hp).value,10);
  1049. ait_real_64bit :
  1050. ObjData.writebytes(Tai_real_64bit(hp).value,8);
  1051. ait_real_32bit :
  1052. ObjData.writebytes(Tai_real_32bit(hp).value,4);
  1053. ait_comp_64bit :
  1054. begin
  1055. {$ifdef x86}
  1056. co:=comp(Tai_comp_64bit(hp).value);
  1057. ObjData.writebytes(co,8);
  1058. {$endif x86}
  1059. end;
  1060. ait_string :
  1061. ObjData.writebytes(Tai_string(hp).str^,Tai_string(hp).len);
  1062. ait_const :
  1063. begin
  1064. { Recalculate relative symbols, addresses of forward references
  1065. can be changed in treepass1 }
  1066. if assigned(tai_const(hp).sym) and
  1067. assigned(tai_const(hp).endsym) then
  1068. begin
  1069. objsym:=Objdata.SymbolRef(tai_const(hp).sym);
  1070. objsymend:=Objdata.SymbolRef(tai_const(hp).endsym);
  1071. Tai_const(hp).value:=objsymend.address-objsym.address+Tai_const(hp).symofs;
  1072. end;
  1073. case tai_const(hp).consttype of
  1074. aitconst_64bit,
  1075. aitconst_32bit,
  1076. aitconst_16bit,
  1077. aitconst_8bit :
  1078. begin
  1079. if assigned(tai_const(hp).sym) and
  1080. not assigned(tai_const(hp).endsym) then
  1081. ObjData.writereloc(Tai_const(hp).symofs,tai_const(hp).size,Objdata.SymbolRef(tai_const(hp).sym),RELOC_ABSOLUTE)
  1082. else
  1083. ObjData.writebytes(Tai_const(hp).value,tai_const(hp).size);
  1084. end;
  1085. aitconst_rva_symbol :
  1086. begin
  1087. { PE32+? }
  1088. if target_info.system=system_x86_64_win64 then
  1089. ObjData.writereloc(Tai_const(hp).symofs,sizeof(longint),Objdata.SymbolRef(tai_const(hp).sym),RELOC_RVA)
  1090. else
  1091. ObjData.writereloc(Tai_const(hp).symofs,sizeof(pint),Objdata.SymbolRef(tai_const(hp).sym),RELOC_RVA);
  1092. end;
  1093. aitconst_secrel32_symbol :
  1094. begin
  1095. { Required for DWARF2 support under Windows }
  1096. ObjData.writereloc(Tai_const(hp).symofs,sizeof(longint),Objdata.SymbolRef(tai_const(hp).sym),RELOC_SECREL32);
  1097. end;
  1098. aitconst_uleb128bit,
  1099. aitconst_sleb128bit :
  1100. begin
  1101. if tai_const(hp).consttype=aitconst_uleb128bit then
  1102. leblen:=EncodeUleb128(qword(Tai_const(hp).value),lebbuf)
  1103. else
  1104. leblen:=EncodeSleb128(Tai_const(hp).value,lebbuf);
  1105. if leblen<>tai_const(hp).size then
  1106. internalerror(200709271);
  1107. ObjData.writebytes(lebbuf,leblen);
  1108. end;
  1109. else
  1110. internalerror(200603254);
  1111. end;
  1112. end;
  1113. ait_label :
  1114. begin
  1115. { exporting shouldn't be necessary as labels are local,
  1116. but it's better to be on the safe side (PFV) }
  1117. ObjOutput.exportsymbol(ObjData.SymbolRef(Tai_label(hp).labsym));
  1118. end;
  1119. ait_instruction :
  1120. Taicpu(hp).Pass2(ObjData);
  1121. ait_stab :
  1122. WriteStab(Tai_stab(hp).str);
  1123. ait_function_name,
  1124. ait_force_line : ;
  1125. ait_cutobject :
  1126. if SmartAsm then
  1127. break;
  1128. end;
  1129. hp:=Tai(hp.next);
  1130. end;
  1131. TreePass2:=hp;
  1132. end;
  1133. procedure TInternalAssembler.writetree;
  1134. label
  1135. doexit;
  1136. var
  1137. hp : Tai;
  1138. ObjWriter : TObjectWriter;
  1139. begin
  1140. ObjWriter:=TObjectwriter.create;
  1141. ObjOutput:=CObjOutput.Create(ObjWriter);
  1142. ObjData:=ObjOutput.newObjData(ObjFileName);
  1143. { Pass 0 }
  1144. ObjData.currpass:=0;
  1145. ObjData.createsection(sec_code);
  1146. ObjData.beforealloc;
  1147. { start with list 1 }
  1148. currlistidx:=1;
  1149. currlist:=list[currlistidx];
  1150. hp:=Tai(currList.first);
  1151. while assigned(hp) do
  1152. begin
  1153. hp:=TreePass0(hp);
  1154. MaybeNextList(hp);
  1155. end;
  1156. ObjData.afteralloc;
  1157. { leave if errors have occured }
  1158. if errorcount>0 then
  1159. goto doexit;
  1160. { Pass 1 }
  1161. ObjData.currpass:=1;
  1162. ObjData.resetsections;
  1163. ObjData.beforealloc;
  1164. ObjData.createsection(sec_code);
  1165. { start with list 1 }
  1166. currlistidx:=1;
  1167. currlist:=list[currlistidx];
  1168. hp:=Tai(currList.first);
  1169. while assigned(hp) do
  1170. begin
  1171. hp:=TreePass1(hp);
  1172. MaybeNextList(hp);
  1173. end;
  1174. ObjData.createsection(sec_code);
  1175. ObjData.afteralloc;
  1176. { leave if errors have occured }
  1177. if errorcount>0 then
  1178. goto doexit;
  1179. { Pass 2 }
  1180. ObjData.currpass:=2;
  1181. ObjData.resetsections;
  1182. ObjData.beforewrite;
  1183. ObjData.createsection(sec_code);
  1184. { start with list 1 }
  1185. currlistidx:=1;
  1186. currlist:=list[currlistidx];
  1187. hp:=Tai(currList.first);
  1188. while assigned(hp) do
  1189. begin
  1190. hp:=TreePass2(hp);
  1191. MaybeNextList(hp);
  1192. end;
  1193. ObjData.createsection(sec_code);
  1194. ObjData.afterwrite;
  1195. { don't write the .o file if errors have occured }
  1196. if errorcount=0 then
  1197. begin
  1198. { write objectfile }
  1199. ObjOutput.startobjectfile(ObjFileName);
  1200. ObjOutput.writeobjectfile(ObjData);
  1201. end;
  1202. doexit:
  1203. { Cleanup }
  1204. ObjData.free;
  1205. ObjData:=nil;
  1206. ObjWriter.free;
  1207. end;
  1208. procedure TInternalAssembler.writetreesmart;
  1209. var
  1210. hp : Tai;
  1211. startsectype : TAsmSectiontype;
  1212. place: tcutplace;
  1213. ObjWriter : TObjectWriter;
  1214. begin
  1215. if not(cs_asm_leave in current_settings.globalswitches) then
  1216. ObjWriter:=TARObjectWriter.create(current_module.staticlibfilename^)
  1217. else
  1218. ObjWriter:=TObjectwriter.create;
  1219. NextSmartName(cut_normal);
  1220. ObjOutput:=CObjOutput.Create(ObjWriter);
  1221. startsectype:=sec_code;
  1222. { start with list 1 }
  1223. currlistidx:=1;
  1224. currlist:=list[currlistidx];
  1225. hp:=Tai(currList.first);
  1226. while assigned(hp) do
  1227. begin
  1228. ObjData:=ObjOutput.newObjData(ObjFileName);
  1229. { Pass 0 }
  1230. ObjData.currpass:=0;
  1231. ObjData.resetsections;
  1232. ObjData.beforealloc;
  1233. ObjData.createsection(startsectype);
  1234. TreePass0(hp);
  1235. ObjData.afteralloc;
  1236. { leave if errors have occured }
  1237. if errorcount>0 then
  1238. break;
  1239. { Pass 1 }
  1240. ObjData.currpass:=1;
  1241. ObjData.resetsections;
  1242. ObjData.beforealloc;
  1243. ObjData.createsection(startsectype);
  1244. TreePass1(hp);
  1245. ObjData.afteralloc;
  1246. { leave if errors have occured }
  1247. if errorcount>0 then
  1248. break;
  1249. { Pass 2 }
  1250. ObjData.currpass:=2;
  1251. ObjOutput.startobjectfile(ObjFileName);
  1252. ObjData.resetsections;
  1253. ObjData.beforewrite;
  1254. ObjData.createsection(startsectype);
  1255. hp:=TreePass2(hp);
  1256. ObjData.afterwrite;
  1257. { leave if errors have occured }
  1258. if errorcount>0 then
  1259. break;
  1260. { write the current objectfile }
  1261. ObjOutput.writeobjectfile(ObjData);
  1262. ObjData.free;
  1263. ObjData:=nil;
  1264. { end of lists? }
  1265. if not MaybeNextList(hp) then
  1266. break;
  1267. { we will start a new objectfile so reset everything }
  1268. { The place can still change in the next while loop, so don't init }
  1269. { the writer yet (JM) }
  1270. if (hp.typ=ait_cutobject) then
  1271. place := Tai_cutobject(hp).place
  1272. else
  1273. place := cut_normal;
  1274. { avoid empty files }
  1275. startsectype:=sec_code;
  1276. while assigned(hp) and
  1277. (Tai(hp).typ in [ait_marker,ait_comment,ait_section,ait_cutobject]) do
  1278. begin
  1279. if Tai(hp).typ=ait_section then
  1280. startsectype:=Tai_section(hp).sectype;
  1281. if (Tai(hp).typ=ait_cutobject) then
  1282. place:=Tai_cutobject(hp).place;
  1283. hp:=Tai(hp.next);
  1284. end;
  1285. if not MaybeNextList(hp) then
  1286. break;
  1287. { start next objectfile }
  1288. NextSmartName(place);
  1289. end;
  1290. ObjData.free;
  1291. ObjData:=nil;
  1292. ObjWriter.free;
  1293. end;
  1294. procedure TInternalAssembler.MakeObject;
  1295. var to_do:set of TasmlistType;
  1296. i:TasmlistType;
  1297. procedure addlist(p:TAsmList);
  1298. begin
  1299. inc(lists);
  1300. list[lists]:=p;
  1301. end;
  1302. begin
  1303. to_do:=[low(Tasmlisttype)..high(Tasmlisttype)];
  1304. if usedeffileforexports then
  1305. exclude(to_do,al_exports);
  1306. if not(tf_section_threadvars in target_info.flags) then
  1307. exclude(to_do,al_threadvars);
  1308. for i:=low(TasmlistType) to high(TasmlistType) do
  1309. if (i in to_do) and (current_asmdata.asmlists[i]<>nil) then
  1310. addlist(current_asmdata.asmlists[i]);
  1311. if SmartAsm then
  1312. writetreesmart
  1313. else
  1314. writetree;
  1315. end;
  1316. {*****************************************************************************
  1317. Generate Assembler Files Main Procedure
  1318. *****************************************************************************}
  1319. Procedure GenerateAsm(smart:boolean);
  1320. var
  1321. a : TAssembler;
  1322. begin
  1323. if not assigned(CAssembler[target_asm.id]) then
  1324. Message(asmw_f_assembler_output_not_supported);
  1325. a:=CAssembler[target_asm.id].Create(smart);
  1326. a.MakeObject;
  1327. a.Free;
  1328. end;
  1329. Procedure OnlyAsm;
  1330. var
  1331. a : TExternalAssembler;
  1332. begin
  1333. a:=TExternalAssembler.Create(false);
  1334. a.DoAssemble;
  1335. a.Free;
  1336. end;
  1337. {*****************************************************************************
  1338. Init/Done
  1339. *****************************************************************************}
  1340. procedure RegisterAssembler(const r:tasminfo;c:TAssemblerClass);
  1341. var
  1342. t : tasm;
  1343. begin
  1344. t:=r.id;
  1345. if assigned(asminfos[t]) then
  1346. writeln('Warning: Assembler is already registered!')
  1347. else
  1348. Getmem(asminfos[t],sizeof(tasminfo));
  1349. asminfos[t]^:=r;
  1350. CAssembler[t]:=c;
  1351. end;
  1352. end.