assemble.pas 51 KB

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