assemble.pas 50 KB

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