assemble.pas 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667
  1. {
  2. $Id$
  3. Copyright (c) 1998-2004 by Peter Vreman
  4. This unit handles the assemblerfile write and assembler calls of FPC
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. {# @abstract(This unit handles the assembler file write and assembler calls of FPC)
  19. Handles the calls to the actual external assemblers, as well as the generation
  20. of object files for smart linking. Also contains the base class for writing
  21. the assembler statements to file.
  22. }
  23. unit assemble;
  24. {$i fpcdefs.inc}
  25. interface
  26. uses
  27. {$ifdef Delphi}
  28. sysutils,
  29. dmisc,
  30. {$else Delphi}
  31. strings,
  32. dos,
  33. {$endif Delphi}
  34. systems,globtype,globals,aasmbase,aasmtai,ogbase;
  35. const
  36. { maximum of aasmoutput lists there will be }
  37. maxoutputlists = 10;
  38. { buffer size for writing the .s file }
  39. AsmOutSize=32768;
  40. type
  41. TAssembler=class(TAbstractAssembler)
  42. public
  43. {filenames}
  44. path : pathstr;
  45. name : namestr;
  46. asmfile, { current .s and .o file }
  47. objfile : string;
  48. ppufilename : string;
  49. asmprefix : string;
  50. SmartAsm : boolean;
  51. SmartFilesCount,
  52. SmartHeaderCount : longint;
  53. Constructor Create(smart:boolean);virtual;
  54. Destructor Destroy;override;
  55. procedure NextSmartName(place:tcutplace);
  56. procedure MakeObject;virtual;abstract;
  57. end;
  58. {# This is the base class which should be overriden for each each
  59. assembler writer. It is used to actually assembler a file,
  60. and write the output to the assembler file.
  61. }
  62. TExternalAssembler=class(TAssembler)
  63. private
  64. procedure CreateSmartLinkPath(const s:string);
  65. protected
  66. {outfile}
  67. AsmSize,
  68. AsmStartSize,
  69. outcnt : longint;
  70. outbuf : array[0..AsmOutSize-1] of char;
  71. outfile : file;
  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,para:string):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:TAAsmoutput);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. public
  105. Constructor Create(smart:boolean);override;
  106. procedure MakeObject;override;
  107. end;
  108. TInternalAssembler=class(TAssembler)
  109. public
  110. constructor create(smart:boolean);override;
  111. destructor destroy;override;
  112. procedure MakeObject;override;
  113. protected
  114. objectdata : TAsmObjectData;
  115. objectoutput : tobjectoutput;
  116. private
  117. { the aasmoutput lists that need to be processed }
  118. lists : byte;
  119. list : array[1..maxoutputlists] of TAAsmoutput;
  120. { current processing }
  121. currlistidx : byte;
  122. currlist : TAAsmoutput;
  123. currpass : byte;
  124. {$ifdef GDB}
  125. n_line : byte; { different types of source lines }
  126. linecount,
  127. includecount : longint;
  128. funcname : tasmsymbol;
  129. stabslastfileinfo : tfileposinfo;
  130. procedure convertstabs(p:pchar);
  131. procedure emitlineinfostabs(nidx,line : longint);
  132. procedure emitstabs(s:string);
  133. procedure WriteFileLineInfo(var fileinfo : tfileposinfo);
  134. procedure StartFileLineInfo;
  135. procedure EndFileLineInfo;
  136. {$endif}
  137. function MaybeNextList(var hp:Tai):boolean;
  138. function TreePass0(hp:Tai):Tai;
  139. function TreePass1(hp:Tai):Tai;
  140. function TreePass2(hp:Tai):Tai;
  141. procedure writetree;
  142. procedure writetreesmart;
  143. end;
  144. TAssemblerClass = class of TAssembler;
  145. Procedure GenerateAsm(smart:boolean);
  146. Procedure OnlyAsm;
  147. procedure RegisterAssembler(const r:tasminfo;c:TAssemblerClass);
  148. procedure InitAssembler;
  149. procedure DoneAssembler;
  150. Implementation
  151. uses
  152. {$ifdef hasunix}
  153. {$ifdef havelinuxrtl10}
  154. linux,
  155. {$else}
  156. unix,
  157. {$endif}
  158. {$endif}
  159. cutils,script,fmodule,verbose,
  160. cpuinfo,
  161. {$ifdef memdebug}
  162. cclasses,
  163. {$endif memdebug}
  164. {$ifdef GDB}
  165. finput,
  166. gdb,
  167. {$endif GDB}
  168. {$ifdef m68k}
  169. cpuinfo,
  170. {$endif m68k}
  171. cpubase,aasmcpu
  172. ;
  173. var
  174. CAssembler : array[tasm] of TAssemblerClass;
  175. {*****************************************************************************
  176. TAssembler
  177. *****************************************************************************}
  178. Constructor TAssembler.Create(smart:boolean);
  179. begin
  180. { load start values }
  181. asmfile:=current_module.get_asmfilename;
  182. objfile:=current_module.objfilename^;
  183. name:=Lower(current_module.modulename^);
  184. path:=current_module.outputpath^;
  185. asmprefix := current_module.asmprefix^;
  186. if not assigned(current_module.outputpath) then
  187. ppufilename := ''
  188. else
  189. ppufilename := current_module.ppufilename^;
  190. SmartAsm:=smart;
  191. SmartFilesCount:=0;
  192. SmartHeaderCount:=0;
  193. SmartLinkOFiles.Clear;
  194. end;
  195. Destructor TAssembler.Destroy;
  196. begin
  197. end;
  198. procedure TAssembler.NextSmartName(place:tcutplace);
  199. var
  200. s : string;
  201. begin
  202. inc(SmartFilesCount);
  203. if SmartFilesCount>999999 then
  204. Message(asmw_f_too_many_asm_files);
  205. case place of
  206. cut_begin :
  207. begin
  208. inc(SmartHeaderCount);
  209. s:=asmprefix+tostr(SmartHeaderCount)+'h';
  210. end;
  211. cut_normal :
  212. s:=asmprefix+tostr(SmartHeaderCount)+'s';
  213. cut_end :
  214. s:=asmprefix+tostr(SmartHeaderCount)+'t';
  215. end;
  216. AsmFile:=Path+FixFileName(s+tostr(SmartFilesCount)+target_info.asmext);
  217. ObjFile:=Path+FixFileName(s+tostr(SmartFilesCount)+target_info.objext);
  218. { insert in container so it can be cleared after the linking }
  219. SmartLinkOFiles.Insert(Objfile);
  220. end;
  221. {*****************************************************************************
  222. TExternalAssembler
  223. *****************************************************************************}
  224. Function DoPipe:boolean;
  225. begin
  226. DoPipe:=(cs_asm_pipe in aktglobalswitches) and
  227. not(cs_asm_leave in aktglobalswitches)
  228. and ((aktoutputformat in [as_gas,as_darwin]));
  229. end;
  230. Constructor TExternalAssembler.Create(smart:boolean);
  231. begin
  232. inherited Create(smart);
  233. if SmartAsm then
  234. begin
  235. path:=FixPath(path+FixFileName(name)+target_info.smartext,false);
  236. CreateSmartLinkPath(path);
  237. end;
  238. Outcnt:=0;
  239. end;
  240. procedure TExternalAssembler.CreateSmartLinkPath(const s:string);
  241. var
  242. dir : searchrec;
  243. hs : string;
  244. begin
  245. if PathExists(s) then
  246. begin
  247. { the path exists, now we clean only all the .o and .s files }
  248. { .o files }
  249. findfirst(s+source_info.dirsep+'*'+target_info.objext,anyfile,dir);
  250. while (doserror=0) do
  251. begin
  252. RemoveFile(s+source_info.dirsep+dir.name);
  253. findnext(dir);
  254. end;
  255. findclose(dir);
  256. { .s files }
  257. findfirst(s+source_info.dirsep+'*'+target_info.asmext,anyfile,dir);
  258. while (doserror=0) do
  259. begin
  260. RemoveFile(s+source_info.dirsep+dir.name);
  261. findnext(dir);
  262. end;
  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,para:string):Boolean;
  313. begin
  314. callassembler:=true;
  315. if not(cs_asm_extern in aktglobalswitches) then
  316. begin
  317. swapvectors;
  318. exec(command,para);
  319. swapvectors;
  320. if (doserror<>0) then
  321. begin
  322. Message1(exec_e_cant_call_assembler,tostr(doserror));
  323. aktglobalswitches:=aktglobalswitches+[cs_asm_extern];
  324. callassembler:=false;
  325. end
  326. else
  327. if (dosexitcode<>0) then
  328. begin
  329. Message1(exec_e_error_while_assembling,tostr(dosexitcode));
  330. callassembler:=false;
  331. end;
  332. end
  333. else
  334. AsmRes.AddAsmCommand(command,para,name);
  335. end;
  336. procedure TExternalAssembler.RemoveAsm;
  337. var
  338. g : file;
  339. begin
  340. if cs_asm_leave in aktglobalswitches then
  341. exit;
  342. if cs_asm_extern in aktglobalswitches then
  343. AsmRes.AddDeleteCommand(AsmFile)
  344. else
  345. begin
  346. assign(g,AsmFile);
  347. {$I-}
  348. erase(g);
  349. {$I+}
  350. if ioresult<>0 then;
  351. end;
  352. end;
  353. Function TExternalAssembler.DoAssemble:boolean;
  354. var
  355. s : string;
  356. begin
  357. DoAssemble:=true;
  358. if DoPipe then
  359. exit;
  360. if not(cs_asm_extern in aktglobalswitches) then
  361. begin
  362. if SmartAsm then
  363. begin
  364. if (SmartFilesCount<=1) then
  365. Message1(exec_i_assembling_smart,name);
  366. end
  367. else
  368. Message1(exec_i_assembling,name);
  369. end;
  370. s:=target_asm.asmcmd;
  371. {$ifdef m68k}
  372. if aktoptprocessor = MC68020 then
  373. s:='-m68020 '+s
  374. else
  375. s:='-m68000 '+s;
  376. {$endif}
  377. if (cs_link_on_target in aktglobalswitches) then
  378. begin
  379. Replace(s,'$ASM',ScriptFixFileName(AsmFile));
  380. Replace(s,'$OBJ',ScriptFixFileName(ObjFile));
  381. end
  382. else
  383. begin
  384. Replace(s,'$ASM',AsmFile);
  385. Replace(s,'$OBJ',ObjFile);
  386. end;
  387. if CallAssembler(FindAssembler,s) then
  388. RemoveAsm
  389. else
  390. begin
  391. DoAssemble:=false;
  392. GenerateError;
  393. end;
  394. end;
  395. Procedure TExternalAssembler.AsmFlush;
  396. begin
  397. if outcnt>0 then
  398. begin
  399. BlockWrite(outfile,outbuf,outcnt);
  400. outcnt:=0;
  401. end;
  402. end;
  403. Procedure TExternalAssembler.AsmClear;
  404. begin
  405. outcnt:=0;
  406. end;
  407. Procedure TExternalAssembler.AsmWrite(const s:string);
  408. begin
  409. if OutCnt+length(s)>=AsmOutSize then
  410. AsmFlush;
  411. Move(s[1],OutBuf[OutCnt],length(s));
  412. inc(OutCnt,length(s));
  413. inc(AsmSize,length(s));
  414. end;
  415. Procedure TExternalAssembler.AsmWriteLn(const s:string);
  416. begin
  417. AsmWrite(s);
  418. AsmLn;
  419. end;
  420. Procedure TExternalAssembler.AsmWritePChar(p:pchar);
  421. var
  422. i,j : longint;
  423. begin
  424. i:=StrLen(p);
  425. j:=i;
  426. while j>0 do
  427. begin
  428. i:=min(j,AsmOutSize);
  429. if OutCnt+i>=AsmOutSize then
  430. AsmFlush;
  431. Move(p[0],OutBuf[OutCnt],i);
  432. inc(OutCnt,i);
  433. inc(AsmSize,i);
  434. dec(j,i);
  435. p:=pchar(@p[i]);
  436. end;
  437. end;
  438. Procedure TExternalAssembler.AsmLn;
  439. begin
  440. if OutCnt>=AsmOutSize-2 then
  441. AsmFlush;
  442. if (cs_link_on_target in aktglobalswitches) then
  443. begin
  444. OutBuf[OutCnt]:=target_info.newline[1];
  445. inc(OutCnt);
  446. inc(AsmSize);
  447. if length(target_info.newline)>1 then
  448. begin
  449. OutBuf[OutCnt]:=target_info.newline[2];
  450. inc(OutCnt);
  451. inc(AsmSize);
  452. end;
  453. end
  454. else
  455. begin
  456. OutBuf[OutCnt]:=source_info.newline[1];
  457. inc(OutCnt);
  458. inc(AsmSize);
  459. if length(source_info.newline)>1 then
  460. begin
  461. OutBuf[OutCnt]:=source_info.newline[2];
  462. inc(OutCnt);
  463. inc(AsmSize);
  464. end;
  465. end;
  466. end;
  467. procedure TExternalAssembler.AsmCreate(Aplace:tcutplace);
  468. begin
  469. if SmartAsm then
  470. NextSmartName(Aplace);
  471. {$ifdef hasunix}
  472. if DoPipe then
  473. begin
  474. Message1(exec_i_assembling_pipe,asmfile);
  475. POpen(outfile,'as -o '+objfile,'W');
  476. end
  477. else
  478. {$endif}
  479. begin
  480. Assign(outfile,asmfile);
  481. {$I-}
  482. Rewrite(outfile,1);
  483. {$I+}
  484. if ioresult<>0 then
  485. Message1(exec_d_cant_create_asmfile,asmfile);
  486. end;
  487. outcnt:=0;
  488. AsmSize:=0;
  489. AsmStartSize:=0;
  490. end;
  491. procedure TExternalAssembler.AsmClose;
  492. var
  493. f : file;
  494. l : 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. getftime(f,l);
  516. close(f);
  517. reset(outfile,1);
  518. setftime(outfile,l);
  519. end;
  520. end;
  521. close(outfile);
  522. end;
  523. end;
  524. procedure TExternalAssembler.WriteTree(p:TAAsmoutput);
  525. begin
  526. end;
  527. procedure TExternalAssembler.WriteAsmList;
  528. begin
  529. end;
  530. procedure TExternalAssembler.MakeObject;
  531. begin
  532. AsmCreate(cut_normal);
  533. WriteAsmList;
  534. AsmClose;
  535. DoAssemble;
  536. end;
  537. {*****************************************************************************
  538. TInternalAssembler
  539. *****************************************************************************}
  540. constructor TInternalAssembler.create(smart:boolean);
  541. begin
  542. inherited create(smart);
  543. objectoutput:=nil;
  544. objectdata:=nil;
  545. SmartAsm:=smart;
  546. currpass:=0;
  547. end;
  548. destructor TInternalAssembler.destroy;
  549. {$ifdef MEMDEBUG}
  550. var
  551. d : tmemdebug;
  552. {$endif}
  553. begin
  554. {$ifdef MEMDEBUG}
  555. d := tmemdebug.create(name+' - agbin');
  556. {$endif}
  557. objectdata.free;
  558. objectoutput.free;
  559. {$ifdef MEMDEBUG}
  560. d.free;
  561. {$endif}
  562. end;
  563. {$ifdef GDB}
  564. procedure TInternalAssembler.convertstabs(p:pchar);
  565. var
  566. ofs,
  567. nidx,nother,ii,i,line,j : longint;
  568. code : integer;
  569. hp : pchar;
  570. reloc : boolean;
  571. ps : tasmsymbol;
  572. s : string;
  573. begin
  574. ofs:=0;
  575. reloc:=true;
  576. ps:=nil;
  577. if p[0]='"' then
  578. begin
  579. i:=1;
  580. { we can have \" inside the string !! PM }
  581. while not ((p[i]='"') and (p[i-1]<>'\')) do
  582. inc(i);
  583. p[i]:=#0;
  584. ii:=i;
  585. hp:=@p[1];
  586. s:=StrPas(@P[i+2]);
  587. end
  588. else
  589. begin
  590. hp:=nil;
  591. s:=StrPas(P);
  592. i:=-2; {needed below (PM) }
  593. end;
  594. { When in pass 1 then only alloc and leave }
  595. if currpass=1 then
  596. begin
  597. objectdata.allocstabs(hp);
  598. if assigned(hp) then
  599. p[i]:='"';
  600. exit;
  601. end;
  602. { Parse the rest of the stabs }
  603. if s='' then
  604. internalerror(33000);
  605. j:=pos(',',s);
  606. if j=0 then
  607. internalerror(33001);
  608. Val(Copy(s,1,j-1),nidx,code);
  609. if code<>0 then
  610. internalerror(33002);
  611. i:=i+2+j;
  612. Delete(s,1,j);
  613. j:=pos(',',s);
  614. if (j=0) then
  615. internalerror(33003);
  616. Val(Copy(s,1,j-1),nother,code);
  617. if code<>0 then
  618. internalerror(33004);
  619. i:=i+j;
  620. Delete(s,1,j);
  621. j:=pos(',',s);
  622. if j=0 then
  623. begin
  624. j:=256;
  625. ofs:=-1;
  626. end;
  627. Val(Copy(s,1,j-1),line,code);
  628. if code<>0 then
  629. internalerror(33005);
  630. if ofs=0 then
  631. begin
  632. Delete(s,1,j);
  633. i:=i+j;
  634. Val(s,ofs,code);
  635. if code=0 then
  636. reloc:=false
  637. else
  638. begin
  639. ofs:=0;
  640. s:=strpas(@p[i]);
  641. { handle asmsymbol or
  642. asmsymbol - asmsymbol }
  643. j:=pos(' ',s);
  644. if j=0 then
  645. j:=pos('-',s);
  646. { also try to handle
  647. asmsymbol + constant
  648. or
  649. asmsymbol - constant }
  650. if j=0 then
  651. j:=pos('+',s);
  652. if j<>0 then
  653. begin
  654. Val(Copy(s,j+1,255),ofs,code);
  655. if code<>0 then
  656. ofs:=0
  657. else
  658. { constant reading successful,
  659. avoid further treatment by
  660. setting s[j] to '+' }
  661. s[j]:='+';
  662. end
  663. else
  664. { single asmsymbol }
  665. j:=256;
  666. { the symbol can be external
  667. so we must use newasmsymbol and
  668. not getasmsymbol !! PM }
  669. ps:=objectlibrary.newasmsymbol(copy(s,1,j-1),AB_EXTERNAL,AT_NONE);
  670. if not assigned(ps) then
  671. internalerror(33006)
  672. else
  673. begin
  674. ofs:=ofs+ps.address;
  675. reloc:=true;
  676. objectlibrary.UsedAsmSymbolListInsert(ps);
  677. end;
  678. if (j<256) and (s[j]<>'+') then
  679. begin
  680. i:=i+j;
  681. s:=strpas(@p[i]);
  682. if (s<>'') and (s[1]=' ') then
  683. begin
  684. j:=0;
  685. while (s[j+1]=' ') do
  686. inc(j);
  687. i:=i+j;
  688. s:=strpas(@p[i]);
  689. end;
  690. ps:=objectlibrary.getasmsymbol(s);
  691. if not assigned(ps) then
  692. internalerror(33007)
  693. else
  694. begin
  695. if ps.section<>objectdata.currsec then
  696. internalerror(33008);
  697. ofs:=ofs-ps.address;
  698. reloc:=false;
  699. objectlibrary.UsedAsmSymbolListInsert(ps);
  700. end;
  701. end;
  702. end;
  703. end;
  704. { external bss need speical handling (PM) }
  705. if assigned(ps) and (ps.section=nil) then
  706. begin
  707. if currpass=2 then
  708. begin
  709. objectdata.writesymbol(ps);
  710. objectoutput.exportsymbol(ps);
  711. end;
  712. objectdata.writeSymStabs(ofs,hp,ps,nidx,nother,line,reloc)
  713. end
  714. else
  715. objectdata.writeStabs(ofs,hp,nidx,nother,line,reloc);
  716. if assigned(hp) then
  717. p[ii]:='"';
  718. end;
  719. procedure TInternalAssembler.emitlineinfostabs(nidx,line : longint);
  720. begin
  721. if currpass=1 then
  722. begin
  723. objectdata.allocstabs(nil);
  724. exit;
  725. end;
  726. if (nidx=n_textline) and assigned(funcname) and
  727. (target_info.use_function_relative_addresses) then
  728. objectdata.writeStabs(objectdata.currsec.datasize-funcname.address,nil,nidx,0,line,false)
  729. else
  730. objectdata.writeStabs(objectdata.currsec.datasize,nil,nidx,0,line,true);
  731. end;
  732. procedure TInternalAssembler.emitstabs(s:string);
  733. begin
  734. s:=s+#0;
  735. ConvertStabs(@s[1]);
  736. end;
  737. procedure TInternalAssembler.WriteFileLineInfo(var fileinfo : tfileposinfo);
  738. var
  739. curr_n : byte;
  740. hp : tasmsymbol;
  741. infile : tinputfile;
  742. begin
  743. if not ((cs_debuginfo in aktmoduleswitches) or
  744. (cs_gdb_lineinfo in aktglobalswitches)) then
  745. exit;
  746. { file changed ? (must be before line info) }
  747. if (fileinfo.fileindex<>0) and
  748. (stabslastfileinfo.fileindex<>fileinfo.fileindex) then
  749. begin
  750. infile:=current_module.sourcefiles.get_file(fileinfo.fileindex);
  751. if assigned(infile) then
  752. begin
  753. if includecount=0 then
  754. curr_n:=n_sourcefile
  755. else
  756. curr_n:=n_includefile;
  757. { get symbol for this includefile }
  758. hp:=objectlibrary.newasmsymbol('Ltext'+ToStr(IncludeCount),AB_LOCAL,AT_FUNCTION);
  759. if currpass=1 then
  760. begin
  761. objectdata.allocsymbol(currpass,hp,0);
  762. objectlibrary.UsedAsmSymbolListInsert(hp);
  763. end
  764. else
  765. objectdata.writesymbol(hp);
  766. { emit stabs }
  767. if (infile.path^<>'') then
  768. EmitStabs('"'+BsToSlash(FixPath(infile.path^,false))+'",'+tostr(curr_n)+
  769. ',0,0,Ltext'+ToStr(IncludeCount));
  770. EmitStabs('"'+FixFileName(infile.name^)+'",'+tostr(curr_n)+
  771. ',0,0,Ltext'+ToStr(IncludeCount));
  772. inc(includecount);
  773. { force new line info }
  774. stabslastfileinfo.line:=-1;
  775. end;
  776. end;
  777. { line changed ? }
  778. if (stabslastfileinfo.line<>fileinfo.line) and (fileinfo.line<>0) then
  779. emitlineinfostabs(n_line,fileinfo.line);
  780. stabslastfileinfo:=fileinfo;
  781. end;
  782. procedure TInternalAssembler.StartFileLineInfo;
  783. var
  784. fileinfo : tfileposinfo;
  785. begin
  786. FillChar(stabslastfileinfo,sizeof(stabslastfileinfo),0);
  787. n_line:=n_bssline;
  788. funcname:=nil;
  789. linecount:=1;
  790. includecount:=0;
  791. fileinfo.fileindex:=1;
  792. fileinfo.line:=1;
  793. WriteFileLineInfo(fileinfo);
  794. end;
  795. procedure TInternalAssembler.EndFileLineInfo;
  796. var
  797. hp : tasmsymbol;
  798. begin
  799. if not ((cs_debuginfo in aktmoduleswitches) or
  800. (cs_gdb_lineinfo in aktglobalswitches)) then
  801. exit;
  802. objectdata.createsection(sec_code,'',0,[]);
  803. hp:=objectlibrary.newasmsymbol('Letext',AB_LOCAL,AT_FUNCTION);
  804. if currpass=1 then
  805. begin
  806. objectdata.allocsymbol(currpass,hp,0);
  807. objectlibrary.UsedAsmSymbolListInsert(hp);
  808. end
  809. else
  810. objectdata.writesymbol(hp);
  811. EmitStabs('"",'+tostr(n_sourcefile)+',0,0,Letext');
  812. end;
  813. {$endif GDB}
  814. function TInternalAssembler.MaybeNextList(var hp:Tai):boolean;
  815. begin
  816. { maybe end of list }
  817. while not assigned(hp) do
  818. begin
  819. if currlistidx<lists then
  820. begin
  821. inc(currlistidx);
  822. currlist:=list[currlistidx];
  823. hp:=Tai(currList.first);
  824. end
  825. else
  826. begin
  827. MaybeNextList:=false;
  828. exit;
  829. end;
  830. end;
  831. MaybeNextList:=true;
  832. end;
  833. function TInternalAssembler.TreePass0(hp:Tai):Tai;
  834. var
  835. l : longint;
  836. begin
  837. while assigned(hp) do
  838. begin
  839. case hp.typ of
  840. ait_align :
  841. begin
  842. { always use the maximum fillsize in this pass to avoid possible
  843. short jumps to become out of range }
  844. Tai_align(hp).fillsize:=Tai_align(hp).aligntype;
  845. objectdata.alloc(Tai_align(hp).fillsize);
  846. end;
  847. ait_datablock :
  848. begin
  849. l:=used_align(size_2_align(Tai_datablock(hp).size),0,objectdata.currsec.addralign);
  850. if SmartAsm or (not Tai_datablock(hp).is_global) then
  851. begin
  852. objectdata.allocalign(l);
  853. objectdata.alloc(Tai_datablock(hp).size);
  854. end;
  855. end;
  856. ait_real_80bit :
  857. objectdata.alloc(10);
  858. ait_real_64bit :
  859. objectdata.alloc(8);
  860. ait_real_32bit :
  861. objectdata.alloc(4);
  862. ait_comp_64bit :
  863. objectdata.alloc(8);
  864. ait_const_64bit,
  865. ait_const_32bit,
  866. ait_const_16bit,
  867. ait_const_8bit,
  868. ait_const_rva_symbol,
  869. ait_const_indirect_symbol :
  870. objectdata.alloc(tai_const(hp).size);
  871. ait_section:
  872. begin
  873. objectdata.CreateSection(Tai_section(hp).sectype,Tai_section(hp).name^,Tai_section(hp).secalign,[]);
  874. Tai_section(hp).sec:=objectdata.CurrSec;
  875. end;
  876. ait_symbol :
  877. objectdata.allocsymbol(currpass,Tai_symbol(hp).sym,0);
  878. ait_label :
  879. objectdata.allocsymbol(currpass,Tai_label(hp).l,0);
  880. ait_string :
  881. objectdata.alloc(Tai_string(hp).len);
  882. ait_instruction :
  883. begin
  884. {$ifdef i386}
  885. {$ifndef NOAG386BIN}
  886. { reset instructions which could change in pass 2 }
  887. Taicpu(hp).resetpass2;
  888. objectdata.alloc(Taicpu(hp).Pass1(objectdata.currsec.datasize));
  889. {$endif NOAG386BIN}
  890. {$endif i386}
  891. end;
  892. ait_cutobject :
  893. if SmartAsm then
  894. break;
  895. end;
  896. hp:=Tai(hp.next);
  897. end;
  898. TreePass0:=hp;
  899. end;
  900. function TInternalAssembler.TreePass1(hp:Tai):Tai;
  901. var
  902. InlineLevel,
  903. l : longint;
  904. {$ifdef i386}
  905. {$ifndef NOAG386BIN}
  906. i : longint;
  907. {$endif NOAG386BIN}
  908. {$endif i386}
  909. begin
  910. inlinelevel:=0;
  911. while assigned(hp) do
  912. begin
  913. {$ifdef GDB}
  914. { write stabs, no line info for inlined code }
  915. if (inlinelevel=0) and
  916. ((cs_debuginfo in aktmoduleswitches) or
  917. (cs_gdb_lineinfo in aktglobalswitches)) then
  918. begin
  919. if (objectdata.currsec<>nil) and
  920. not(hp.typ in SkipLineInfo) then
  921. WriteFileLineInfo(tailineinfo(hp).fileinfo);
  922. end;
  923. {$endif GDB}
  924. case hp.typ of
  925. ait_align :
  926. begin
  927. { here we must determine the fillsize which is used in pass2 }
  928. Tai_align(hp).fillsize:=align(objectdata.currsec.datasize,Tai_align(hp).aligntype)-
  929. objectdata.currsec.datasize;
  930. objectdata.alloc(Tai_align(hp).fillsize);
  931. end;
  932. ait_datablock :
  933. begin
  934. if objectdata.currsec.sectype<>sec_bss then
  935. Message(asmw_e_alloc_data_only_in_bss);
  936. l:=used_align(size_2_align(Tai_datablock(hp).size),0,objectdata.currsec.addralign);
  937. if Tai_datablock(hp).is_global and
  938. not SmartAsm then
  939. begin
  940. objectdata.allocsymbol(currpass,Tai_datablock(hp).sym,Tai_datablock(hp).size);
  941. { force to be common/external, must be after setaddress as that would
  942. set it to AB_GLOBAL }
  943. Tai_datablock(hp).sym.currbind:=AB_COMMON;
  944. end
  945. else
  946. begin
  947. objectdata.allocalign(l);
  948. objectdata.allocsymbol(currpass,Tai_datablock(hp).sym,Tai_datablock(hp).size);
  949. objectdata.alloc(Tai_datablock(hp).size);
  950. end;
  951. objectlibrary.UsedAsmSymbolListInsert(Tai_datablock(hp).sym);
  952. end;
  953. ait_real_80bit :
  954. objectdata.alloc(10);
  955. ait_real_64bit :
  956. objectdata.alloc(8);
  957. ait_real_32bit :
  958. objectdata.alloc(4);
  959. ait_comp_64bit :
  960. objectdata.alloc(8);
  961. ait_const_64bit,
  962. ait_const_32bit,
  963. ait_const_16bit,
  964. ait_const_8bit,
  965. ait_const_rva_symbol,
  966. ait_const_indirect_symbol :
  967. begin
  968. objectdata.alloc(tai_const(hp).size);
  969. if assigned(Tai_const(hp).sym) then
  970. objectlibrary.UsedAsmSymbolListInsert(Tai_const(hp).sym);
  971. if assigned(Tai_const(hp).endsym) then
  972. objectlibrary.UsedAsmSymbolListInsert(Tai_const(hp).endsym);
  973. end;
  974. ait_section:
  975. begin
  976. { use cached value }
  977. objectdata.setsection(Tai_section(hp).sec);
  978. {$ifdef GDB}
  979. case Tai_section(hp).sectype of
  980. sec_code :
  981. n_line:=n_textline;
  982. sec_data :
  983. n_line:=n_dataline;
  984. sec_bss :
  985. n_line:=n_bssline;
  986. else
  987. n_line:=n_dataline;
  988. end;
  989. stabslastfileinfo.line:=-1;
  990. {$endif GDB}
  991. end;
  992. {$ifdef GDB}
  993. ait_stabn :
  994. begin
  995. if assigned(Tai_stabn(hp).str) then
  996. convertstabs(Tai_stabn(hp).str);
  997. end;
  998. ait_stabs :
  999. begin
  1000. if assigned(Tai_stabs(hp).str) then
  1001. convertstabs(Tai_stabs(hp).str);
  1002. end;
  1003. ait_stab_function_name :
  1004. begin
  1005. if assigned(Tai_stab_function_name(hp).str) then
  1006. begin
  1007. funcname:=objectlibrary.getasmsymbol(strpas(Tai_stab_function_name(hp).str));
  1008. objectlibrary.UsedAsmSymbolListInsert(funcname);
  1009. end
  1010. else
  1011. funcname:=nil;
  1012. end;
  1013. ait_force_line :
  1014. stabslastfileinfo.line:=0;
  1015. {$endif}
  1016. ait_symbol :
  1017. begin
  1018. objectdata.allocsymbol(currpass,Tai_symbol(hp).sym,0);
  1019. objectlibrary.UsedAsmSymbolListInsert(Tai_symbol(hp).sym);
  1020. end;
  1021. ait_symbol_end :
  1022. begin
  1023. if target_info.system in [system_i386_linux,system_i386_beos] then
  1024. begin
  1025. Tai_symbol_end(hp).sym.size:=objectdata.currsec.datasize-Tai_symbol_end(hp).sym.address;
  1026. objectlibrary.UsedAsmSymbolListInsert(Tai_symbol_end(hp).sym);
  1027. end;
  1028. end;
  1029. ait_label :
  1030. begin
  1031. objectdata.allocsymbol(currpass,Tai_label(hp).l,0);
  1032. objectlibrary.UsedAsmSymbolListInsert(Tai_label(hp).l);
  1033. end;
  1034. ait_string :
  1035. objectdata.alloc(Tai_string(hp).len);
  1036. ait_instruction :
  1037. begin
  1038. {$ifdef i386}
  1039. {$ifndef NOAG386BIN}
  1040. objectdata.alloc(Taicpu(hp).Pass1(objectdata.currsec.datasize));
  1041. { fixup the references }
  1042. for i:=1 to Taicpu(hp).ops do
  1043. begin
  1044. with Taicpu(hp).oper[i-1]^ do
  1045. begin
  1046. case typ of
  1047. top_ref :
  1048. begin
  1049. if assigned(ref^.symbol) then
  1050. objectlibrary.UsedAsmSymbolListInsert(ref^.symbol);
  1051. if assigned(ref^.relsymbol) then
  1052. objectlibrary.UsedAsmSymbolListInsert(ref^.symbol);
  1053. end;
  1054. end;
  1055. end;
  1056. end;
  1057. {$endif NOAG386BIN}
  1058. {$endif i386}
  1059. end;
  1060. ait_direct :
  1061. Message(asmw_f_direct_not_supported);
  1062. ait_cutobject :
  1063. if SmartAsm then
  1064. break;
  1065. ait_marker :
  1066. if tai_marker(hp).kind=InlineStart then
  1067. inc(InlineLevel)
  1068. else if tai_marker(hp).kind=InlineEnd then
  1069. dec(InlineLevel);
  1070. end;
  1071. hp:=Tai(hp.next);
  1072. end;
  1073. TreePass1:=hp;
  1074. end;
  1075. function TInternalAssembler.TreePass2(hp:Tai):Tai;
  1076. var
  1077. fillbuffer : tfillbuffer;
  1078. InlineLevel,
  1079. l : longint;
  1080. v : int64;
  1081. {$ifdef x86}
  1082. co : comp;
  1083. {$endif x86}
  1084. begin
  1085. inlinelevel:=0;
  1086. { main loop }
  1087. while assigned(hp) do
  1088. begin
  1089. {$ifdef GDB}
  1090. { write stabs, no line info for inlined code }
  1091. if (inlinelevel=0) and
  1092. ((cs_debuginfo in aktmoduleswitches) or
  1093. (cs_gdb_lineinfo in aktglobalswitches)) then
  1094. begin
  1095. if (objectdata.currsec<>nil) and
  1096. not(hp.typ in SkipLineInfo) then
  1097. WriteFileLineInfo(tailineinfo(hp).fileinfo);
  1098. end;
  1099. {$endif GDB}
  1100. case hp.typ of
  1101. ait_align :
  1102. begin
  1103. if objectdata.currsec.sectype=sec_bss then
  1104. objectdata.alloc(Tai_align(hp).fillsize)
  1105. else
  1106. objectdata.writebytes(Tai_align(hp).calculatefillbuf(fillbuffer)^,Tai_align(hp).fillsize);
  1107. end;
  1108. ait_section :
  1109. begin
  1110. { use cached value }
  1111. objectdata.setsection(Tai_section(hp).sec);
  1112. {$ifdef GDB}
  1113. case Tai_section(hp).sectype of
  1114. sec_code : n_line:=n_textline;
  1115. sec_data : n_line:=n_dataline;
  1116. sec_bss : n_line:=n_bssline;
  1117. else
  1118. n_line:=n_dataline;
  1119. end;
  1120. stabslastfileinfo.line:=-1;
  1121. {$endif GDB}
  1122. end;
  1123. ait_symbol :
  1124. begin
  1125. objectdata.writesymbol(Tai_symbol(hp).sym);
  1126. objectoutput.exportsymbol(Tai_symbol(hp).sym);
  1127. end;
  1128. ait_datablock :
  1129. begin
  1130. l:=used_align(size_2_align(Tai_datablock(hp).size),0,objectdata.currsec.addralign);
  1131. objectdata.writesymbol(Tai_datablock(hp).sym);
  1132. objectoutput.exportsymbol(Tai_datablock(hp).sym);
  1133. if SmartAsm or (not Tai_datablock(hp).is_global) then
  1134. begin
  1135. objectdata.allocalign(l);
  1136. objectdata.alloc(Tai_datablock(hp).size);
  1137. end;
  1138. end;
  1139. ait_real_80bit :
  1140. objectdata.writebytes(Tai_real_80bit(hp).value,10);
  1141. ait_real_64bit :
  1142. objectdata.writebytes(Tai_real_64bit(hp).value,8);
  1143. ait_real_32bit :
  1144. objectdata.writebytes(Tai_real_32bit(hp).value,4);
  1145. ait_comp_64bit :
  1146. begin
  1147. {$ifdef x86}
  1148. {$ifdef FPC}
  1149. co:=comp(Tai_comp_64bit(hp).value);
  1150. {$else}
  1151. co:=Tai_comp_64bit(hp).value;
  1152. {$endif}
  1153. objectdata.writebytes(co,8);
  1154. {$endif x86}
  1155. end;
  1156. ait_string :
  1157. objectdata.writebytes(Tai_string(hp).str^,Tai_string(hp).len);
  1158. ait_const_64bit,
  1159. ait_const_32bit,
  1160. ait_const_16bit,
  1161. ait_const_8bit :
  1162. begin
  1163. if assigned(tai_const(hp).sym) then
  1164. begin
  1165. if assigned(tai_const(hp).endsym) then
  1166. begin
  1167. if tai_const(hp).endsym.section<>tai_const(hp).sym.section then
  1168. internalerror(200404124);
  1169. v:=tai_const(hp).endsym.address-tai_const(hp).sym.address+Tai_const(hp).value;
  1170. objectdata.writebytes(v,tai_const(hp).size);
  1171. end
  1172. else
  1173. objectdata.writereloc(Tai_const(hp).value,Tai_const(hp).size,Tai_const(hp).sym,RELOC_ABSOLUTE);
  1174. end
  1175. else
  1176. objectdata.writebytes(Tai_const(hp).value,tai_const(hp).size);
  1177. end;
  1178. ait_const_rva_symbol :
  1179. objectdata.writereloc(Tai_const(hp).value,sizeof(aint),Tai_const(hp).sym,RELOC_RVA);
  1180. ait_label :
  1181. begin
  1182. objectdata.writesymbol(Tai_label(hp).l);
  1183. { exporting shouldn't be necessary as labels are local,
  1184. but it's better to be on the safe side (PFV) }
  1185. objectoutput.exportsymbol(Tai_label(hp).l);
  1186. end;
  1187. {$ifdef i386}
  1188. {$ifndef NOAG386BIN}
  1189. ait_instruction :
  1190. Taicpu(hp).Pass2(objectdata);
  1191. {$endif NOAG386BIN}
  1192. {$endif i386}
  1193. {$ifdef GDB}
  1194. ait_stabn :
  1195. convertstabs(Tai_stabn(hp).str);
  1196. ait_stabs :
  1197. convertstabs(Tai_stabs(hp).str);
  1198. ait_stab_function_name :
  1199. if assigned(Tai_stab_function_name(hp).str) then
  1200. funcname:=objectlibrary.getasmsymbol(strpas(Tai_stab_function_name(hp).str))
  1201. else
  1202. funcname:=nil;
  1203. ait_force_line :
  1204. stabslastfileinfo.line:=0;
  1205. {$endif}
  1206. ait_cutobject :
  1207. if SmartAsm then
  1208. break;
  1209. ait_marker :
  1210. if tai_marker(hp).kind=InlineStart then
  1211. inc(InlineLevel)
  1212. else if tai_marker(hp).kind=InlineEnd then
  1213. dec(InlineLevel);
  1214. end;
  1215. hp:=Tai(hp.next);
  1216. end;
  1217. TreePass2:=hp;
  1218. end;
  1219. procedure TInternalAssembler.writetree;
  1220. var
  1221. hp : Tai;
  1222. label
  1223. doexit;
  1224. begin
  1225. objectdata:=objectoutput.newobjectdata(Objfile);
  1226. { reset the asmsymbol list }
  1227. objectlibrary.CreateUsedAsmsymbolList;
  1228. { Pass 0 }
  1229. currpass:=0;
  1230. objectdata.createsection(sec_code,'',0,[]);
  1231. objectdata.beforealloc;
  1232. { start with list 1 }
  1233. currlistidx:=1;
  1234. currlist:=list[currlistidx];
  1235. hp:=Tai(currList.first);
  1236. while assigned(hp) do
  1237. begin
  1238. hp:=TreePass0(hp);
  1239. MaybeNextList(hp);
  1240. end;
  1241. objectdata.afteralloc;
  1242. { leave if errors have occured }
  1243. if errorcount>0 then
  1244. goto doexit;
  1245. { Pass 1 }
  1246. currpass:=1;
  1247. objectdata.resetsections;
  1248. objectdata.beforealloc;
  1249. objectdata.createsection(sec_code,'',0,[]);
  1250. {$ifdef GDB}
  1251. StartFileLineInfo;
  1252. {$endif GDB}
  1253. { start with list 1 }
  1254. currlistidx:=1;
  1255. currlist:=list[currlistidx];
  1256. hp:=Tai(currList.first);
  1257. while assigned(hp) do
  1258. begin
  1259. hp:=TreePass1(hp);
  1260. MaybeNextList(hp);
  1261. end;
  1262. {$ifdef GDB}
  1263. EndFileLineInfo;
  1264. {$endif GDB}
  1265. objectdata.afteralloc;
  1266. { check for undefined labels and reset }
  1267. objectlibrary.UsedAsmSymbolListCheckUndefined;
  1268. { leave if errors have occured }
  1269. if errorcount>0 then
  1270. goto doexit;
  1271. { Pass 2 }
  1272. currpass:=2;
  1273. objectdata.resetsections;
  1274. objectdata.beforewrite;
  1275. objectdata.createsection(sec_code,'',0,[]);
  1276. {$ifdef GDB}
  1277. StartFileLineInfo;
  1278. {$endif GDB}
  1279. { start with list 1 }
  1280. currlistidx:=1;
  1281. currlist:=list[currlistidx];
  1282. hp:=Tai(currList.first);
  1283. while assigned(hp) do
  1284. begin
  1285. hp:=TreePass2(hp);
  1286. MaybeNextList(hp);
  1287. end;
  1288. {$ifdef GDB}
  1289. EndFileLineInfo;
  1290. {$endif GDB}
  1291. objectdata.afterwrite;
  1292. { don't write the .o file if errors have occured }
  1293. if errorcount=0 then
  1294. begin
  1295. { write objectfile }
  1296. objectoutput.startobjectfile(ObjFile);
  1297. objectoutput.writeobjectfile(objectdata);
  1298. objectdata.free;
  1299. objectdata:=nil;
  1300. end;
  1301. doexit:
  1302. { reset the used symbols back, must be after the .o has been
  1303. written }
  1304. objectlibrary.UsedAsmsymbolListReset;
  1305. objectlibrary.DestroyUsedAsmsymbolList;
  1306. end;
  1307. procedure TInternalAssembler.writetreesmart;
  1308. var
  1309. hp : Tai;
  1310. startsectype : TAsmSectionType;
  1311. place: tcutplace;
  1312. begin
  1313. NextSmartName(cut_normal);
  1314. objectdata:=objectoutput.newobjectdata(Objfile);
  1315. startsectype:=sec_code;
  1316. { start with list 1 }
  1317. currlistidx:=1;
  1318. currlist:=list[currlistidx];
  1319. hp:=Tai(currList.first);
  1320. while assigned(hp) do
  1321. begin
  1322. { reset the asmsymbol list }
  1323. objectlibrary.CreateUsedAsmSymbolList;
  1324. { Pass 0 }
  1325. currpass:=0;
  1326. objectdata.resetsections;
  1327. objectdata.beforealloc;
  1328. objectdata.createsection(startsectype,'',0,[]);
  1329. TreePass0(hp);
  1330. objectdata.afteralloc;
  1331. { leave if errors have occured }
  1332. if errorcount>0 then
  1333. exit;
  1334. { Pass 1 }
  1335. currpass:=1;
  1336. objectdata.resetsections;
  1337. objectdata.beforealloc;
  1338. objectdata.createsection(startsectype,'',0,[]);
  1339. {$ifdef GDB}
  1340. StartFileLineInfo;
  1341. {$endif GDB}
  1342. TreePass1(hp);
  1343. {$ifdef GDB}
  1344. EndFileLineInfo;
  1345. {$endif GDB}
  1346. objectdata.afteralloc;
  1347. { check for undefined labels }
  1348. objectlibrary.UsedAsmSymbolListCheckUndefined;
  1349. { leave if errors have occured }
  1350. if errorcount>0 then
  1351. exit;
  1352. { Pass 2 }
  1353. currpass:=2;
  1354. objectoutput.startobjectfile(Objfile);
  1355. objectdata.resetsections;
  1356. objectdata.beforewrite;
  1357. objectdata.createsection(startsectype,'',0,[]);
  1358. {$ifdef GDB}
  1359. StartFileLineInfo;
  1360. {$endif GDB}
  1361. hp:=TreePass2(hp);
  1362. { save section type for next loop, must be done before EndFileLineInfo
  1363. because that changes the section to sec_code }
  1364. startsectype:=objectdata.currsec.sectype;
  1365. {$ifdef GDB}
  1366. EndFileLineInfo;
  1367. {$endif GDB}
  1368. objectdata.afterwrite;
  1369. { leave if errors have occured }
  1370. if errorcount>0 then
  1371. exit;
  1372. { write the current objectfile }
  1373. objectoutput.writeobjectfile(objectdata);
  1374. objectdata.free;
  1375. objectdata:=nil;
  1376. { reset the used symbols back, must be after the .o has been
  1377. written }
  1378. objectlibrary.UsedAsmsymbolListReset;
  1379. objectlibrary.DestroyUsedAsmsymbolList;
  1380. { end of lists? }
  1381. if not MaybeNextList(hp) then
  1382. break;
  1383. { we will start a new objectfile so reset everything }
  1384. { The place can still change in the next while loop, so don't init }
  1385. { the writer yet (JM) }
  1386. if (hp.typ=ait_cutobject) then
  1387. place := Tai_cutobject(hp).place
  1388. else
  1389. place := cut_normal;
  1390. { avoid empty files }
  1391. while assigned(hp) and
  1392. (Tai(hp).typ in [ait_marker,ait_comment,ait_section,ait_cutobject]) do
  1393. begin
  1394. if Tai(hp).typ=ait_section then
  1395. startsectype:=Tai_section(hp).sectype
  1396. else if (Tai(hp).typ=ait_cutobject) then
  1397. place:=Tai_cutobject(hp).place;
  1398. hp:=Tai(hp.next);
  1399. end;
  1400. { there is a problem if startsectype is sec_none !! PM }
  1401. if startsectype=sec_none then
  1402. startsectype:=sec_code;
  1403. if not MaybeNextList(hp) then
  1404. break;
  1405. { start next objectfile }
  1406. NextSmartName(place);
  1407. objectdata:=objectoutput.newobjectdata(Objfile);
  1408. end;
  1409. end;
  1410. procedure TInternalAssembler.MakeObject;
  1411. procedure addlist(p:TAAsmoutput);
  1412. begin
  1413. inc(lists);
  1414. list[lists]:=p;
  1415. end;
  1416. begin
  1417. if cs_debuginfo in aktmoduleswitches then
  1418. addlist(debuglist);
  1419. addlist(codesegment);
  1420. addlist(datasegment);
  1421. addlist(consts);
  1422. addlist(rttilist);
  1423. addlist(picdata);
  1424. if assigned(resourcestringlist) then
  1425. addlist(resourcestringlist);
  1426. addlist(bsssegment);
  1427. if assigned(importssection) then
  1428. addlist(importssection);
  1429. if assigned(exportssection) and not UseDeffileForExports then
  1430. addlist(exportssection);
  1431. if assigned(resourcesection) then
  1432. addlist(resourcesection);
  1433. {$warning TODO internal writer support for dwarf}
  1434. {if assigned(dwarflist) then
  1435. addlist(dwarflist);}
  1436. if SmartAsm then
  1437. writetreesmart
  1438. else
  1439. writetree;
  1440. end;
  1441. {*****************************************************************************
  1442. Generate Assembler Files Main Procedure
  1443. *****************************************************************************}
  1444. Procedure GenerateAsm(smart:boolean);
  1445. var
  1446. a : TAssembler;
  1447. begin
  1448. if not assigned(CAssembler[target_asm.id]) then
  1449. Message(asmw_f_assembler_output_not_supported);
  1450. a:=CAssembler[target_asm.id].Create(smart);
  1451. a.MakeObject;
  1452. a.Free;
  1453. end;
  1454. Procedure OnlyAsm;
  1455. var
  1456. a : TExternalAssembler;
  1457. begin
  1458. a:=TExternalAssembler.Create(false);
  1459. a.DoAssemble;
  1460. a.Free;
  1461. end;
  1462. {*****************************************************************************
  1463. Init/Done
  1464. *****************************************************************************}
  1465. procedure RegisterAssembler(const r:tasminfo;c:TAssemblerClass);
  1466. var
  1467. t : tasm;
  1468. begin
  1469. t:=r.id;
  1470. if assigned(asminfos[t]) then
  1471. writeln('Warning: Assembler is already registered!')
  1472. else
  1473. Getmem(asminfos[t],sizeof(tasminfo));
  1474. asminfos[t]^:=r;
  1475. CAssembler[t]:=c;
  1476. end;
  1477. procedure InitAssembler;
  1478. begin
  1479. { target_asm is already set by readarguments }
  1480. initoutputformat:=target_asm.id;
  1481. aktoutputformat:=target_asm.id;
  1482. end;
  1483. procedure DoneAssembler;
  1484. begin
  1485. end;
  1486. end.
  1487. {
  1488. $Log$
  1489. Revision 1.74 2004-08-27 20:53:52 peter
  1490. don't lowercase filenames in stabs
  1491. Revision 1.73 2004/08/25 15:55:32 peter
  1492. * fixed win32 that was broken by previous fix
  1493. Revision 1.72 2004/08/24 19:31:44 hajny
  1494. * binary writer fix for GO32v2 from Peter
  1495. Revision 1.71 2004/07/01 18:28:54 jonas
  1496. + detect assembler errors when using -ap
  1497. Revision 1.70 2004/07/01 15:42:53 peter
  1498. * fix wrong calculation of .bss section
  1499. Revision 1.69 2004/06/20 08:55:28 florian
  1500. * logs truncated
  1501. Revision 1.68 2004/06/16 20:07:06 florian
  1502. * dwarf branch merged
  1503. Revision 1.67 2004/05/21 22:43:36 peter
  1504. * set correct n_line type when starting new .o file by passing
  1505. the current section type
  1506. Revision 1.66.2.7 2004/05/03 14:59:57 peter
  1507. * no dlltool needed for win32 linking executables
  1508. Revision 1.66.2.6 2004/05/01 16:02:09 peter
  1509. * POINTER_SIZE replaced with sizeof(aint)
  1510. * aint,aword,tconst*int moved to globtype
  1511. Revision 1.66.2.5 2004/04/29 23:30:28 peter
  1512. * fix i386 compiler
  1513. }