2
0

assemble.pas 43 KB

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