assemble.pas 45 KB

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