assemble.pas 45 KB

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