assemble.pas 51 KB

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