assemble.pas 49 KB

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