assemble.pas 45 KB

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