assemble.pas 45 KB

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