assemble.pas 52 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 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. { object alloc and output }
  115. objectalloc : TAsmObjectAlloc;
  116. objectdata : TAsmObjectData;
  117. objectoutput : tobjectoutput;
  118. private
  119. { the aasmoutput lists that need to be processed }
  120. lists : byte;
  121. list : array[1..maxoutputlists] of TAAsmoutput;
  122. { current processing }
  123. currlistidx : byte;
  124. currlist : TAAsmoutput;
  125. currpass : byte;
  126. {$ifdef GDB}
  127. n_line : byte; { different types of source lines }
  128. linecount,
  129. includecount : longint;
  130. funcname : tasmsymbol;
  131. stabslastfileinfo : tfileposinfo;
  132. procedure convertstabs(p:pchar);
  133. procedure emitlineinfostabs(nidx,line : longint);
  134. procedure emitstabs(s:string);
  135. procedure WriteFileLineInfo(var fileinfo : tfileposinfo);
  136. procedure StartFileLineInfo;
  137. procedure EndFileLineInfo;
  138. {$endif}
  139. function MaybeNextList(var hp:Tai):boolean;
  140. function TreePass0(hp:Tai):Tai;
  141. function TreePass1(hp:Tai):Tai;
  142. function TreePass2(hp:Tai):Tai;
  143. procedure writetree;
  144. procedure writetreesmart;
  145. end;
  146. TAssemblerClass = class of TAssembler;
  147. Procedure GenerateAsm(smart:boolean);
  148. Procedure OnlyAsm;
  149. procedure RegisterAssembler(const r:tasminfo;c:TAssemblerClass);
  150. procedure InitAssembler;
  151. procedure DoneAssembler;
  152. Implementation
  153. uses
  154. {$ifdef hasunix}
  155. {$ifdef ver1_0}
  156. linux,
  157. {$else}
  158. unix,
  159. {$endif}
  160. {$endif}
  161. cutils,script,fmodule,verbose,
  162. {$ifdef memdebug}
  163. cclasses,
  164. {$endif memdebug}
  165. {$ifdef GDB}
  166. finput,
  167. gdb,
  168. {$endif GDB}
  169. cpubase,cpuinfo,aasmcpu
  170. ;
  171. var
  172. CAssembler : array[tasm] of TAssemblerClass;
  173. {*****************************************************************************
  174. TAssembler
  175. *****************************************************************************}
  176. Constructor TAssembler.Create(smart:boolean);
  177. begin
  178. { load start values }
  179. asmfile:=current_module.get_asmfilename;
  180. objfile:=current_module.objfilename^;
  181. name:=Lower(current_module.modulename^);
  182. path:=current_module.outputpath^;
  183. asmprefix := current_module.asmprefix^;
  184. if not assigned(current_module.outputpath) then
  185. ppufilename := ''
  186. else
  187. ppufilename := current_module.ppufilename^;
  188. SmartAsm:=smart;
  189. SmartFilesCount:=0;
  190. SmartHeaderCount:=0;
  191. SmartLinkOFiles.Clear;
  192. end;
  193. Destructor TAssembler.Destroy;
  194. begin
  195. end;
  196. procedure TAssembler.NextSmartName(place:tcutplace);
  197. var
  198. s : string;
  199. begin
  200. inc(SmartFilesCount);
  201. if SmartFilesCount>999999 then
  202. Message(asmw_f_too_many_asm_files);
  203. case place of
  204. cut_begin :
  205. begin
  206. inc(SmartHeaderCount);
  207. s:=asmprefix+tostr(SmartHeaderCount)+'h';
  208. end;
  209. cut_normal :
  210. s:=asmprefix+tostr(SmartHeaderCount)+'s';
  211. cut_end :
  212. s:=asmprefix+tostr(SmartHeaderCount)+'t';
  213. end;
  214. AsmFile:=Path+FixFileName(s+tostr(SmartFilesCount)+target_info.asmext);
  215. ObjFile:=Path+FixFileName(s+tostr(SmartFilesCount)+target_info.objext);
  216. { insert in container so it can be cleared after the linking }
  217. SmartLinkOFiles.Insert(Objfile);
  218. end;
  219. {*****************************************************************************
  220. TExternalAssembler
  221. *****************************************************************************}
  222. Function DoPipe:boolean;
  223. begin
  224. DoPipe:=(cs_asm_pipe in aktglobalswitches) and
  225. not(cs_asm_leave in aktglobalswitches)
  226. and ((aktoutputformat=as_gas));
  227. end;
  228. Constructor TExternalAssembler.Create(smart:boolean);
  229. begin
  230. inherited Create(smart);
  231. if SmartAsm then
  232. begin
  233. path:=FixPath(path+FixFileName(name)+target_info.smartext,false);
  234. CreateSmartLinkPath(path);
  235. end;
  236. Outcnt:=0;
  237. end;
  238. procedure TExternalAssembler.CreateSmartLinkPath(const s:string);
  239. var
  240. dir : searchrec;
  241. hs : string;
  242. begin
  243. if PathExists(s) then
  244. begin
  245. { the path exists, now we clean only all the .o and .s files }
  246. { .o files }
  247. findfirst(s+source_info.dirsep+'*'+target_info.objext,anyfile,dir);
  248. while (doserror=0) do
  249. begin
  250. RemoveFile(s+source_info.dirsep+dir.name);
  251. findnext(dir);
  252. end;
  253. findclose(dir);
  254. { .s files }
  255. findfirst(s+source_info.dirsep+'*'+target_info.asmext,anyfile,dir);
  256. while (doserror=0) do
  257. begin
  258. RemoveFile(s+source_info.dirsep+dir.name);
  259. findnext(dir);
  260. end;
  261. findclose(dir);
  262. end
  263. else
  264. begin
  265. hs:=s;
  266. if hs[length(hs)] in ['/','\'] then
  267. delete(hs,length(hs),1);
  268. {$I-}
  269. mkdir(hs);
  270. {$I+}
  271. if ioresult<>0 then;
  272. end;
  273. end;
  274. const
  275. lastas : byte=255;
  276. var
  277. LastASBin : pathstr;
  278. Function TExternalAssembler.FindAssembler:string;
  279. var
  280. asfound : boolean;
  281. UtilExe : string;
  282. begin
  283. asfound:=false;
  284. if cs_link_on_target in aktglobalswitches then
  285. begin
  286. { If linking on target, don't add any path PM }
  287. FindAssembler:=AddExtension(target_asm.asmbin,target_info.exeext);
  288. exit;
  289. end
  290. else
  291. UtilExe:=AddExtension(target_asm.asmbin,source_info.exeext);
  292. if lastas<>ord(target_asm.id) then
  293. begin
  294. lastas:=ord(target_asm.id);
  295. { is an assembler passed ? }
  296. if utilsdirectory<>'' then
  297. asfound:=FindFile(UtilExe,utilsdirectory,LastASBin);
  298. if not AsFound then
  299. asfound:=FindExe(UtilExe,LastASBin);
  300. if (not asfound) and not(cs_asm_extern in aktglobalswitches) then
  301. begin
  302. Message1(exec_e_assembler_not_found,LastASBin);
  303. aktglobalswitches:=aktglobalswitches+[cs_asm_extern];
  304. end;
  305. if asfound then
  306. Message1(exec_t_using_assembler,LastASBin);
  307. end;
  308. FindAssembler:=LastASBin;
  309. end;
  310. Function TExternalAssembler.CallAssembler(const command,para:string):Boolean;
  311. begin
  312. callassembler:=true;
  313. if not(cs_asm_extern in aktglobalswitches) then
  314. begin
  315. swapvectors;
  316. exec(command,para);
  317. swapvectors;
  318. if (doserror<>0) then
  319. begin
  320. Message1(exec_e_cant_call_assembler,tostr(doserror));
  321. aktglobalswitches:=aktglobalswitches+[cs_asm_extern];
  322. callassembler:=false;
  323. end
  324. else
  325. if (dosexitcode<>0) then
  326. begin
  327. Message1(exec_e_error_while_assembling,tostr(dosexitcode));
  328. callassembler:=false;
  329. end;
  330. end
  331. else
  332. AsmRes.AddAsmCommand(command,para,name);
  333. end;
  334. procedure TExternalAssembler.RemoveAsm;
  335. var
  336. g : file;
  337. begin
  338. if cs_asm_leave in aktglobalswitches then
  339. exit;
  340. if cs_asm_extern in aktglobalswitches then
  341. AsmRes.AddDeleteCommand(AsmFile)
  342. else
  343. begin
  344. assign(g,AsmFile);
  345. {$I-}
  346. erase(g);
  347. {$I+}
  348. if ioresult<>0 then;
  349. end;
  350. end;
  351. Function TExternalAssembler.DoAssemble:boolean;
  352. var
  353. s : string;
  354. begin
  355. DoAssemble:=true;
  356. if DoPipe then
  357. exit;
  358. if not(cs_asm_extern in aktglobalswitches) then
  359. begin
  360. if SmartAsm then
  361. begin
  362. if (SmartFilesCount<=1) then
  363. Message1(exec_i_assembling_smart,name);
  364. end
  365. else
  366. Message1(exec_i_assembling,name);
  367. end;
  368. s:=target_asm.asmcmd;
  369. {$ifdef m68k}
  370. if aktoptprocessor = MC68020 then
  371. s:='-m68020 '+s
  372. else
  373. s:='-m68000 '+s;
  374. {$endif}
  375. if (cs_link_on_target in aktglobalswitches) then
  376. begin
  377. Replace(s,'$ASM',ScriptFixFileName(AsmFile));
  378. Replace(s,'$OBJ',ScriptFixFileName(ObjFile));
  379. end
  380. else
  381. begin
  382. Replace(s,'$ASM',AsmFile);
  383. Replace(s,'$OBJ',ObjFile);
  384. end;
  385. if CallAssembler(FindAssembler,s) then
  386. RemoveAsm
  387. else
  388. begin
  389. DoAssemble:=false;
  390. GenerateError;
  391. end;
  392. end;
  393. Procedure TExternalAssembler.AsmFlush;
  394. begin
  395. if outcnt>0 then
  396. begin
  397. BlockWrite(outfile,outbuf,outcnt);
  398. outcnt:=0;
  399. end;
  400. end;
  401. Procedure TExternalAssembler.AsmClear;
  402. begin
  403. outcnt:=0;
  404. end;
  405. Procedure TExternalAssembler.AsmWrite(const s:string);
  406. begin
  407. if OutCnt+length(s)>=AsmOutSize then
  408. AsmFlush;
  409. Move(s[1],OutBuf[OutCnt],length(s));
  410. inc(OutCnt,length(s));
  411. inc(AsmSize,length(s));
  412. end;
  413. Procedure TExternalAssembler.AsmWriteLn(const s:string);
  414. begin
  415. AsmWrite(s);
  416. AsmLn;
  417. end;
  418. Procedure TExternalAssembler.AsmWritePChar(p:pchar);
  419. var
  420. i,j : longint;
  421. begin
  422. i:=StrLen(p);
  423. j:=i;
  424. while j>0 do
  425. begin
  426. i:=min(j,AsmOutSize);
  427. if OutCnt+i>=AsmOutSize then
  428. AsmFlush;
  429. Move(p[0],OutBuf[OutCnt],i);
  430. inc(OutCnt,i);
  431. inc(AsmSize,i);
  432. dec(j,i);
  433. p:=pchar(@p[i]);
  434. end;
  435. end;
  436. Procedure TExternalAssembler.AsmLn;
  437. begin
  438. if OutCnt>=AsmOutSize-2 then
  439. AsmFlush;
  440. OutBuf[OutCnt]:=target_info.newline[1];
  441. inc(OutCnt);
  442. inc(AsmSize);
  443. if length(target_info.newline)>1 then
  444. begin
  445. OutBuf[OutCnt]:=target_info.newline[2];
  446. inc(OutCnt);
  447. inc(AsmSize);
  448. end;
  449. end;
  450. procedure TExternalAssembler.AsmCreate(Aplace:tcutplace);
  451. begin
  452. if SmartAsm then
  453. NextSmartName(Aplace);
  454. {$ifdef hasunix}
  455. if DoPipe then
  456. begin
  457. Message1(exec_i_assembling_pipe,asmfile);
  458. POpen(outfile,'as -o '+objfile,'W');
  459. end
  460. else
  461. {$endif}
  462. begin
  463. Assign(outfile,asmfile);
  464. {$I-}
  465. Rewrite(outfile,1);
  466. {$I+}
  467. if ioresult<>0 then
  468. Message1(exec_d_cant_create_asmfile,asmfile);
  469. end;
  470. outcnt:=0;
  471. AsmSize:=0;
  472. AsmStartSize:=0;
  473. end;
  474. procedure TExternalAssembler.AsmClose;
  475. var
  476. f : file;
  477. l : longint;
  478. begin
  479. AsmFlush;
  480. {$ifdef hasunix}
  481. if DoPipe then
  482. PClose(outfile)
  483. else
  484. {$endif}
  485. begin
  486. {Touch Assembler time to ppu time is there is a ppufilename}
  487. if ppufilename<>'' then
  488. begin
  489. Assign(f,ppufilename);
  490. {$I-}
  491. reset(f,1);
  492. {$I+}
  493. if ioresult=0 then
  494. begin
  495. getftime(f,l);
  496. close(f);
  497. reset(outfile,1);
  498. setftime(outfile,l);
  499. end;
  500. end;
  501. close(outfile);
  502. end;
  503. end;
  504. procedure TExternalAssembler.WriteTree(p:TAAsmoutput);
  505. begin
  506. end;
  507. procedure TExternalAssembler.WriteAsmList;
  508. begin
  509. end;
  510. procedure TExternalAssembler.MakeObject;
  511. begin
  512. AsmCreate(cut_normal);
  513. WriteAsmList;
  514. AsmClose;
  515. DoAssemble;
  516. end;
  517. {*****************************************************************************
  518. TInternalAssembler
  519. *****************************************************************************}
  520. constructor TInternalAssembler.create(smart:boolean);
  521. begin
  522. inherited create(smart);
  523. objectoutput:=nil;
  524. objectdata:=nil;
  525. objectalloc:=TAsmObjectAlloc.create;
  526. SmartAsm:=smart;
  527. currpass:=0;
  528. end;
  529. destructor TInternalAssembler.destroy;
  530. {$ifdef MEMDEBUG}
  531. var
  532. d : tmemdebug;
  533. {$endif}
  534. begin
  535. {$ifdef MEMDEBUG}
  536. d := tmemdebug.create(name+' - agbin');
  537. {$endif}
  538. objectdata.free;
  539. objectoutput.free;
  540. objectalloc.free;
  541. {$ifdef MEMDEBUG}
  542. d.free;
  543. {$endif}
  544. end;
  545. {$ifdef GDB}
  546. procedure TInternalAssembler.convertstabs(p:pchar);
  547. var
  548. ofs,
  549. nidx,nother,ii,i,line,j : longint;
  550. code : integer;
  551. hp : pchar;
  552. reloc : boolean;
  553. sec : TSection;
  554. ps : tasmsymbol;
  555. s : string;
  556. begin
  557. ofs:=0;
  558. reloc:=true;
  559. ps:=nil;
  560. sec:=sec_none;
  561. if p[0]='"' then
  562. begin
  563. i:=1;
  564. { we can have \" inside the string !! PM }
  565. while not ((p[i]='"') and (p[i-1]<>'\')) do
  566. inc(i);
  567. p[i]:=#0;
  568. ii:=i;
  569. hp:=@p[1];
  570. s:=StrPas(@P[i+2]);
  571. end
  572. else
  573. begin
  574. hp:=nil;
  575. s:=StrPas(P);
  576. i:=-2; {needed below (PM) }
  577. end;
  578. { When in pass 1 then only alloc and leave }
  579. if currpass=1 then
  580. begin
  581. objectalloc.staballoc(hp);
  582. if assigned(hp) then
  583. p[i]:='"';
  584. exit;
  585. end;
  586. { Parse the rest of the stabs }
  587. if s='' then
  588. internalerror(33000);
  589. j:=pos(',',s);
  590. if j=0 then
  591. internalerror(33001);
  592. Val(Copy(s,1,j-1),nidx,code);
  593. if code<>0 then
  594. internalerror(33002);
  595. i:=i+2+j;
  596. Delete(s,1,j);
  597. j:=pos(',',s);
  598. if (j=0) then
  599. internalerror(33003);
  600. Val(Copy(s,1,j-1),nother,code);
  601. if code<>0 then
  602. internalerror(33004);
  603. i:=i+j;
  604. Delete(s,1,j);
  605. j:=pos(',',s);
  606. if j=0 then
  607. begin
  608. j:=256;
  609. ofs:=-1;
  610. end;
  611. Val(Copy(s,1,j-1),line,code);
  612. if code<>0 then
  613. internalerror(33005);
  614. if ofs=0 then
  615. begin
  616. Delete(s,1,j);
  617. i:=i+j;
  618. Val(s,ofs,code);
  619. if code=0 then
  620. reloc:=false
  621. else
  622. begin
  623. ofs:=0;
  624. s:=strpas(@p[i]);
  625. { handle asmsymbol or
  626. asmsymbol - asmsymbol }
  627. j:=pos(' ',s);
  628. if j=0 then
  629. j:=pos('-',s);
  630. { single asmsymbol }
  631. if j=0 then
  632. j:=256;
  633. { the symbol can be external
  634. so we must use newasmsymbol and
  635. not getasmsymbol !! PM }
  636. ps:=objectlibrary.newasmsymbol(copy(s,1,j-1));
  637. if not assigned(ps) then
  638. internalerror(33006)
  639. else
  640. begin
  641. sec:=ps.section;
  642. ofs:=ps.address;
  643. reloc:=true;
  644. objectlibrary.UsedAsmSymbolListInsert(ps);
  645. end;
  646. if j<256 then
  647. begin
  648. i:=i+j;
  649. s:=strpas(@p[i]);
  650. if (s<>'') and (s[1]=' ') then
  651. begin
  652. j:=0;
  653. while (s[j+1]=' ') do
  654. inc(j);
  655. i:=i+j;
  656. s:=strpas(@p[i]);
  657. end;
  658. ps:=objectlibrary.getasmsymbol(s);
  659. if not assigned(ps) then
  660. internalerror(33007)
  661. else
  662. begin
  663. if ps.section<>sec then
  664. internalerror(33008);
  665. ofs:=ofs-ps.address;
  666. reloc:=false;
  667. objectlibrary.UsedAsmSymbolListInsert(ps);
  668. end;
  669. end;
  670. end;
  671. end;
  672. { external bss need speical handling (PM) }
  673. if assigned(ps) and (ps.section=sec_none) then
  674. begin
  675. if currpass=2 then
  676. begin
  677. objectdata.writesymbol(ps);
  678. objectoutput.exportsymbol(ps);
  679. end;
  680. objectdata.writeSymStabs(sec,ofs,hp,ps,nidx,nother,line,reloc)
  681. end
  682. else
  683. objectdata.writeStabs(sec,ofs,hp,nidx,nother,line,reloc);
  684. if assigned(hp) then
  685. p[ii]:='"';
  686. end;
  687. procedure TInternalAssembler.emitlineinfostabs(nidx,line : longint);
  688. var
  689. sec : TSection;
  690. begin
  691. if currpass=1 then
  692. begin
  693. objectalloc.staballoc(nil);
  694. exit;
  695. end;
  696. if (nidx=n_textline) and assigned(funcname) and
  697. (target_info.use_function_relative_addresses) then
  698. objectdata.writeStabs(sec_code,objectdata.sectionsize(sec_code)-funcname.address,
  699. nil,nidx,0,line,false)
  700. else
  701. begin
  702. if nidx=n_textline then
  703. sec:=sec_code
  704. else if nidx=n_dataline then
  705. sec:=sec_data
  706. else
  707. sec:=sec_bss;
  708. objectdata.writeStabs(sec,objectdata.sectionsize(sec),
  709. nil,nidx,0,line,true);
  710. end;
  711. end;
  712. procedure TInternalAssembler.emitstabs(s:string);
  713. begin
  714. s:=s+#0;
  715. ConvertStabs(@s[1]);
  716. end;
  717. procedure TInternalAssembler.WriteFileLineInfo(var fileinfo : tfileposinfo);
  718. var
  719. curr_n : byte;
  720. hp : tasmsymbol;
  721. infile : tinputfile;
  722. begin
  723. if not ((cs_debuginfo in aktmoduleswitches) or
  724. (cs_gdb_lineinfo in aktglobalswitches)) then
  725. exit;
  726. { file changed ? (must be before line info) }
  727. if (fileinfo.fileindex<>0) and
  728. (stabslastfileinfo.fileindex<>fileinfo.fileindex) then
  729. begin
  730. infile:=current_module.sourcefiles.get_file(fileinfo.fileindex);
  731. if assigned(infile) then
  732. begin
  733. if includecount=0 then
  734. curr_n:=n_sourcefile
  735. else
  736. curr_n:=n_includefile;
  737. { get symbol for this includefile }
  738. hp:=objectlibrary.newasmsymboltype('Ltext'+ToStr(IncludeCount),AB_LOCAL,AT_FUNCTION);
  739. if currpass=1 then
  740. begin
  741. hp.setaddress(currpass,objectalloc.currsec,objectalloc.sectionsize,0);
  742. objectlibrary.UsedAsmSymbolListInsert(hp);
  743. end
  744. else
  745. objectdata.writesymbol(hp);
  746. { emit stabs }
  747. if (infile.path^<>'') then
  748. EmitStabs('"'+lower(BsToSlash(FixPath(infile.path^,false)))+'",'+tostr(curr_n)+
  749. ',0,0,Ltext'+ToStr(IncludeCount));
  750. EmitStabs('"'+lower(FixFileName(infile.name^))+'",'+tostr(curr_n)+
  751. ',0,0,Ltext'+ToStr(IncludeCount));
  752. inc(includecount);
  753. { force new line info }
  754. stabslastfileinfo.line:=-1;
  755. end;
  756. end;
  757. { line changed ? }
  758. if (stabslastfileinfo.line<>fileinfo.line) and (fileinfo.line<>0) then
  759. emitlineinfostabs(n_line,fileinfo.line);
  760. stabslastfileinfo:=fileinfo;
  761. end;
  762. procedure TInternalAssembler.StartFileLineInfo;
  763. var
  764. fileinfo : tfileposinfo;
  765. begin
  766. FillChar(stabslastfileinfo,sizeof(stabslastfileinfo),0);
  767. n_line:=n_textline;
  768. funcname:=nil;
  769. linecount:=1;
  770. includecount:=0;
  771. fileinfo.fileindex:=1;
  772. fileinfo.line:=1;
  773. WriteFileLineInfo(fileinfo);
  774. end;
  775. procedure TInternalAssembler.EndFileLineInfo;
  776. var
  777. hp : tasmsymbol;
  778. store_sec : TSection;
  779. begin
  780. if not ((cs_debuginfo in aktmoduleswitches) or
  781. (cs_gdb_lineinfo in aktglobalswitches)) then
  782. exit;
  783. store_sec:=objectalloc.currsec;
  784. objectalloc.seTSection(sec_code);
  785. hp:=objectlibrary.newasmsymboltype('Letext',AB_LOCAL,AT_FUNCTION);
  786. if currpass=1 then
  787. begin
  788. hp.setaddress(currpass,objectalloc.currsec,objectalloc.sectionsize,0);
  789. objectlibrary.UsedAsmSymbolListInsert(hp);
  790. end
  791. else
  792. objectdata.writesymbol(hp);
  793. EmitStabs('"",'+tostr(n_sourcefile)+',0,0,Letext');
  794. objectalloc.seTSection(store_sec);
  795. end;
  796. {$endif GDB}
  797. function TInternalAssembler.MaybeNextList(var hp:Tai):boolean;
  798. begin
  799. { maybe end of list }
  800. while not assigned(hp) do
  801. begin
  802. if currlistidx<lists then
  803. begin
  804. inc(currlistidx);
  805. currlist:=list[currlistidx];
  806. hp:=Tai(currList.first);
  807. end
  808. else
  809. begin
  810. MaybeNextList:=false;
  811. exit;
  812. end;
  813. end;
  814. MaybeNextList:=true;
  815. end;
  816. function TInternalAssembler.TreePass0(hp:Tai):Tai;
  817. var
  818. l : longint;
  819. begin
  820. while assigned(hp) do
  821. begin
  822. case hp.typ of
  823. ait_align :
  824. begin
  825. { always use the maximum fillsize in this pass to avoid possible
  826. short jumps to become out of range }
  827. Tai_align(hp).fillsize:=Tai_align(hp).aligntype;
  828. objectalloc.sectionalloc(Tai_align(hp).fillsize);
  829. end;
  830. ait_datablock :
  831. begin
  832. if not SmartAsm then
  833. begin
  834. if not Tai_datablock(hp).is_global then
  835. begin
  836. l:=Tai_datablock(hp).size;
  837. if l>2 then
  838. objectalloc.sectionalign(4)
  839. else if l>1 then
  840. objectalloc.sectionalign(2);
  841. objectalloc.sectionalloc(Tai_datablock(hp).size);
  842. end;
  843. end
  844. else
  845. begin
  846. l:=Tai_datablock(hp).size;
  847. if l>2 then
  848. objectalloc.sectionalign(4)
  849. else if l>1 then
  850. objectalloc.sectionalign(2);
  851. objectalloc.sectionalloc(Tai_datablock(hp).size);
  852. end;
  853. end;
  854. ait_const_32bit :
  855. objectalloc.sectionalloc(4);
  856. ait_const_16bit :
  857. objectalloc.sectionalloc(2);
  858. ait_const_8bit :
  859. objectalloc.sectionalloc(1);
  860. ait_real_80bit :
  861. objectalloc.sectionalloc(10);
  862. ait_real_64bit :
  863. objectalloc.sectionalloc(8);
  864. ait_real_32bit :
  865. objectalloc.sectionalloc(4);
  866. ait_comp_64bit :
  867. objectalloc.sectionalloc(8);
  868. ait_const_rva,
  869. ait_const_symbol :
  870. objectalloc.sectionalloc(4);
  871. ait_section:
  872. objectalloc.seTSection(Tai_section(hp).sec);
  873. ait_symbol :
  874. Tai_symbol(hp).sym.setaddress(currpass,objectalloc.currsec,objectalloc.sectionsize,0);
  875. ait_label :
  876. Tai_label(hp).l.setaddress(currpass,objectalloc.currsec,objectalloc.sectionsize,0);
  877. ait_string :
  878. objectalloc.sectionalloc(Tai_string(hp).len);
  879. ait_instruction :
  880. begin
  881. {$ifdef i386}
  882. {$ifndef NOAG386BIN}
  883. { reset instructions which could change in pass 2 }
  884. Taicpu(hp).resetpass2;
  885. objectalloc.sectionalloc(Taicpu(hp).Pass1(objectalloc.sectionsize));
  886. {$endif NOAG386BIN}
  887. {$endif i386}
  888. end;
  889. ait_cut :
  890. if SmartAsm then
  891. break;
  892. end;
  893. hp:=Tai(hp.next);
  894. end;
  895. TreePass0:=hp;
  896. end;
  897. function TInternalAssembler.TreePass1(hp:Tai):Tai;
  898. var
  899. InlineLevel,
  900. i,l : longint;
  901. begin
  902. inlinelevel:=0;
  903. while assigned(hp) do
  904. begin
  905. {$ifdef GDB}
  906. { write stabs, no line info for inlined code }
  907. if (inlinelevel=0) and
  908. ((cs_debuginfo in aktmoduleswitches) or
  909. (cs_gdb_lineinfo in aktglobalswitches)) then
  910. begin
  911. if (objectalloc.currsec<>sec_none) and
  912. not(hp.typ in SkipLineInfo) then
  913. WriteFileLineInfo(tailineinfo(hp).fileinfo);
  914. end;
  915. {$endif GDB}
  916. case hp.typ of
  917. ait_align :
  918. begin
  919. { here we must determine the fillsize which is used in pass2 }
  920. Tai_align(hp).fillsize:=align(objectalloc.sectionsize,Tai_align(hp).aligntype)-
  921. objectalloc.sectionsize;
  922. objectalloc.sectionalloc(Tai_align(hp).fillsize);
  923. end;
  924. ait_datablock :
  925. begin
  926. if objectalloc.currsec<>sec_bss then
  927. Message(asmw_e_alloc_data_only_in_bss);
  928. if not SmartAsm then
  929. begin
  930. if Tai_datablock(hp).is_global then
  931. begin
  932. Tai_datablock(hp).sym.setaddress(currpass,sec_none,Tai_datablock(hp).size,Tai_datablock(hp).size);
  933. { force to be common/external, must be after setaddress as that would
  934. set it to AS_GLOBAL }
  935. Tai_datablock(hp).sym.currbind:=AB_COMMON;
  936. end
  937. else
  938. begin
  939. l:=Tai_datablock(hp).size;
  940. if l>2 then
  941. objectalloc.sectionalign(4)
  942. else if l>1 then
  943. objectalloc.sectionalign(2);
  944. Tai_datablock(hp).sym.setaddress(currpass,objectalloc.currsec,objectalloc.sectionsize,
  945. Tai_datablock(hp).size);
  946. objectalloc.sectionalloc(Tai_datablock(hp).size);
  947. end;
  948. end
  949. else
  950. begin
  951. l:=Tai_datablock(hp).size;
  952. if l>2 then
  953. objectalloc.sectionalign(4)
  954. else if l>1 then
  955. objectalloc.sectionalign(2);
  956. Tai_datablock(hp).sym.setaddress(currpass,objectalloc.currsec,objectalloc.sectionsize,Tai_datablock(hp).size);
  957. objectalloc.sectionalloc(Tai_datablock(hp).size);
  958. end;
  959. objectlibrary.UsedAsmSymbolListInsert(Tai_datablock(hp).sym);
  960. end;
  961. ait_const_32bit :
  962. objectalloc.sectionalloc(4);
  963. ait_const_16bit :
  964. objectalloc.sectionalloc(2);
  965. ait_const_8bit :
  966. objectalloc.sectionalloc(1);
  967. ait_real_80bit :
  968. objectalloc.sectionalloc(10);
  969. ait_real_64bit :
  970. objectalloc.sectionalloc(8);
  971. ait_real_32bit :
  972. objectalloc.sectionalloc(4);
  973. ait_comp_64bit :
  974. objectalloc.sectionalloc(8);
  975. ait_const_rva,
  976. ait_const_symbol :
  977. begin
  978. objectalloc.sectionalloc(4);
  979. objectlibrary.UsedAsmSymbolListInsert(Tai_const_symbol(hp).sym);
  980. end;
  981. ait_section:
  982. begin
  983. objectalloc.seTSection(Tai_section(hp).sec);
  984. {$ifdef GDB}
  985. case Tai_section(hp).sec of
  986. sec_code : n_line:=n_textline;
  987. sec_data : n_line:=n_dataline;
  988. sec_bss : n_line:=n_bssline;
  989. else
  990. n_line:=n_dataline;
  991. end;
  992. stabslastfileinfo.line:=-1;
  993. {$endif GDB}
  994. end;
  995. {$ifdef GDB}
  996. ait_stabn :
  997. convertstabs(Tai_stabn(hp).str);
  998. ait_stabs :
  999. convertstabs(Tai_stabs(hp).str);
  1000. ait_stab_function_name :
  1001. begin
  1002. if assigned(Tai_stab_function_name(hp).str) then
  1003. begin
  1004. funcname:=objectlibrary.getasmsymbol(strpas(Tai_stab_function_name(hp).str));
  1005. objectlibrary.UsedAsmSymbolListInsert(funcname);
  1006. end
  1007. else
  1008. funcname:=nil;
  1009. end;
  1010. ait_force_line :
  1011. stabslastfileinfo.line:=0;
  1012. {$endif}
  1013. ait_symbol :
  1014. begin
  1015. Tai_symbol(hp).sym.setaddress(currpass,objectalloc.currsec,objectalloc.sectionsize,0);
  1016. objectlibrary.UsedAsmSymbolListInsert(Tai_symbol(hp).sym);
  1017. end;
  1018. ait_symbol_end :
  1019. begin
  1020. if target_info.system in [system_i386_linux,system_i386_beos] then
  1021. begin
  1022. Tai_symbol_end(hp).sym.size:=objectalloc.sectionsize-Tai_symbol_end(hp).sym.address;
  1023. objectlibrary.UsedAsmSymbolListInsert(Tai_symbol_end(hp).sym);
  1024. end;
  1025. end;
  1026. ait_label :
  1027. begin
  1028. Tai_label(hp).l.setaddress(currpass,objectalloc.currsec,objectalloc.sectionsize,0);
  1029. objectlibrary.UsedAsmSymbolListInsert(Tai_label(hp).l);
  1030. end;
  1031. ait_string :
  1032. objectalloc.sectionalloc(Tai_string(hp).len);
  1033. ait_instruction :
  1034. begin
  1035. {$ifdef i386}
  1036. {$ifndef NOAG386BIN}
  1037. objectalloc.sectionalloc(Taicpu(hp).Pass1(objectalloc.sectionsize));
  1038. { fixup the references }
  1039. for i:=1 to Taicpu(hp).ops do
  1040. begin
  1041. with Taicpu(hp).oper[i-1] do
  1042. begin
  1043. case typ of
  1044. top_ref :
  1045. begin
  1046. if assigned(ref^.symbol) then
  1047. objectlibrary.UsedAsmSymbolListInsert(ref^.symbol);
  1048. end;
  1049. top_symbol :
  1050. begin
  1051. objectlibrary.UsedAsmSymbolListInsert(sym);
  1052. end;
  1053. end;
  1054. end;
  1055. end;
  1056. {$endif NOAG386BIN}
  1057. {$endif i386}
  1058. end;
  1059. ait_direct :
  1060. Message(asmw_f_direct_not_supported);
  1061. ait_cut :
  1062. if SmartAsm then
  1063. break;
  1064. ait_marker :
  1065. if tai_marker(hp).kind=InlineStart then
  1066. inc(InlineLevel)
  1067. else if tai_marker(hp).kind=InlineEnd then
  1068. dec(InlineLevel);
  1069. end;
  1070. hp:=Tai(hp.next);
  1071. end;
  1072. TreePass1:=hp;
  1073. end;
  1074. function TInternalAssembler.TreePass2(hp:Tai):Tai;
  1075. var
  1076. fillbuffer : tfillbuffer;
  1077. InlineLevel,
  1078. l : longint;
  1079. {$ifdef i386}
  1080. co : comp;
  1081. {$endif i386}
  1082. begin
  1083. inlinelevel:=0;
  1084. { main loop }
  1085. while assigned(hp) do
  1086. begin
  1087. {$ifdef GDB}
  1088. { write stabs, no line info for inlined code }
  1089. if (inlinelevel=0) and
  1090. ((cs_debuginfo in aktmoduleswitches) or
  1091. (cs_gdb_lineinfo in aktglobalswitches)) then
  1092. begin
  1093. if (objectdata.currsec<>sec_none) and
  1094. not(hp.typ in SkipLineInfo) then
  1095. WriteFileLineInfo(tailineinfo(hp).fileinfo);
  1096. end;
  1097. {$endif GDB}
  1098. case hp.typ of
  1099. ait_align :
  1100. begin
  1101. if objectdata.currsec=sec_bss then
  1102. objectdata.alloc(Tai_align(hp).fillsize)
  1103. else
  1104. objectdata.writebytes(Tai_align(hp).calculatefillbuf(fillbuffer)^,Tai_align(hp).fillsize);
  1105. end;
  1106. ait_section :
  1107. begin
  1108. objectdata.defaulTSection(Tai_section(hp).sec);
  1109. {$ifdef GDB}
  1110. case Tai_section(hp).sec of
  1111. sec_code : n_line:=n_textline;
  1112. sec_data : n_line:=n_dataline;
  1113. sec_bss : n_line:=n_bssline;
  1114. else
  1115. n_line:=n_dataline;
  1116. end;
  1117. stabslastfileinfo.line:=-1;
  1118. {$endif GDB}
  1119. end;
  1120. ait_symbol :
  1121. begin
  1122. objectdata.writesymbol(Tai_symbol(hp).sym);
  1123. objectoutput.exportsymbol(Tai_symbol(hp).sym);
  1124. end;
  1125. ait_datablock :
  1126. begin
  1127. objectdata.writesymbol(Tai_datablock(hp).sym);
  1128. objectoutput.exportsymbol(Tai_datablock(hp).sym);
  1129. if SmartAsm or (not Tai_datablock(hp).is_global) then
  1130. begin
  1131. l:=Tai_datablock(hp).size;
  1132. if l>2 then
  1133. objectdata.allocalign(4)
  1134. else if l>1 then
  1135. objectdata.allocalign(2);
  1136. objectdata.alloc(Tai_datablock(hp).size);
  1137. end;
  1138. end;
  1139. ait_const_32bit :
  1140. objectdata.writebytes(Tai_const(hp).value,4);
  1141. ait_const_16bit :
  1142. objectdata.writebytes(Tai_const(hp).value,2);
  1143. ait_const_8bit :
  1144. objectdata.writebytes(Tai_const(hp).value,1);
  1145. ait_real_80bit :
  1146. objectdata.writebytes(Tai_real_80bit(hp).value,10);
  1147. ait_real_64bit :
  1148. objectdata.writebytes(Tai_real_64bit(hp).value,8);
  1149. ait_real_32bit :
  1150. objectdata.writebytes(Tai_real_32bit(hp).value,4);
  1151. ait_comp_64bit :
  1152. begin
  1153. {$ifdef i386}
  1154. {$ifdef FPC}
  1155. co:=comp(Tai_comp_64bit(hp).value);
  1156. {$else}
  1157. co:=Tai_comp_64bit(hp).value;
  1158. {$endif}
  1159. objectdata.writebytes(co,8);
  1160. {$endif i386}
  1161. end;
  1162. ait_string :
  1163. objectdata.writebytes(Tai_string(hp).str^,Tai_string(hp).len);
  1164. ait_const_rva :
  1165. objectdata.writereloc(Tai_const_symbol(hp).offset,4,
  1166. Tai_const_symbol(hp).sym,RELOC_RVA);
  1167. ait_const_symbol :
  1168. objectdata.writereloc(Tai_const_symbol(hp).offset,4,
  1169. Tai_const_symbol(hp).sym,RELOC_ABSOLUTE);
  1170. ait_label :
  1171. begin
  1172. objectdata.writesymbol(Tai_label(hp).l);
  1173. { exporting shouldn't be necessary as labels are local,
  1174. but it's better to be on the safe side (PFV) }
  1175. objectoutput.exportsymbol(Tai_label(hp).l);
  1176. end;
  1177. {$ifdef i386}
  1178. {$ifndef NOAG386BIN}
  1179. ait_instruction :
  1180. Taicpu(hp).Pass2(objectdata);
  1181. {$endif NOAG386BIN}
  1182. {$endif i386}
  1183. {$ifdef GDB}
  1184. ait_stabn :
  1185. convertstabs(Tai_stabn(hp).str);
  1186. ait_stabs :
  1187. convertstabs(Tai_stabs(hp).str);
  1188. ait_stab_function_name :
  1189. if assigned(Tai_stab_function_name(hp).str) then
  1190. funcname:=objectlibrary.getasmsymbol(strpas(Tai_stab_function_name(hp).str))
  1191. else
  1192. funcname:=nil;
  1193. ait_force_line :
  1194. stabslastfileinfo.line:=0;
  1195. {$endif}
  1196. ait_cut :
  1197. if SmartAsm then
  1198. break;
  1199. ait_marker :
  1200. if tai_marker(hp).kind=InlineStart then
  1201. inc(InlineLevel)
  1202. else if tai_marker(hp).kind=InlineEnd then
  1203. dec(InlineLevel);
  1204. end;
  1205. hp:=Tai(hp.next);
  1206. end;
  1207. TreePass2:=hp;
  1208. end;
  1209. procedure TInternalAssembler.writetree;
  1210. var
  1211. hp : Tai;
  1212. label
  1213. doexit;
  1214. begin
  1215. objectalloc.reseTSections;
  1216. objectalloc.seTSection(sec_code);
  1217. objectdata:=objectoutput.newobjectdata(Objfile);
  1218. objectdata.defaulTSection(sec_code);
  1219. { reset the asmsymbol list }
  1220. objectlibrary.CreateUsedAsmsymbolList;
  1221. { Pass 0 }
  1222. currpass:=0;
  1223. objectalloc.seTSection(sec_code);
  1224. { start with list 1 }
  1225. currlistidx:=1;
  1226. currlist:=list[currlistidx];
  1227. hp:=Tai(currList.first);
  1228. while assigned(hp) do
  1229. begin
  1230. hp:=TreePass0(hp);
  1231. MaybeNextList(hp);
  1232. end;
  1233. { leave if errors have occured }
  1234. if errorcount>0 then
  1235. goto doexit;
  1236. { Pass 1 }
  1237. currpass:=1;
  1238. objectalloc.reseTSections;
  1239. objectalloc.seTSection(sec_code);
  1240. {$ifdef GDB}
  1241. StartFileLineInfo;
  1242. {$endif GDB}
  1243. { start with list 1 }
  1244. currlistidx:=1;
  1245. currlist:=list[currlistidx];
  1246. hp:=Tai(currList.first);
  1247. while assigned(hp) do
  1248. begin
  1249. hp:=TreePass1(hp);
  1250. MaybeNextList(hp);
  1251. end;
  1252. {$ifdef GDB}
  1253. EndFileLineInfo;
  1254. {$endif GDB}
  1255. { check for undefined labels and reset }
  1256. objectlibrary.UsedAsmSymbolListCheckUndefined;
  1257. { set section sizes }
  1258. objectdata.seTSectionsizes(objectalloc.secsize);
  1259. { leave if errors have occured }
  1260. if errorcount>0 then
  1261. goto doexit;
  1262. { Pass 2 }
  1263. currpass:=2;
  1264. {$ifdef GDB}
  1265. StartFileLineInfo;
  1266. {$endif GDB}
  1267. { start with list 1 }
  1268. currlistidx:=1;
  1269. currlist:=list[currlistidx];
  1270. hp:=Tai(currList.first);
  1271. while assigned(hp) do
  1272. begin
  1273. hp:=TreePass2(hp);
  1274. MaybeNextList(hp);
  1275. end;
  1276. {$ifdef GDB}
  1277. EndFileLineInfo;
  1278. {$endif GDB}
  1279. { don't write the .o file if errors have occured }
  1280. if errorcount=0 then
  1281. begin
  1282. { write objectfile }
  1283. objectoutput.startobjectfile(ObjFile);
  1284. objectoutput.writeobjectfile(objectdata);
  1285. objectdata.free;
  1286. objectdata:=nil;
  1287. end;
  1288. doexit:
  1289. { reset the used symbols back, must be after the .o has been
  1290. written }
  1291. objectlibrary.UsedAsmsymbolListReset;
  1292. objectlibrary.DestroyUsedAsmsymbolList;
  1293. end;
  1294. procedure TInternalAssembler.writetreesmart;
  1295. var
  1296. hp : Tai;
  1297. starTSec : TSection;
  1298. place: tcutplace;
  1299. begin
  1300. objectalloc.reseTSections;
  1301. objectalloc.seTSection(sec_code);
  1302. NextSmartName(cut_normal);
  1303. objectdata:=objectoutput.newobjectdata(Objfile);
  1304. objectdata.defaulTSection(sec_code);
  1305. starTSec:=sec_code;
  1306. { start with list 1 }
  1307. currlistidx:=1;
  1308. currlist:=list[currlistidx];
  1309. hp:=Tai(currList.first);
  1310. while assigned(hp) do
  1311. begin
  1312. { reset the asmsymbol list }
  1313. objectlibrary.CreateUsedAsmSymbolList;
  1314. { Pass 0 }
  1315. currpass:=0;
  1316. objectalloc.reseTSections;
  1317. objectalloc.seTSection(starTSec);
  1318. TreePass0(hp);
  1319. { leave if errors have occured }
  1320. if errorcount>0 then
  1321. exit;
  1322. { Pass 1 }
  1323. currpass:=1;
  1324. objectalloc.reseTSections;
  1325. objectalloc.seTSection(starTSec);
  1326. {$ifdef GDB}
  1327. StartFileLineInfo;
  1328. {$endif GDB}
  1329. TreePass1(hp);
  1330. {$ifdef GDB}
  1331. EndFileLineInfo;
  1332. {$endif GDB}
  1333. { check for undefined labels }
  1334. objectlibrary.UsedAsmSymbolListCheckUndefined;
  1335. { set section sizes }
  1336. objectdata.seTSectionsizes(objectalloc.secsize);
  1337. { leave if errors have occured }
  1338. if errorcount>0 then
  1339. exit;
  1340. { Pass 2 }
  1341. currpass:=2;
  1342. objectoutput.startobjectfile(Objfile);
  1343. objectdata.defaulTSection(starTSec);
  1344. {$ifdef GDB}
  1345. StartFileLineInfo;
  1346. {$endif GDB}
  1347. hp:=TreePass2(hp);
  1348. {$ifdef GDB}
  1349. EndFileLineInfo;
  1350. {$endif GDB}
  1351. { leave if errors have occured }
  1352. if errorcount>0 then
  1353. exit;
  1354. { write the current objectfile }
  1355. objectoutput.writeobjectfile(objectdata);
  1356. objectdata.free;
  1357. objectdata:=nil;
  1358. { reset the used symbols back, must be after the .o has been
  1359. written }
  1360. objectlibrary.UsedAsmsymbolListReset;
  1361. objectlibrary.DestroyUsedAsmsymbolList;
  1362. { end of lists? }
  1363. if not MaybeNextList(hp) then
  1364. break;
  1365. { save section for next loop }
  1366. { this leads to a problem if starTSec is sec_none !! PM }
  1367. starTSec:=objectalloc.currsec;
  1368. { we will start a new objectfile so reset everything }
  1369. { The place can still change in the next while loop, so don't init }
  1370. { the writer yet (JM) }
  1371. if (hp.typ=ait_cut) then
  1372. place := Tai_cut(hp).place
  1373. else
  1374. place := cut_normal;
  1375. { avoid empty files }
  1376. while assigned(hp) and
  1377. (Tai(hp).typ in [ait_marker,ait_comment,ait_section,ait_cut]) do
  1378. begin
  1379. if Tai(hp).typ=ait_section then
  1380. starTSec:=Tai_section(hp).sec
  1381. else if (Tai(hp).typ=ait_cut) then
  1382. place := Tai_cut(hp).place;
  1383. hp:=Tai(hp.next);
  1384. end;
  1385. if not MaybeNextList(hp) then
  1386. break;
  1387. { start next objectfile }
  1388. NextSmartName(place);
  1389. objectdata:=objectoutput.newobjectdata(Objfile);
  1390. { there is a problem if starTSec is sec_none !! PM }
  1391. if starTSec=sec_none then
  1392. starTSec:=sec_code;
  1393. end;
  1394. end;
  1395. procedure TInternalAssembler.MakeObject;
  1396. procedure addlist(p:TAAsmoutput);
  1397. begin
  1398. inc(lists);
  1399. list[lists]:=p;
  1400. end;
  1401. begin
  1402. if cs_debuginfo in aktmoduleswitches then
  1403. addlist(debuglist);
  1404. addlist(codesegment);
  1405. addlist(datasegment);
  1406. addlist(consts);
  1407. addlist(rttilist);
  1408. if assigned(resourcestringlist) then
  1409. addlist(resourcestringlist);
  1410. addlist(bsssegment);
  1411. if assigned(importssection) then
  1412. addlist(importssection);
  1413. if assigned(exportssection) and not UseDeffileForExport then
  1414. addlist(exportssection);
  1415. if assigned(resourcesection) then
  1416. addlist(resourcesection);
  1417. if SmartAsm then
  1418. writetreesmart
  1419. else
  1420. writetree;
  1421. end;
  1422. {*****************************************************************************
  1423. Generate Assembler Files Main Procedure
  1424. *****************************************************************************}
  1425. Procedure GenerateAsm(smart:boolean);
  1426. var
  1427. a : TAssembler;
  1428. begin
  1429. if not assigned(CAssembler[target_asm.id]) then
  1430. Message(asmw_f_assembler_output_not_supported);
  1431. a:=CAssembler[target_asm.id].Create(smart);
  1432. a.MakeObject;
  1433. a.Free;
  1434. end;
  1435. Procedure OnlyAsm;
  1436. var
  1437. a : TExternalAssembler;
  1438. begin
  1439. a:=TExternalAssembler.Create(false);
  1440. a.DoAssemble;
  1441. a.Free;
  1442. end;
  1443. {*****************************************************************************
  1444. Init/Done
  1445. *****************************************************************************}
  1446. procedure RegisterAssembler(const r:tasminfo;c:TAssemblerClass);
  1447. var
  1448. t : tasm;
  1449. begin
  1450. t:=r.id;
  1451. if assigned(asminfos[t]) then
  1452. writeln('Warning: Assembler is already registered!')
  1453. else
  1454. Getmem(asminfos[t],sizeof(tasminfo));
  1455. asminfos[t]^:=r;
  1456. CAssembler[t]:=c;
  1457. end;
  1458. procedure InitAssembler;
  1459. begin
  1460. { target_asm is already set by readarguments }
  1461. initoutputformat:=target_asm.id;
  1462. aktoutputformat:=target_asm.id;
  1463. end;
  1464. procedure DoneAssembler;
  1465. begin
  1466. end;
  1467. end.
  1468. {
  1469. $Log$
  1470. Revision 1.50 2003-03-10 18:16:00 olle
  1471. * niceified comments
  1472. Revision 1.49 2003/01/10 21:49:00 marco
  1473. * more hasunix fixes
  1474. Revision 1.48 2002/11/24 18:21:49 carl
  1475. - remove some unused defines
  1476. Revision 1.47 2002/11/17 16:31:55 carl
  1477. * memory optimization (3-4%) : cleanup of tai fields,
  1478. cleanup of tdef and tsym fields.
  1479. * make it work for m68k
  1480. Revision 1.46 2002/11/15 01:58:46 peter
  1481. * merged changes from 1.0.7 up to 04-11
  1482. - -V option for generating bug report tracing
  1483. - more tracing for option parsing
  1484. - errors for cdecl and high()
  1485. - win32 import stabs
  1486. - win32 records<=8 are returned in eax:edx (turned off by default)
  1487. - heaptrc update
  1488. - more info for temp management in .s file with EXTDEBUG
  1489. Revision 1.45 2002/10/30 21:01:14 peter
  1490. * always include lineno after fileswitch. valgrind requires this
  1491. Revision 1.44 2002/09/05 19:29:42 peter
  1492. * memdebug enhancements
  1493. Revision 1.43 2002/08/20 16:55:38 peter
  1494. * don't write (stabs)line info when inlining a procedure
  1495. Revision 1.42 2002/08/12 15:08:39 carl
  1496. + stab register indexes for powerpc (moved from gdb to cpubase)
  1497. + tprocessor enumeration moved to cpuinfo
  1498. + linker in target_info is now a class
  1499. * many many updates for m68k (will soon start to compile)
  1500. - removed some ifdef or correct them for correct cpu
  1501. Revision 1.41 2002/08/11 14:32:26 peter
  1502. * renamed current_library to objectlibrary
  1503. Revision 1.40 2002/08/11 13:24:10 peter
  1504. * saving of asmsymbols in ppu supported
  1505. * asmsymbollist global is removed and moved into a new class
  1506. tasmlibrarydata that will hold the info of a .a file which
  1507. corresponds with a single module. Added librarydata to tmodule
  1508. to keep the library info stored for the module. In the future the
  1509. objectfiles will also be stored to the tasmlibrarydata class
  1510. * all getlabel/newasmsymbol and friends are moved to the new class
  1511. Revision 1.39 2002/07/26 21:15:37 florian
  1512. * rewrote the system handling
  1513. Revision 1.38 2002/07/10 07:24:40 jonas
  1514. * memory leak fixes from Sergey Korshunoff
  1515. Revision 1.37 2002/07/01 18:46:21 peter
  1516. * internal linker
  1517. * reorganized aasm layer
  1518. Revision 1.36 2002/05/18 13:34:05 peter
  1519. * readded missing revisions
  1520. Revision 1.35 2002/05/16 19:46:35 carl
  1521. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  1522. + try to fix temp allocation (still in ifdef)
  1523. + generic constructor calls
  1524. + start of tassembler / tmodulebase class cleanup
  1525. Revision 1.33 2002/04/10 08:07:55 jonas
  1526. * fix for the ie9999 under Linux (patch from Peter)
  1527. Revision 1.32 2002/04/07 13:19:14 carl
  1528. + more documentation
  1529. Revision 1.31 2002/04/04 19:05:54 peter
  1530. * removed unused units
  1531. * use tlocation.size in cg.a_*loc*() routines
  1532. Revision 1.30 2002/04/02 17:11:27 peter
  1533. * tlocation,treference update
  1534. * LOC_CONSTANT added for better constant handling
  1535. * secondadd splitted in multiple routines
  1536. * location_force_reg added for loading a location to a register
  1537. of a specified size
  1538. * secondassignment parses now first the right and then the left node
  1539. (this is compatible with Kylix). This saves a lot of push/pop especially
  1540. with string operations
  1541. * adapted some routines to use the new cg methods
  1542. }