assemble.pas 46 KB

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