assemble.pas 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488
  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,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. asmfile, { current .s and .o file }
  45. objfile : string;
  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:TAAsmoutput);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. public
  111. constructor create(smart:boolean);override;
  112. destructor destroy;override;
  113. procedure MakeObject;override;
  114. protected
  115. objectdata : TAsmObjectData;
  116. objectoutput : tobjectoutput;
  117. private
  118. { the aasmoutput lists that need to be processed }
  119. lists : byte;
  120. list : array[1..maxoutputlists] of TAAsmoutput;
  121. { current processing }
  122. currlistidx : byte;
  123. currlist : TAAsmoutput;
  124. currpass : byte;
  125. procedure convertstab(p:pchar);
  126. function MaybeNextList(var hp:Tai):boolean;
  127. function TreePass0(hp:Tai):Tai;
  128. function TreePass1(hp:Tai):Tai;
  129. function TreePass2(hp:Tai):Tai;
  130. procedure writetree;
  131. procedure writetreesmart;
  132. end;
  133. TAssemblerClass = class of TAssembler;
  134. Procedure GenerateAsm(smart:boolean);
  135. Procedure OnlyAsm;
  136. procedure RegisterAssembler(const r:tasminfo;c:TAssemblerClass);
  137. procedure InitAssembler;
  138. procedure DoneAssembler;
  139. Implementation
  140. uses
  141. {$ifdef hasunix}
  142. {$ifdef havelinuxrtl10}
  143. linux,
  144. {$else}
  145. unix,
  146. {$endif}
  147. {$endif}
  148. cutils,script,fmodule,verbose,
  149. {$ifdef memdebug}
  150. cclasses,
  151. {$endif memdebug}
  152. {$ifdef m68k}
  153. cpuinfo,
  154. {$endif m68k}
  155. aasmcpu
  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. asmfile:=current_module.get_asmfilename;
  166. objfile:=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. AsmFile:=Path+FixFileName(s+tostr(SmartFilesCount)+target_info.asmext);
  201. ObjFile:=Path+FixFileName(s+tostr(SmartFilesCount)+target_info.objext);
  202. { insert in container so it can be cleared after the linking }
  203. SmartLinkOFiles.Insert(Objfile);
  204. end;
  205. {*****************************************************************************
  206. TExternalAssembler
  207. *****************************************************************************}
  208. Function DoPipe:boolean;
  209. begin
  210. DoPipe:=(cs_asm_pipe in aktglobalswitches) and
  211. (([cs_asm_leave,cs_link_on_target] * aktglobalswitches) = []) and
  212. ((target_asm.id in [as_gas,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(path+FixFileName(name)+target_info.smartext,false);
  220. CreateSmartLinkPath(path);
  221. end;
  222. Outcnt:=0;
  223. end;
  224. procedure TExternalAssembler.CreateSmartLinkPath(const s:string);
  225. var
  226. {$IFDEF USE_SYSUTILS}
  227. dir : TSearchRec;
  228. {$ELSE USE_SYSUTILS}
  229. dir : searchrec;
  230. {$ENDIF USE_SYSUTILS}
  231. hs : string;
  232. begin
  233. if PathExists(s) then
  234. begin
  235. { the path exists, now we clean only all the .o and .s files }
  236. { .o files }
  237. {$IFDEF USE_SYSUTILS}
  238. if findfirst(s+source_info.dirsep+'*'+target_info.objext,faAnyFile,dir) = 0
  239. then repeat
  240. RemoveFile(s+source_info.dirsep+dir.name);
  241. until findnext(dir) <> 0;
  242. {$ELSE USE_SYSUTILS}
  243. findfirst(s+source_info.dirsep+'*'+target_info.objext,anyfile,dir);
  244. while (doserror=0) do
  245. begin
  246. RemoveFile(s+source_info.dirsep+dir.name);
  247. findnext(dir);
  248. end;
  249. {$ENDIF USE_SYSUTILS}
  250. findclose(dir);
  251. { .s files }
  252. {$IFDEF USE_SYSUTILS}
  253. if findfirst(s+source_info.dirsep+'*'+target_info.asmext,faAnyFile,dir) = 0
  254. then repeat
  255. RemoveFile(s+source_info.dirsep+dir.name);
  256. until findnext(dir) <> 0;
  257. {$ELSE USE_SYSUTILS}
  258. findfirst(s+source_info.dirsep+'*'+target_info.asmext,anyfile,dir);
  259. while (doserror=0) do
  260. begin
  261. RemoveFile(s+source_info.dirsep+dir.name);
  262. findnext(dir);
  263. end;
  264. {$ENDIF USE_SYSUTILS}
  265. findclose(dir);
  266. end
  267. else
  268. begin
  269. hs:=s;
  270. if hs[length(hs)] in ['/','\'] then
  271. delete(hs,length(hs),1);
  272. {$I-}
  273. mkdir(hs);
  274. {$I+}
  275. if ioresult<>0 then;
  276. end;
  277. end;
  278. const
  279. lastas : byte=255;
  280. var
  281. LastASBin : pathstr;
  282. Function TExternalAssembler.FindAssembler:string;
  283. var
  284. asfound : boolean;
  285. UtilExe : string;
  286. begin
  287. asfound:=false;
  288. if cs_link_on_target in aktglobalswitches then
  289. begin
  290. { If linking on target, don't add any path PM }
  291. FindAssembler:=utilsprefix+AddExtension(target_asm.asmbin,target_info.exeext);
  292. exit;
  293. end
  294. else
  295. UtilExe:=utilsprefix+AddExtension(target_asm.asmbin,source_info.exeext);
  296. if lastas<>ord(target_asm.id) then
  297. begin
  298. lastas:=ord(target_asm.id);
  299. { is an assembler passed ? }
  300. if utilsdirectory<>'' then
  301. asfound:=FindFile(UtilExe,utilsdirectory,LastASBin);
  302. if not AsFound then
  303. asfound:=FindExe(UtilExe,LastASBin);
  304. if (not asfound) and not(cs_asm_extern in aktglobalswitches) then
  305. begin
  306. Message1(exec_e_assembler_not_found,LastASBin);
  307. aktglobalswitches:=aktglobalswitches+[cs_asm_extern];
  308. end;
  309. if asfound then
  310. Message1(exec_t_using_assembler,LastASBin);
  311. end;
  312. FindAssembler:=LastASBin;
  313. end;
  314. Function TExternalAssembler.CallAssembler(const command:string; const para:TCmdStr):Boolean;
  315. {$IFDEF USE_SYSUTILS}
  316. var
  317. DosExitCode:Integer;
  318. {$ENDIF USE_SYSUTILS}
  319. begin
  320. callassembler:=true;
  321. if not(cs_asm_extern in aktglobalswitches) then
  322. {$IFDEF USE_SYSUTILS}
  323. try
  324. DosExitCode := ExecuteProcess(command,para);
  325. if DosExitCode <>0
  326. then begin
  327. Message1(exec_e_error_while_assembling,tostr(dosexitcode));
  328. callassembler:=false;
  329. end;
  330. except on E:EOSError do
  331. begin
  332. Message1(exec_e_cant_call_assembler,tostr(E.ErrorCode));
  333. aktglobalswitches:=aktglobalswitches+[cs_asm_extern];
  334. callassembler:=false;
  335. end
  336. end
  337. {$ELSE USE_SYSUTILS}
  338. begin
  339. swapvectors;
  340. exec(maybequoted(command),para);
  341. swapvectors;
  342. if (doserror<>0) then
  343. begin
  344. Message1(exec_e_cant_call_assembler,tostr(doserror));
  345. aktglobalswitches:=aktglobalswitches+[cs_asm_extern];
  346. callassembler:=false;
  347. end
  348. else
  349. if (dosexitcode<>0) then
  350. begin
  351. Message1(exec_e_error_while_assembling,tostr(dosexitcode));
  352. callassembler:=false;
  353. end;
  354. end
  355. {$ENDIF USE_SYSUTILS}
  356. else
  357. AsmRes.AddAsmCommand(command,para,name);
  358. end;
  359. procedure TExternalAssembler.RemoveAsm;
  360. var
  361. g : file;
  362. begin
  363. if cs_asm_leave in aktglobalswitches then
  364. exit;
  365. if cs_asm_extern in aktglobalswitches then
  366. AsmRes.AddDeleteCommand(AsmFile)
  367. else
  368. begin
  369. assign(g,AsmFile);
  370. {$I-}
  371. erase(g);
  372. {$I+}
  373. if ioresult<>0 then;
  374. end;
  375. end;
  376. Function TExternalAssembler.DoAssemble:boolean;
  377. var
  378. s : TCmdStr;
  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 aktoptprocessor = 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(AsmFile)));
  489. Replace(result,'$OBJ',maybequoted(ScriptFixFileName(ObjFile)));
  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(AsmFile));
  499. Replace(result,'$OBJ',maybequoted(ObjFile));
  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. Message1(exec_i_assembling_pipe,asmfile);
  510. POpen(outfile,FindAssembler+' '+MakeCmdLine,'W');
  511. end
  512. else
  513. {$endif}
  514. begin
  515. Assign(outfile,asmfile);
  516. {$I-}
  517. Rewrite(outfile,1);
  518. {$I+}
  519. if ioresult<>0 then
  520. begin
  521. ioerror:=true;
  522. Message1(exec_d_cant_create_asmfile,asmfile);
  523. end;
  524. end;
  525. outcnt:=0;
  526. AsmSize:=0;
  527. AsmStartSize:=0;
  528. end;
  529. procedure TExternalAssembler.AsmClose;
  530. var
  531. f : file;
  532. FileAge : longint;
  533. begin
  534. AsmFlush;
  535. {$ifdef hasunix}
  536. if DoPipe then
  537. begin
  538. if PClose(outfile) <> 0 then
  539. GenerateError;
  540. end
  541. else
  542. {$endif}
  543. begin
  544. {Touch Assembler time to ppu time is there is a ppufilename}
  545. if ppufilename<>'' then
  546. begin
  547. Assign(f,ppufilename);
  548. {$I-}
  549. reset(f,1);
  550. {$I+}
  551. if ioresult=0 then
  552. begin
  553. {$IFDEF USE_SYSUTILS}
  554. FileAge := FileGetDate(GetFileHandle(f));
  555. {$ELSE USE_SYSUTILS}
  556. GetFTime(f, FileAge);
  557. {$ENDIF USE_SYSUTILS}
  558. close(f);
  559. reset(outfile,1);
  560. {$IFDEF USE_SYSUTILS}
  561. FileSetDate(GetFileHandle(outFile),FileAge);
  562. {$ELSE USE_SYSUTILS}
  563. SetFTime(f, FileAge);
  564. {$ENDIF USE_SYSUTILS}
  565. end;
  566. end;
  567. close(outfile);
  568. end;
  569. end;
  570. procedure TExternalAssembler.WriteTree(p:TAAsmoutput);
  571. begin
  572. end;
  573. procedure TExternalAssembler.WriteAsmList;
  574. begin
  575. end;
  576. procedure TExternalAssembler.MakeObject;
  577. begin
  578. AsmCreate(cut_normal);
  579. WriteAsmList;
  580. AsmClose;
  581. if not(ioerror) then
  582. DoAssemble;
  583. end;
  584. {*****************************************************************************
  585. TInternalAssembler
  586. *****************************************************************************}
  587. constructor TInternalAssembler.create(smart:boolean);
  588. begin
  589. inherited create(smart);
  590. objectoutput:=nil;
  591. objectdata:=nil;
  592. SmartAsm:=smart;
  593. currpass:=0;
  594. end;
  595. destructor TInternalAssembler.destroy;
  596. {$ifdef MEMDEBUG}
  597. var
  598. d : tmemdebug;
  599. {$endif}
  600. begin
  601. {$ifdef MEMDEBUG}
  602. d := tmemdebug.create(name+' - agbin');
  603. {$endif}
  604. objectdata.free;
  605. objectoutput.free;
  606. {$ifdef MEMDEBUG}
  607. d.free;
  608. {$endif}
  609. end;
  610. procedure TInternalAssembler.convertstab(p:pchar);
  611. function consumecomma(var p:pchar):boolean;
  612. begin
  613. while (p^=' ') do
  614. inc(p);
  615. result:=(p^=',');
  616. inc(p);
  617. end;
  618. function consumenumber(var p:pchar;out value:longint):boolean;
  619. var
  620. hs : string;
  621. len,
  622. code : integer;
  623. begin
  624. value:=0;
  625. while (p^=' ') do
  626. inc(p);
  627. len:=0;
  628. while (p^ in ['0'..'9']) do
  629. begin
  630. inc(len);
  631. hs[len]:=p^;
  632. inc(p);
  633. end;
  634. if len>0 then
  635. begin
  636. hs[0]:=chr(len);
  637. val(hs,value,code);
  638. end
  639. else
  640. code:=-1;
  641. result:=(code=0);
  642. end;
  643. function consumeoffset(var p:pchar;out relocsym:tasmsymbol;out value:longint):boolean;
  644. var
  645. hs : string;
  646. len,
  647. code : integer;
  648. pstart : pchar;
  649. sym : tasmsymbol;
  650. exprvalue : longint;
  651. gotmin,
  652. dosub : boolean;
  653. begin
  654. result:=false;
  655. value:=0;
  656. relocsym:=nil;
  657. gotmin:=false;
  658. repeat
  659. dosub:=false;
  660. exprvalue:=0;
  661. if gotmin then
  662. begin
  663. dosub:=true;
  664. gotmin:=false;
  665. end;
  666. while (p^=' ') do
  667. inc(p);
  668. case p^ of
  669. #0 :
  670. break;
  671. ' ' :
  672. inc(p);
  673. '0'..'9' :
  674. begin
  675. len:=0;
  676. while (p^ in ['0'..'9']) do
  677. begin
  678. inc(len);
  679. hs[len]:=p^;
  680. inc(p);
  681. end;
  682. hs[0]:=chr(len);
  683. val(hs,exprvalue,code);
  684. end;
  685. '.','_',
  686. 'A'..'Z',
  687. 'a'..'z' :
  688. begin
  689. pstart:=p;
  690. while not(p^ in [#0,' ','-','+']) do
  691. inc(p);
  692. len:=p-pstart;
  693. if len>255 then
  694. internalerror(200509187);
  695. move(pstart^,hs[1],len);
  696. hs[0]:=chr(len);
  697. sym:=objectlibrary.newasmsymbol(hs,AB_EXTERNAL,AT_NONE);
  698. if not assigned(sym) then
  699. internalerror(200509188);
  700. objectlibrary.UsedAsmSymbolListInsert(sym);
  701. { Second symbol? }
  702. if assigned(relocsym) then
  703. begin
  704. if (relocsym.section<>sym.section) then
  705. internalerror(2005091810);
  706. relocsym:=nil;
  707. end
  708. else
  709. begin
  710. relocsym:=sym;
  711. end;
  712. exprvalue:=sym.address;
  713. end;
  714. '+' :
  715. begin
  716. { nothing, by default addition is done }
  717. inc(p);
  718. end;
  719. '-' :
  720. begin
  721. gotmin:=true;
  722. inc(p);
  723. end;
  724. else
  725. internalerror(200509189);
  726. end;
  727. if dosub then
  728. dec(value,exprvalue)
  729. else
  730. inc(value,exprvalue);
  731. until false;
  732. result:=true;
  733. end;
  734. const
  735. N_Function = $24; { function or const }
  736. var
  737. ofs,
  738. nline,
  739. nidx,
  740. nother,
  741. i : longint;
  742. relocsym : tasmsymbol;
  743. pstr,
  744. pcurr,
  745. pendquote : pchar;
  746. begin
  747. pcurr:=nil;
  748. pstr:=nil;
  749. pendquote:=nil;
  750. { Parse string part }
  751. if p[0]='"' then
  752. begin
  753. pstr:=@p[1];
  754. { Ignore \" inside the string }
  755. i:=1;
  756. while not((p[i]='"') and (p[i-1]<>'\')) and
  757. (p[i]<>#0) do
  758. inc(i);
  759. pendquote:=@p[i];
  760. pendquote^:=#0;
  761. pcurr:=@p[i+1];
  762. if not consumecomma(pcurr) then
  763. internalerror(200509181);
  764. end
  765. else
  766. pcurr:=p;
  767. { When in pass 1 then only alloc and leave }
  768. if currpass=1 then
  769. objectdata.allocstab(pstr)
  770. else
  771. begin
  772. { Stabs format: nidx,nother,nline[,offset] }
  773. if not consumenumber(pcurr,nidx) then
  774. internalerror(200509182);
  775. if not consumecomma(pcurr) then
  776. internalerror(200509183);
  777. if not consumenumber(pcurr,nother) then
  778. internalerror(200509184);
  779. if not consumecomma(pcurr) then
  780. internalerror(200509185);
  781. if not consumenumber(pcurr,nline) then
  782. internalerror(200509186);
  783. if consumecomma(pcurr) then
  784. consumeoffset(pcurr,relocsym,ofs)
  785. else
  786. begin
  787. ofs:=0;
  788. relocsym:=nil;
  789. end;
  790. if (nidx=N_Function) and
  791. (tf_use_function_relative_addresses in target_info.flags) then
  792. ofs:=0;
  793. objectdata.writestab(ofs,relocsym,nidx,nother,nline,pstr);
  794. end;
  795. if assigned(pendquote) then
  796. pendquote^:='"';
  797. end;
  798. function TInternalAssembler.MaybeNextList(var hp:Tai):boolean;
  799. begin
  800. { maybe end of list }
  801. while not assigned(hp) do
  802. begin
  803. if currlistidx<lists then
  804. begin
  805. inc(currlistidx);
  806. currlist:=list[currlistidx];
  807. hp:=Tai(currList.first);
  808. end
  809. else
  810. begin
  811. MaybeNextList:=false;
  812. exit;
  813. end;
  814. end;
  815. MaybeNextList:=true;
  816. end;
  817. function TInternalAssembler.TreePass0(hp:Tai):Tai;
  818. var
  819. l : longint;
  820. begin
  821. while assigned(hp) do
  822. begin
  823. case hp.typ of
  824. ait_align :
  825. begin
  826. { always use the maximum fillsize in this pass to avoid possible
  827. short jumps to become out of range }
  828. Tai_align(hp).fillsize:=Tai_align(hp).aligntype;
  829. objectdata.alloc(Tai_align(hp).fillsize);
  830. end;
  831. ait_datablock :
  832. begin
  833. l:=used_align(size_2_align(Tai_datablock(hp).size),0,objectdata.currsec.addralign);
  834. if SmartAsm or (not Tai_datablock(hp).is_global) then
  835. begin
  836. objectdata.allocalign(l);
  837. objectdata.alloc(Tai_datablock(hp).size);
  838. end;
  839. end;
  840. ait_real_80bit :
  841. objectdata.alloc(10);
  842. ait_real_64bit :
  843. objectdata.alloc(8);
  844. ait_real_32bit :
  845. objectdata.alloc(4);
  846. ait_comp_64bit :
  847. objectdata.alloc(8);
  848. ait_const:
  849. objectdata.alloc(tai_const(hp).size);
  850. ait_section:
  851. begin
  852. objectdata.CreateSection(Tai_section(hp).sectype,Tai_section(hp).name^,Tai_section(hp).secalign,[]);
  853. Tai_section(hp).sec:=objectdata.CurrSec;
  854. end;
  855. ait_symbol :
  856. objectdata.allocsymbol(currpass,Tai_symbol(hp).sym,0);
  857. ait_label :
  858. objectdata.allocsymbol(currpass,Tai_label(hp).l,0);
  859. ait_string :
  860. objectdata.alloc(Tai_string(hp).len);
  861. ait_instruction :
  862. begin
  863. {$ifdef i386}
  864. {$ifndef NOAG386BIN}
  865. { reset instructions which could change in pass 2 }
  866. Taicpu(hp).resetpass2;
  867. objectdata.alloc(Taicpu(hp).Pass1(objectdata.currsec.datasize));
  868. {$endif NOAG386BIN}
  869. {$endif i386}
  870. {$ifdef arm}
  871. { reset instructions which could change in pass 2 }
  872. Taicpu(hp).resetpass2;
  873. objectdata.alloc(Taicpu(hp).Pass1(objectdata.currsec.datasize));
  874. {$endif arm}
  875. end;
  876. ait_cutobject :
  877. if SmartAsm then
  878. break;
  879. end;
  880. hp:=Tai(hp.next);
  881. end;
  882. TreePass0:=hp;
  883. end;
  884. function TInternalAssembler.TreePass1(hp:Tai):Tai;
  885. var
  886. InlineLevel,
  887. l,
  888. i : longint;
  889. begin
  890. inlinelevel:=0;
  891. while assigned(hp) do
  892. begin
  893. case hp.typ of
  894. ait_align :
  895. begin
  896. { here we must determine the fillsize which is used in pass2 }
  897. Tai_align(hp).fillsize:=align(objectdata.currsec.datasize,Tai_align(hp).aligntype)-
  898. objectdata.currsec.datasize;
  899. objectdata.alloc(Tai_align(hp).fillsize);
  900. end;
  901. ait_datablock :
  902. begin
  903. if not (objectdata.currsec.sectype in [sec_bss,sec_threadvar]) then
  904. Message(asmw_e_alloc_data_only_in_bss);
  905. l:=used_align(size_2_align(Tai_datablock(hp).size),0,objectdata.currsec.addralign);
  906. { if Tai_datablock(hp).is_global and
  907. not SmartAsm then
  908. begin}
  909. { objectdata.allocsymbol(currpass,Tai_datablock(hp).sym,Tai_datablock(hp).size);}
  910. { force to be common/external, must be after setaddress as that would
  911. set it to AB_GLOBAL }
  912. { Tai_datablock(hp).sym.currbind:=AB_COMMON;
  913. end
  914. else
  915. begin}
  916. objectdata.allocalign(l);
  917. objectdata.allocsymbol(currpass,Tai_datablock(hp).sym,Tai_datablock(hp).size);
  918. objectdata.alloc(Tai_datablock(hp).size);
  919. { end;}
  920. objectlibrary.UsedAsmSymbolListInsert(Tai_datablock(hp).sym);
  921. end;
  922. ait_real_80bit :
  923. objectdata.alloc(10);
  924. ait_real_64bit :
  925. objectdata.alloc(8);
  926. ait_real_32bit :
  927. objectdata.alloc(4);
  928. ait_comp_64bit :
  929. objectdata.alloc(8);
  930. ait_const:
  931. begin
  932. objectdata.alloc(tai_const(hp).size);
  933. if assigned(Tai_const(hp).sym) then
  934. objectlibrary.UsedAsmSymbolListInsert(Tai_const(hp).sym);
  935. if assigned(Tai_const(hp).endsym) then
  936. objectlibrary.UsedAsmSymbolListInsert(Tai_const(hp).endsym);
  937. end;
  938. ait_section:
  939. begin
  940. { use cached value }
  941. objectdata.setsection(Tai_section(hp).sec);
  942. end;
  943. ait_stab :
  944. begin
  945. if assigned(Tai_stab(hp).str) then
  946. convertstab(Tai_stab(hp).str);
  947. end;
  948. ait_function_name,
  949. ait_force_line : ;
  950. ait_symbol :
  951. begin
  952. objectdata.allocsymbol(currpass,Tai_symbol(hp).sym,0);
  953. objectlibrary.UsedAsmSymbolListInsert(Tai_symbol(hp).sym);
  954. end;
  955. ait_symbol_end :
  956. begin
  957. if target_info.system in [system_i386_linux,system_i386_beos] then
  958. begin
  959. Tai_symbol_end(hp).sym.size:=objectdata.currsec.datasize-Tai_symbol_end(hp).sym.address;
  960. objectlibrary.UsedAsmSymbolListInsert(Tai_symbol_end(hp).sym);
  961. end;
  962. end;
  963. ait_label :
  964. begin
  965. objectdata.allocsymbol(currpass,Tai_label(hp).l,0);
  966. objectlibrary.UsedAsmSymbolListInsert(Tai_label(hp).l);
  967. end;
  968. ait_string :
  969. objectdata.alloc(Tai_string(hp).len);
  970. ait_instruction :
  971. begin
  972. objectdata.alloc(Taicpu(hp).Pass1(objectdata.currsec.datasize));
  973. { fixup the references }
  974. for i:=1 to Taicpu(hp).ops do
  975. begin
  976. with Taicpu(hp).oper[i-1]^ do
  977. begin
  978. case typ of
  979. top_ref :
  980. begin
  981. if assigned(ref^.symbol) then
  982. objectlibrary.UsedAsmSymbolListInsert(ref^.symbol);
  983. if assigned(ref^.relsymbol) then
  984. objectlibrary.UsedAsmSymbolListInsert(ref^.symbol);
  985. end;
  986. end;
  987. end;
  988. end;
  989. end;
  990. ait_cutobject :
  991. if SmartAsm then
  992. break;
  993. ait_marker :
  994. if tai_marker(hp).kind=InlineStart then
  995. inc(InlineLevel)
  996. else if tai_marker(hp).kind=InlineEnd then
  997. dec(InlineLevel);
  998. end;
  999. hp:=Tai(hp.next);
  1000. end;
  1001. TreePass1:=hp;
  1002. end;
  1003. function TInternalAssembler.TreePass2(hp:Tai):Tai;
  1004. var
  1005. fillbuffer : tfillbuffer;
  1006. InlineLevel,
  1007. l : longint;
  1008. v : int64;
  1009. {$ifdef x86}
  1010. co : comp;
  1011. {$endif x86}
  1012. begin
  1013. inlinelevel:=0;
  1014. { main loop }
  1015. while assigned(hp) do
  1016. begin
  1017. case hp.typ of
  1018. ait_align :
  1019. begin
  1020. if objectdata.currsec.sectype in [sec_bss,sec_threadvar] then
  1021. objectdata.alloc(Tai_align(hp).fillsize)
  1022. else
  1023. objectdata.writebytes(Tai_align(hp).calculatefillbuf(fillbuffer)^,Tai_align(hp).fillsize);
  1024. end;
  1025. ait_section :
  1026. begin
  1027. { use cached value }
  1028. objectdata.setsection(Tai_section(hp).sec);
  1029. end;
  1030. ait_symbol :
  1031. begin
  1032. objectdata.writesymbol(Tai_symbol(hp).sym);
  1033. objectoutput.exportsymbol(Tai_symbol(hp).sym);
  1034. end;
  1035. ait_datablock :
  1036. begin
  1037. l:=used_align(size_2_align(Tai_datablock(hp).size),0,objectdata.currsec.addralign);
  1038. objectdata.writesymbol(Tai_datablock(hp).sym);
  1039. objectoutput.exportsymbol(Tai_datablock(hp).sym);
  1040. { if SmartAsm or (not Tai_datablock(hp).is_global) then
  1041. begin}
  1042. objectdata.allocalign(l);
  1043. objectdata.alloc(Tai_datablock(hp).size);
  1044. { end;}
  1045. end;
  1046. ait_real_80bit :
  1047. objectdata.writebytes(Tai_real_80bit(hp).value,10);
  1048. ait_real_64bit :
  1049. objectdata.writebytes(Tai_real_64bit(hp).value,8);
  1050. ait_real_32bit :
  1051. objectdata.writebytes(Tai_real_32bit(hp).value,4);
  1052. ait_comp_64bit :
  1053. begin
  1054. {$ifdef x86}
  1055. co:=comp(Tai_comp_64bit(hp).value);
  1056. objectdata.writebytes(co,8);
  1057. {$endif x86}
  1058. end;
  1059. ait_string :
  1060. objectdata.writebytes(Tai_string(hp).str^,Tai_string(hp).len);
  1061. ait_const :
  1062. begin
  1063. case tai_const(hp).consttype of
  1064. aitconst_64bit,
  1065. aitconst_32bit,
  1066. aitconst_16bit,
  1067. aitconst_8bit :
  1068. if assigned(tai_const(hp).sym) then
  1069. begin
  1070. if assigned(tai_const(hp).endsym) then
  1071. begin
  1072. if tai_const(hp).endsym.section<>tai_const(hp).sym.section then
  1073. internalerror(200404124);
  1074. v:=tai_const(hp).endsym.address-tai_const(hp).sym.address+Tai_const(hp).value;
  1075. objectdata.writebytes(v,tai_const(hp).size);
  1076. end
  1077. else
  1078. objectdata.writereloc(Tai_const(hp).value,Tai_const(hp).size,
  1079. Tai_const(hp).sym,RELOC_ABSOLUTE);
  1080. end
  1081. else
  1082. objectdata.writebytes(Tai_const(hp).value,tai_const(hp).size);
  1083. aitconst_rva_symbol :
  1084. objectdata.writereloc(Tai_const(hp).value,sizeof(aint),Tai_const(hp).sym,RELOC_RVA);
  1085. end;
  1086. end;
  1087. ait_label :
  1088. begin
  1089. objectdata.writesymbol(Tai_label(hp).l);
  1090. { exporting shouldn't be necessary as labels are local,
  1091. but it's better to be on the safe side (PFV) }
  1092. objectoutput.exportsymbol(Tai_label(hp).l);
  1093. end;
  1094. ait_instruction :
  1095. Taicpu(hp).Pass2(objectdata);
  1096. ait_stab :
  1097. convertstab(Tai_stab(hp).str);
  1098. ait_function_name,
  1099. ait_force_line : ;
  1100. ait_cutobject :
  1101. if SmartAsm then
  1102. break;
  1103. ait_marker :
  1104. if tai_marker(hp).kind=InlineStart then
  1105. inc(InlineLevel)
  1106. else if tai_marker(hp).kind=InlineEnd then
  1107. dec(InlineLevel);
  1108. end;
  1109. hp:=Tai(hp.next);
  1110. end;
  1111. TreePass2:=hp;
  1112. end;
  1113. procedure TInternalAssembler.writetree;
  1114. var
  1115. hp : Tai;
  1116. label
  1117. doexit;
  1118. begin
  1119. objectdata:=objectoutput.newobjectdata(Objfile);
  1120. { reset the asmsymbol list }
  1121. objectlibrary.CreateUsedAsmsymbolList;
  1122. { Pass 0 }
  1123. currpass:=0;
  1124. objectdata.createsection(sec_code,'',0,[]);
  1125. objectdata.beforealloc;
  1126. { start with list 1 }
  1127. currlistidx:=1;
  1128. currlist:=list[currlistidx];
  1129. hp:=Tai(currList.first);
  1130. while assigned(hp) do
  1131. begin
  1132. hp:=TreePass0(hp);
  1133. MaybeNextList(hp);
  1134. end;
  1135. objectdata.afteralloc;
  1136. { leave if errors have occured }
  1137. if errorcount>0 then
  1138. goto doexit;
  1139. { Pass 1 }
  1140. currpass:=1;
  1141. objectdata.resetsections;
  1142. objectdata.beforealloc;
  1143. objectdata.createsection(sec_code,'',0,[]);
  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:=TreePass1(hp);
  1151. MaybeNextList(hp);
  1152. end;
  1153. objectdata.createsection(sec_code,'',0,[]);
  1154. objectdata.afteralloc;
  1155. { check for undefined labels and reset }
  1156. objectlibrary.UsedAsmSymbolListCheckUndefined;
  1157. { leave if errors have occured }
  1158. if errorcount>0 then
  1159. goto doexit;
  1160. { Pass 2 }
  1161. currpass:=2;
  1162. objectdata.resetsections;
  1163. objectdata.beforewrite;
  1164. objectdata.createsection(sec_code,'',0,[]);
  1165. { start with list 1 }
  1166. currlistidx:=1;
  1167. currlist:=list[currlistidx];
  1168. hp:=Tai(currList.first);
  1169. while assigned(hp) do
  1170. begin
  1171. hp:=TreePass2(hp);
  1172. MaybeNextList(hp);
  1173. end;
  1174. objectdata.createsection(sec_code,'',0,[]);
  1175. objectdata.afterwrite;
  1176. { don't write the .o file if errors have occured }
  1177. if errorcount=0 then
  1178. begin
  1179. { write objectfile }
  1180. objectoutput.startobjectfile(ObjFile);
  1181. objectoutput.writeobjectfile(objectdata);
  1182. objectdata.free;
  1183. objectdata:=nil;
  1184. end;
  1185. doexit:
  1186. { reset the used symbols back, must be after the .o has been
  1187. written }
  1188. objectlibrary.UsedAsmsymbolListReset;
  1189. objectlibrary.DestroyUsedAsmsymbolList;
  1190. end;
  1191. procedure TInternalAssembler.writetreesmart;
  1192. var
  1193. hp : Tai;
  1194. startsectype : TAsmSectionType;
  1195. place: tcutplace;
  1196. begin
  1197. NextSmartName(cut_normal);
  1198. objectdata:=objectoutput.newobjectdata(Objfile);
  1199. startsectype:=sec_code;
  1200. { start with list 1 }
  1201. currlistidx:=1;
  1202. currlist:=list[currlistidx];
  1203. hp:=Tai(currList.first);
  1204. while assigned(hp) do
  1205. begin
  1206. { reset the asmsymbol list }
  1207. objectlibrary.CreateUsedAsmSymbolList;
  1208. { Pass 0 }
  1209. currpass:=0;
  1210. objectdata.resetsections;
  1211. objectdata.beforealloc;
  1212. objectdata.createsection(startsectype,'',0,[]);
  1213. TreePass0(hp);
  1214. objectdata.afteralloc;
  1215. { leave if errors have occured }
  1216. if errorcount>0 then
  1217. exit;
  1218. { Pass 1 }
  1219. currpass:=1;
  1220. objectdata.resetsections;
  1221. objectdata.beforealloc;
  1222. objectdata.createsection(startsectype,'',0,[]);
  1223. TreePass1(hp);
  1224. objectdata.afteralloc;
  1225. { check for undefined labels }
  1226. objectlibrary.UsedAsmSymbolListCheckUndefined;
  1227. { leave if errors have occured }
  1228. if errorcount>0 then
  1229. exit;
  1230. { Pass 2 }
  1231. currpass:=2;
  1232. objectoutput.startobjectfile(Objfile);
  1233. objectdata.resetsections;
  1234. objectdata.beforewrite;
  1235. objectdata.createsection(startsectype,'',0,[]);
  1236. hp:=TreePass2(hp);
  1237. { save section type for next loop, must be done before EndFileLineInfo
  1238. because that changes the section to sec_code }
  1239. startsectype:=objectdata.currsec.sectype;
  1240. objectdata.afterwrite;
  1241. { leave if errors have occured }
  1242. if errorcount>0 then
  1243. exit;
  1244. { write the current objectfile }
  1245. objectoutput.writeobjectfile(objectdata);
  1246. objectdata.free;
  1247. objectdata:=nil;
  1248. { reset the used symbols back, must be after the .o has been
  1249. written }
  1250. objectlibrary.UsedAsmsymbolListReset;
  1251. objectlibrary.DestroyUsedAsmsymbolList;
  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. while assigned(hp) and
  1264. (Tai(hp).typ in [ait_marker,ait_comment,ait_section,ait_cutobject]) do
  1265. begin
  1266. if Tai(hp).typ=ait_section then
  1267. startsectype:=Tai_section(hp).sectype
  1268. else if (Tai(hp).typ=ait_cutobject) then
  1269. place:=Tai_cutobject(hp).place;
  1270. hp:=Tai(hp.next);
  1271. end;
  1272. { there is a problem if startsectype is sec_none !! PM }
  1273. if startsectype=sec_none then
  1274. startsectype:=sec_code;
  1275. if not MaybeNextList(hp) then
  1276. break;
  1277. { start next objectfile }
  1278. NextSmartName(place);
  1279. objectdata:=objectoutput.newobjectdata(Objfile);
  1280. end;
  1281. end;
  1282. procedure TInternalAssembler.MakeObject;
  1283. var to_do:set of Tasmlist;
  1284. i:Tasmlist;
  1285. procedure addlist(p:TAAsmoutput);
  1286. begin
  1287. inc(lists);
  1288. list[lists]:=p;
  1289. end;
  1290. begin
  1291. to_do:=[low(Tasmlist)..high(Tasmlist)];
  1292. if usedeffileforexports then
  1293. exclude(to_do,al_exports);
  1294. {$warning TODO internal writer support for dwarf}
  1295. exclude(to_do,al_dwarf);
  1296. if not(tf_section_threadvars in target_info.flags) then
  1297. exclude(to_do,al_threadvars);
  1298. for i:=low(Tasmlist) to high(Tasmlist) do
  1299. if (i in to_do) and (asmlist[i]<>nil) then
  1300. addlist(asmlist[i]);
  1301. if SmartAsm then
  1302. writetreesmart
  1303. else
  1304. writetree;
  1305. end;
  1306. {*****************************************************************************
  1307. Generate Assembler Files Main Procedure
  1308. *****************************************************************************}
  1309. Procedure GenerateAsm(smart:boolean);
  1310. var
  1311. a : TAssembler;
  1312. begin
  1313. if not assigned(CAssembler[target_asm.id]) then
  1314. Message(asmw_f_assembler_output_not_supported);
  1315. a:=CAssembler[target_asm.id].Create(smart);
  1316. a.MakeObject;
  1317. a.Free;
  1318. end;
  1319. Procedure OnlyAsm;
  1320. var
  1321. a : TExternalAssembler;
  1322. begin
  1323. a:=TExternalAssembler.Create(false);
  1324. a.DoAssemble;
  1325. a.Free;
  1326. end;
  1327. {*****************************************************************************
  1328. Init/Done
  1329. *****************************************************************************}
  1330. procedure RegisterAssembler(const r:tasminfo;c:TAssemblerClass);
  1331. var
  1332. t : tasm;
  1333. begin
  1334. t:=r.id;
  1335. if assigned(asminfos[t]) then
  1336. writeln('Warning: Assembler is already registered!')
  1337. else
  1338. Getmem(asminfos[t],sizeof(tasminfo));
  1339. asminfos[t]^:=r;
  1340. CAssembler[t]:=c;
  1341. end;
  1342. procedure InitAssembler;
  1343. begin
  1344. end;
  1345. procedure DoneAssembler;
  1346. begin
  1347. end;
  1348. end.