assemble.pas 51 KB

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