assemble.pas 51 KB

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