2
0

assemble.pas 45 KB

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