assemble.pas 51 KB

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