2
0

assemble.pas 51 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706
  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. if SmartAsm then
  530. begin
  531. if (SmartFilesCount<=1) then
  532. Message1(exec_i_assembling_smart,name);
  533. end
  534. else
  535. Message1(exec_i_assembling_pipe,asmfile);
  536. POpen(outfile,FindAssembler+' '+MakeCmdLine,'W');
  537. end
  538. else
  539. {$endif}
  540. begin
  541. Assign(outfile,asmfile);
  542. {$I-}
  543. Rewrite(outfile,1);
  544. {$I+}
  545. if ioresult<>0 then
  546. begin
  547. ioerror:=true;
  548. Message1(exec_d_cant_create_asmfile,asmfile);
  549. end;
  550. end;
  551. outcnt:=0;
  552. AsmSize:=0;
  553. AsmStartSize:=0;
  554. end;
  555. procedure TExternalAssembler.AsmClose;
  556. var
  557. f : file;
  558. FileAge : longint;
  559. begin
  560. AsmFlush;
  561. {$ifdef hasunix}
  562. if DoPipe then
  563. begin
  564. if PClose(outfile) <> 0 then
  565. GenerateError;
  566. end
  567. else
  568. {$endif}
  569. begin
  570. {Touch Assembler time to ppu time is there is a ppufilename}
  571. if ppufilename<>'' then
  572. begin
  573. Assign(f,ppufilename);
  574. {$I-}
  575. reset(f,1);
  576. {$I+}
  577. if ioresult=0 then
  578. begin
  579. {$IFDEF USE_SYSUTILS}
  580. FileAge := FileGetDate(GetFileHandle(f));
  581. {$ELSE USE_SYSUTILS}
  582. GetFTime(f, FileAge);
  583. {$ENDIF USE_SYSUTILS}
  584. close(f);
  585. reset(outfile,1);
  586. {$IFDEF USE_SYSUTILS}
  587. FileSetDate(GetFileHandle(outFile),FileAge);
  588. {$ELSE USE_SYSUTILS}
  589. SetFTime(f, FileAge);
  590. {$ENDIF USE_SYSUTILS}
  591. end;
  592. end;
  593. close(outfile);
  594. end;
  595. end;
  596. procedure TExternalAssembler.WriteTree(p:TAAsmoutput);
  597. begin
  598. end;
  599. procedure TExternalAssembler.WriteAsmList;
  600. begin
  601. end;
  602. procedure TExternalAssembler.MakeObject;
  603. begin
  604. AsmCreate(cut_normal);
  605. WriteAsmList;
  606. AsmClose;
  607. if not(ioerror) then
  608. DoAssemble;
  609. end;
  610. {*****************************************************************************
  611. TInternalAssembler
  612. *****************************************************************************}
  613. constructor TInternalAssembler.create(smart:boolean);
  614. begin
  615. inherited create(smart);
  616. objectoutput:=nil;
  617. objectdata:=nil;
  618. SmartAsm:=smart;
  619. currpass:=0;
  620. end;
  621. destructor TInternalAssembler.destroy;
  622. {$ifdef MEMDEBUG}
  623. var
  624. d : tmemdebug;
  625. {$endif}
  626. begin
  627. {$ifdef MEMDEBUG}
  628. d := tmemdebug.create(name+' - agbin');
  629. {$endif}
  630. objectdata.free;
  631. objectoutput.free;
  632. {$ifdef MEMDEBUG}
  633. d.free;
  634. {$endif}
  635. end;
  636. {$ifdef GDB}
  637. procedure TInternalAssembler.convertstabs(p:pchar);
  638. var
  639. ofs,
  640. nidx,nother,ii,i,line,j : longint;
  641. code : integer;
  642. hp : pchar;
  643. reloc : boolean;
  644. ps : tasmsymbol;
  645. s : string;
  646. begin
  647. ofs:=0;
  648. reloc:=true;
  649. ps:=nil;
  650. if p[0]='"' then
  651. begin
  652. i:=1;
  653. { we can have \" inside the string !! PM }
  654. while not ((p[i]='"') and (p[i-1]<>'\')) do
  655. inc(i);
  656. p[i]:=#0;
  657. ii:=i;
  658. hp:=@p[1];
  659. s:=StrPas(@P[i+2]);
  660. end
  661. else
  662. begin
  663. hp:=nil;
  664. s:=StrPas(P);
  665. i:=-2; {needed below (PM) }
  666. end;
  667. { When in pass 1 then only alloc and leave }
  668. if currpass=1 then
  669. begin
  670. objectdata.allocstabs(hp);
  671. if assigned(hp) then
  672. p[i]:='"';
  673. exit;
  674. end;
  675. { Parse the rest of the stabs }
  676. if s='' then
  677. internalerror(33000);
  678. j:=pos(',',s);
  679. if j=0 then
  680. internalerror(33001);
  681. Val(Copy(s,1,j-1),nidx,code);
  682. if code<>0 then
  683. internalerror(33002);
  684. i:=i+2+j;
  685. Delete(s,1,j);
  686. j:=pos(',',s);
  687. if (j=0) then
  688. internalerror(33003);
  689. Val(Copy(s,1,j-1),nother,code);
  690. if code<>0 then
  691. internalerror(33004);
  692. i:=i+j;
  693. Delete(s,1,j);
  694. j:=pos(',',s);
  695. if j=0 then
  696. begin
  697. j:=256;
  698. ofs:=-1;
  699. end;
  700. Val(Copy(s,1,j-1),line,code);
  701. if code<>0 then
  702. internalerror(33005);
  703. if ofs=0 then
  704. begin
  705. Delete(s,1,j);
  706. i:=i+j;
  707. Val(s,ofs,code);
  708. if code=0 then
  709. reloc:=false
  710. else
  711. begin
  712. ofs:=0;
  713. s:=strpas(@p[i]);
  714. { handle asmsymbol or
  715. asmsymbol - asmsymbol }
  716. j:=pos(' ',s);
  717. if j=0 then
  718. j:=pos('-',s);
  719. { also try to handle
  720. asmsymbol + constant
  721. or
  722. asmsymbol - constant }
  723. if j=0 then
  724. j:=pos('+',s);
  725. if j<>0 then
  726. begin
  727. Val(Copy(s,j+1,255),ofs,code);
  728. if code<>0 then
  729. ofs:=0
  730. else
  731. { constant reading successful,
  732. avoid further treatment by
  733. setting s[j] to '+' }
  734. s[j]:='+';
  735. end
  736. else
  737. { single asmsymbol }
  738. j:=256;
  739. { the symbol can be external
  740. so we must use newasmsymbol and
  741. not getasmsymbol !! PM }
  742. ps:=objectlibrary.newasmsymbol(copy(s,1,j-1),AB_EXTERNAL,AT_NONE);
  743. if not assigned(ps) then
  744. internalerror(33006)
  745. else
  746. begin
  747. ofs:=ofs+ps.address;
  748. reloc:=true;
  749. objectlibrary.UsedAsmSymbolListInsert(ps);
  750. end;
  751. if (j<256) and (s[j]<>'+') then
  752. begin
  753. i:=i+j;
  754. s:=strpas(@p[i]);
  755. if (s<>'') and (s[1]=' ') then
  756. begin
  757. j:=0;
  758. while (s[j+1]=' ') do
  759. inc(j);
  760. i:=i+j;
  761. s:=strpas(@p[i]);
  762. end;
  763. ps:=objectlibrary.getasmsymbol(s);
  764. if not assigned(ps) then
  765. internalerror(33007)
  766. else
  767. begin
  768. if ps.section<>objectdata.currsec then
  769. internalerror(33008);
  770. ofs:=ofs-ps.address;
  771. reloc:=false;
  772. objectlibrary.UsedAsmSymbolListInsert(ps);
  773. end;
  774. end;
  775. end;
  776. end;
  777. { External references (AB_EXTERNAL and AB_COMMON) need a symbol relocation }
  778. if assigned(ps) and (ps.currbind in [AB_EXTERNAL,AB_COMMON]) then
  779. begin
  780. if currpass=2 then
  781. begin
  782. objectdata.writesymbol(ps);
  783. objectoutput.exportsymbol(ps);
  784. end;
  785. objectdata.writeSymStabs(ofs,hp,ps,nidx,nother,line,reloc)
  786. end
  787. else
  788. objectdata.writeStabs(ofs,hp,nidx,nother,line,reloc);
  789. if assigned(hp) then
  790. p[ii]:='"';
  791. end;
  792. procedure TInternalAssembler.emitlineinfostabs(nidx,line : longint);
  793. begin
  794. if currpass=1 then
  795. begin
  796. objectdata.allocstabs(nil);
  797. exit;
  798. end;
  799. if (nidx=n_textline) and assigned(funcname) and
  800. (target_info.use_function_relative_addresses) then
  801. objectdata.writeStabs(objectdata.currsec.datasize-funcname.address,nil,nidx,0,line,false)
  802. else
  803. objectdata.writeStabs(objectdata.currsec.datasize,nil,nidx,0,line,true);
  804. end;
  805. procedure TInternalAssembler.emitstabs(s:string);
  806. begin
  807. s:=s+#0;
  808. ConvertStabs(@s[1]);
  809. end;
  810. procedure TInternalAssembler.WriteFileLineInfo(var fileinfo : tfileposinfo);
  811. var
  812. curr_n : byte;
  813. hp : tasmsymbol;
  814. infile : tinputfile;
  815. begin
  816. if not ((cs_debuginfo in aktmoduleswitches) or
  817. (cs_gdb_lineinfo in aktglobalswitches)) then
  818. exit;
  819. { file changed ? (must be before line info) }
  820. if (fileinfo.fileindex<>0) and
  821. (stabslastfileinfo.fileindex<>fileinfo.fileindex) then
  822. begin
  823. infile:=current_module.sourcefiles.get_file(fileinfo.fileindex);
  824. if assigned(infile) then
  825. begin
  826. if includecount=0 then
  827. curr_n:=n_sourcefile
  828. else
  829. curr_n:=n_includefile;
  830. { get symbol for this includefile }
  831. hp:=objectlibrary.newasmsymbol('Ltext'+ToStr(IncludeCount),AB_LOCAL,AT_FUNCTION);
  832. if currpass=1 then
  833. begin
  834. objectdata.allocsymbol(currpass,hp,0);
  835. objectlibrary.UsedAsmSymbolListInsert(hp);
  836. end
  837. else
  838. objectdata.writesymbol(hp);
  839. { emit stabs }
  840. if (infile.path^<>'') then
  841. EmitStabs('"'+BsToSlash(FixPath(infile.path^,false))+'",'+tostr(curr_n)+
  842. ',0,0,Ltext'+ToStr(IncludeCount));
  843. EmitStabs('"'+FixFileName(infile.name^)+'",'+tostr(curr_n)+
  844. ',0,0,Ltext'+ToStr(IncludeCount));
  845. inc(includecount);
  846. { force new line info }
  847. stabslastfileinfo.line:=-1;
  848. end;
  849. end;
  850. { line changed ? }
  851. if (stabslastfileinfo.line<>fileinfo.line) and (fileinfo.line<>0) then
  852. emitlineinfostabs(n_line,fileinfo.line);
  853. stabslastfileinfo:=fileinfo;
  854. end;
  855. procedure TInternalAssembler.StartFileLineInfo;
  856. var
  857. fileinfo : tfileposinfo;
  858. begin
  859. FillChar(stabslastfileinfo,sizeof(stabslastfileinfo),0);
  860. n_line:=n_bssline;
  861. funcname:=nil;
  862. linecount:=1;
  863. includecount:=0;
  864. fileinfo.fileindex:=1;
  865. fileinfo.line:=1;
  866. WriteFileLineInfo(fileinfo);
  867. end;
  868. procedure TInternalAssembler.EndFileLineInfo;
  869. var
  870. hp : tasmsymbol;
  871. begin
  872. if not ((cs_debuginfo in aktmoduleswitches) or
  873. (cs_gdb_lineinfo in aktglobalswitches)) then
  874. exit;
  875. objectdata.createsection(sec_code,'',0,[]);
  876. hp:=objectlibrary.newasmsymbol('Letext',AB_LOCAL,AT_FUNCTION);
  877. if currpass=1 then
  878. begin
  879. objectdata.allocsymbol(currpass,hp,0);
  880. objectlibrary.UsedAsmSymbolListInsert(hp);
  881. end
  882. else
  883. objectdata.writesymbol(hp);
  884. EmitStabs('"",'+tostr(n_sourcefile)+',0,0,Letext');
  885. end;
  886. {$endif GDB}
  887. function TInternalAssembler.MaybeNextList(var hp:Tai):boolean;
  888. begin
  889. { maybe end of list }
  890. while not assigned(hp) do
  891. begin
  892. if currlistidx<lists then
  893. begin
  894. inc(currlistidx);
  895. currlist:=list[currlistidx];
  896. hp:=Tai(currList.first);
  897. end
  898. else
  899. begin
  900. MaybeNextList:=false;
  901. exit;
  902. end;
  903. end;
  904. MaybeNextList:=true;
  905. end;
  906. function TInternalAssembler.TreePass0(hp:Tai):Tai;
  907. var
  908. l : longint;
  909. begin
  910. while assigned(hp) do
  911. begin
  912. case hp.typ of
  913. ait_align :
  914. begin
  915. { always use the maximum fillsize in this pass to avoid possible
  916. short jumps to become out of range }
  917. Tai_align_abstract(hp).fillsize:=Tai_align_abstract(hp).aligntype;
  918. objectdata.alloc(Tai_align_abstract(hp).fillsize);
  919. end;
  920. ait_datablock :
  921. begin
  922. l:=used_align(size_2_align(Tai_datablock(hp).size),0,objectdata.currsec.addralign);
  923. if SmartAsm or (not Tai_datablock(hp).is_global) then
  924. begin
  925. objectdata.allocalign(l);
  926. objectdata.alloc(Tai_datablock(hp).size);
  927. end;
  928. end;
  929. ait_real_80bit :
  930. objectdata.alloc(10);
  931. ait_real_64bit :
  932. objectdata.alloc(8);
  933. ait_real_32bit :
  934. objectdata.alloc(4);
  935. ait_comp_64bit :
  936. objectdata.alloc(8);
  937. ait_const_64bit,
  938. ait_const_32bit,
  939. ait_const_16bit,
  940. ait_const_8bit,
  941. ait_const_rva_symbol,
  942. ait_const_indirect_symbol :
  943. objectdata.alloc(tai_const(hp).size);
  944. ait_section:
  945. begin
  946. objectdata.CreateSection(Tai_section(hp).sectype,Tai_section(hp).name^,Tai_section(hp).secalign,[]);
  947. Tai_section(hp).sec:=objectdata.CurrSec;
  948. end;
  949. ait_symbol :
  950. objectdata.allocsymbol(currpass,Tai_symbol(hp).sym,0);
  951. ait_label :
  952. objectdata.allocsymbol(currpass,Tai_label(hp).l,0);
  953. ait_string :
  954. objectdata.alloc(Tai_string(hp).len);
  955. ait_instruction :
  956. begin
  957. {$ifdef i386}
  958. {$ifndef NOAG386BIN}
  959. { reset instructions which could change in pass 2 }
  960. Taicpu(hp).resetpass2;
  961. objectdata.alloc(Taicpu(hp).Pass1(objectdata.currsec.datasize));
  962. {$endif NOAG386BIN}
  963. {$endif i386}
  964. end;
  965. ait_cutobject :
  966. if SmartAsm then
  967. break;
  968. end;
  969. hp:=Tai(hp.next);
  970. end;
  971. TreePass0:=hp;
  972. end;
  973. function TInternalAssembler.TreePass1(hp:Tai):Tai;
  974. var
  975. InlineLevel,
  976. l : longint;
  977. {$ifdef i386}
  978. {$ifndef NOAG386BIN}
  979. i : longint;
  980. {$endif NOAG386BIN}
  981. {$endif i386}
  982. begin
  983. inlinelevel:=0;
  984. while assigned(hp) do
  985. begin
  986. {$ifdef GDB}
  987. { write stabs, no line info for inlined code }
  988. if (inlinelevel=0) and
  989. ((cs_debuginfo in aktmoduleswitches) or
  990. (cs_gdb_lineinfo in aktglobalswitches)) then
  991. begin
  992. if (objectdata.currsec<>nil) and
  993. not(hp.typ in SkipLineInfo) then
  994. WriteFileLineInfo(tailineinfo(hp).fileinfo);
  995. end;
  996. {$endif GDB}
  997. case hp.typ of
  998. ait_align :
  999. begin
  1000. { here we must determine the fillsize which is used in pass2 }
  1001. Tai_align_abstract(hp).fillsize:=align(objectdata.currsec.datasize,Tai_align_abstract(hp).aligntype)-
  1002. objectdata.currsec.datasize;
  1003. objectdata.alloc(Tai_align_abstract(hp).fillsize);
  1004. end;
  1005. ait_datablock :
  1006. begin
  1007. if objectdata.currsec.sectype<>sec_bss then
  1008. Message(asmw_e_alloc_data_only_in_bss);
  1009. l:=used_align(size_2_align(Tai_datablock(hp).size),0,objectdata.currsec.addralign);
  1010. if Tai_datablock(hp).is_global and
  1011. not SmartAsm then
  1012. begin
  1013. objectdata.allocsymbol(currpass,Tai_datablock(hp).sym,Tai_datablock(hp).size);
  1014. { force to be common/external, must be after setaddress as that would
  1015. set it to AB_GLOBAL }
  1016. Tai_datablock(hp).sym.currbind:=AB_COMMON;
  1017. end
  1018. else
  1019. begin
  1020. objectdata.allocalign(l);
  1021. objectdata.allocsymbol(currpass,Tai_datablock(hp).sym,Tai_datablock(hp).size);
  1022. objectdata.alloc(Tai_datablock(hp).size);
  1023. end;
  1024. objectlibrary.UsedAsmSymbolListInsert(Tai_datablock(hp).sym);
  1025. end;
  1026. ait_real_80bit :
  1027. objectdata.alloc(10);
  1028. ait_real_64bit :
  1029. objectdata.alloc(8);
  1030. ait_real_32bit :
  1031. objectdata.alloc(4);
  1032. ait_comp_64bit :
  1033. objectdata.alloc(8);
  1034. ait_const_64bit,
  1035. ait_const_32bit,
  1036. ait_const_16bit,
  1037. ait_const_8bit,
  1038. ait_const_rva_symbol,
  1039. ait_const_indirect_symbol :
  1040. begin
  1041. objectdata.alloc(tai_const(hp).size);
  1042. if assigned(Tai_const(hp).sym) then
  1043. objectlibrary.UsedAsmSymbolListInsert(Tai_const(hp).sym);
  1044. if assigned(Tai_const(hp).endsym) then
  1045. objectlibrary.UsedAsmSymbolListInsert(Tai_const(hp).endsym);
  1046. end;
  1047. ait_section:
  1048. begin
  1049. { use cached value }
  1050. objectdata.setsection(Tai_section(hp).sec);
  1051. {$ifdef GDB}
  1052. case Tai_section(hp).sectype of
  1053. sec_code :
  1054. n_line:=n_textline;
  1055. sec_data :
  1056. n_line:=n_dataline;
  1057. sec_bss :
  1058. n_line:=n_bssline;
  1059. else
  1060. n_line:=n_dataline;
  1061. end;
  1062. stabslastfileinfo.line:=-1;
  1063. {$endif GDB}
  1064. end;
  1065. {$ifdef GDB}
  1066. ait_stabn :
  1067. begin
  1068. if assigned(Tai_stabn(hp).str) then
  1069. convertstabs(Tai_stabn(hp).str);
  1070. end;
  1071. ait_stabs :
  1072. begin
  1073. if assigned(Tai_stabs(hp).str) then
  1074. convertstabs(Tai_stabs(hp).str);
  1075. end;
  1076. ait_stab_function_name :
  1077. begin
  1078. if assigned(Tai_stab_function_name(hp).str) then
  1079. begin
  1080. funcname:=objectlibrary.getasmsymbol(strpas(Tai_stab_function_name(hp).str));
  1081. objectlibrary.UsedAsmSymbolListInsert(funcname);
  1082. end
  1083. else
  1084. funcname:=nil;
  1085. end;
  1086. ait_force_line :
  1087. stabslastfileinfo.line:=0;
  1088. {$endif}
  1089. ait_symbol :
  1090. begin
  1091. objectdata.allocsymbol(currpass,Tai_symbol(hp).sym,0);
  1092. objectlibrary.UsedAsmSymbolListInsert(Tai_symbol(hp).sym);
  1093. end;
  1094. ait_symbol_end :
  1095. begin
  1096. if target_info.system in [system_i386_linux,system_i386_beos] then
  1097. begin
  1098. Tai_symbol_end(hp).sym.size:=objectdata.currsec.datasize-Tai_symbol_end(hp).sym.address;
  1099. objectlibrary.UsedAsmSymbolListInsert(Tai_symbol_end(hp).sym);
  1100. end;
  1101. end;
  1102. ait_label :
  1103. begin
  1104. objectdata.allocsymbol(currpass,Tai_label(hp).l,0);
  1105. objectlibrary.UsedAsmSymbolListInsert(Tai_label(hp).l);
  1106. end;
  1107. ait_string :
  1108. objectdata.alloc(Tai_string(hp).len);
  1109. ait_instruction :
  1110. begin
  1111. {$ifdef i386}
  1112. {$ifndef NOAG386BIN}
  1113. objectdata.alloc(Taicpu(hp).Pass1(objectdata.currsec.datasize));
  1114. { fixup the references }
  1115. for i:=1 to Taicpu(hp).ops do
  1116. begin
  1117. with Taicpu(hp).oper[i-1]^ do
  1118. begin
  1119. case typ of
  1120. top_ref :
  1121. begin
  1122. if assigned(ref^.symbol) then
  1123. objectlibrary.UsedAsmSymbolListInsert(ref^.symbol);
  1124. if assigned(ref^.relsymbol) then
  1125. objectlibrary.UsedAsmSymbolListInsert(ref^.symbol);
  1126. end;
  1127. end;
  1128. end;
  1129. end;
  1130. {$endif NOAG386BIN}
  1131. {$endif i386}
  1132. end;
  1133. ait_direct :
  1134. Message(asmw_f_direct_not_supported);
  1135. ait_cutobject :
  1136. if SmartAsm then
  1137. break;
  1138. ait_marker :
  1139. if tai_marker(hp).kind=InlineStart then
  1140. inc(InlineLevel)
  1141. else if tai_marker(hp).kind=InlineEnd then
  1142. dec(InlineLevel);
  1143. end;
  1144. hp:=Tai(hp.next);
  1145. end;
  1146. TreePass1:=hp;
  1147. end;
  1148. function TInternalAssembler.TreePass2(hp:Tai):Tai;
  1149. var
  1150. fillbuffer : tfillbuffer;
  1151. InlineLevel,
  1152. l : longint;
  1153. v : int64;
  1154. {$ifdef x86}
  1155. co : comp;
  1156. {$endif x86}
  1157. begin
  1158. inlinelevel:=0;
  1159. { main loop }
  1160. while assigned(hp) do
  1161. begin
  1162. {$ifdef GDB}
  1163. { write stabs, no line info for inlined code }
  1164. if (inlinelevel=0) and
  1165. ((cs_debuginfo in aktmoduleswitches) or
  1166. (cs_gdb_lineinfo in aktglobalswitches)) then
  1167. begin
  1168. if (objectdata.currsec<>nil) and
  1169. not(hp.typ in SkipLineInfo) then
  1170. WriteFileLineInfo(tailineinfo(hp).fileinfo);
  1171. end;
  1172. {$endif GDB}
  1173. case hp.typ of
  1174. ait_align :
  1175. begin
  1176. if objectdata.currsec.sectype=sec_bss then
  1177. objectdata.alloc(Tai_align_abstract(hp).fillsize)
  1178. else
  1179. objectdata.writebytes(Tai_align_abstract(hp).calculatefillbuf(fillbuffer)^,Tai_align_abstract(hp).fillsize);
  1180. end;
  1181. ait_section :
  1182. begin
  1183. { use cached value }
  1184. objectdata.setsection(Tai_section(hp).sec);
  1185. {$ifdef GDB}
  1186. case Tai_section(hp).sectype of
  1187. sec_code : n_line:=n_textline;
  1188. sec_data : n_line:=n_dataline;
  1189. sec_bss : n_line:=n_bssline;
  1190. else
  1191. n_line:=n_dataline;
  1192. end;
  1193. stabslastfileinfo.line:=-1;
  1194. {$endif GDB}
  1195. end;
  1196. ait_symbol :
  1197. begin
  1198. objectdata.writesymbol(Tai_symbol(hp).sym);
  1199. objectoutput.exportsymbol(Tai_symbol(hp).sym);
  1200. end;
  1201. ait_datablock :
  1202. begin
  1203. l:=used_align(size_2_align(Tai_datablock(hp).size),0,objectdata.currsec.addralign);
  1204. objectdata.writesymbol(Tai_datablock(hp).sym);
  1205. objectoutput.exportsymbol(Tai_datablock(hp).sym);
  1206. if SmartAsm or (not Tai_datablock(hp).is_global) then
  1207. begin
  1208. objectdata.allocalign(l);
  1209. objectdata.alloc(Tai_datablock(hp).size);
  1210. end;
  1211. end;
  1212. ait_real_80bit :
  1213. objectdata.writebytes(Tai_real_80bit(hp).value,10);
  1214. ait_real_64bit :
  1215. objectdata.writebytes(Tai_real_64bit(hp).value,8);
  1216. ait_real_32bit :
  1217. objectdata.writebytes(Tai_real_32bit(hp).value,4);
  1218. ait_comp_64bit :
  1219. begin
  1220. {$ifdef x86}
  1221. {$ifdef FPC}
  1222. co:=comp(Tai_comp_64bit(hp).value);
  1223. {$else}
  1224. co:=Tai_comp_64bit(hp).value;
  1225. {$endif}
  1226. objectdata.writebytes(co,8);
  1227. {$endif x86}
  1228. end;
  1229. ait_string :
  1230. objectdata.writebytes(Tai_string(hp).str^,Tai_string(hp).len);
  1231. ait_const_64bit,
  1232. ait_const_32bit,
  1233. ait_const_16bit,
  1234. ait_const_8bit :
  1235. begin
  1236. if assigned(tai_const(hp).sym) then
  1237. begin
  1238. if assigned(tai_const(hp).endsym) then
  1239. begin
  1240. if tai_const(hp).endsym.section<>tai_const(hp).sym.section then
  1241. internalerror(200404124);
  1242. v:=tai_const(hp).endsym.address-tai_const(hp).sym.address+Tai_const(hp).value;
  1243. objectdata.writebytes(v,tai_const(hp).size);
  1244. end
  1245. else
  1246. objectdata.writereloc(Tai_const(hp).value,Tai_const(hp).size,Tai_const(hp).sym,RELOC_ABSOLUTE);
  1247. end
  1248. else
  1249. objectdata.writebytes(Tai_const(hp).value,tai_const(hp).size);
  1250. end;
  1251. ait_const_rva_symbol :
  1252. objectdata.writereloc(Tai_const(hp).value,sizeof(aint),Tai_const(hp).sym,RELOC_RVA);
  1253. ait_label :
  1254. begin
  1255. objectdata.writesymbol(Tai_label(hp).l);
  1256. { exporting shouldn't be necessary as labels are local,
  1257. but it's better to be on the safe side (PFV) }
  1258. objectoutput.exportsymbol(Tai_label(hp).l);
  1259. end;
  1260. {$ifdef i386}
  1261. {$ifndef NOAG386BIN}
  1262. ait_instruction :
  1263. Taicpu(hp).Pass2(objectdata);
  1264. {$endif NOAG386BIN}
  1265. {$endif i386}
  1266. {$ifdef GDB}
  1267. ait_stabn :
  1268. convertstabs(Tai_stabn(hp).str);
  1269. ait_stabs :
  1270. convertstabs(Tai_stabs(hp).str);
  1271. ait_stab_function_name :
  1272. if assigned(Tai_stab_function_name(hp).str) then
  1273. funcname:=objectlibrary.getasmsymbol(strpas(Tai_stab_function_name(hp).str))
  1274. else
  1275. funcname:=nil;
  1276. ait_force_line :
  1277. stabslastfileinfo.line:=0;
  1278. {$endif}
  1279. ait_cutobject :
  1280. if SmartAsm then
  1281. break;
  1282. ait_marker :
  1283. if tai_marker(hp).kind=InlineStart then
  1284. inc(InlineLevel)
  1285. else if tai_marker(hp).kind=InlineEnd then
  1286. dec(InlineLevel);
  1287. end;
  1288. hp:=Tai(hp.next);
  1289. end;
  1290. TreePass2:=hp;
  1291. end;
  1292. procedure TInternalAssembler.writetree;
  1293. var
  1294. hp : Tai;
  1295. label
  1296. doexit;
  1297. begin
  1298. objectdata:=objectoutput.newobjectdata(Objfile);
  1299. { reset the asmsymbol list }
  1300. objectlibrary.CreateUsedAsmsymbolList;
  1301. { Pass 0 }
  1302. currpass:=0;
  1303. objectdata.createsection(sec_code,'',0,[]);
  1304. objectdata.beforealloc;
  1305. { start with list 1 }
  1306. currlistidx:=1;
  1307. currlist:=list[currlistidx];
  1308. hp:=Tai(currList.first);
  1309. while assigned(hp) do
  1310. begin
  1311. hp:=TreePass0(hp);
  1312. MaybeNextList(hp);
  1313. end;
  1314. objectdata.afteralloc;
  1315. { leave if errors have occured }
  1316. if errorcount>0 then
  1317. goto doexit;
  1318. { Pass 1 }
  1319. currpass:=1;
  1320. objectdata.resetsections;
  1321. objectdata.beforealloc;
  1322. objectdata.createsection(sec_code,'',0,[]);
  1323. {$ifdef GDB}
  1324. StartFileLineInfo;
  1325. {$endif GDB}
  1326. { start with list 1 }
  1327. currlistidx:=1;
  1328. currlist:=list[currlistidx];
  1329. hp:=Tai(currList.first);
  1330. while assigned(hp) do
  1331. begin
  1332. hp:=TreePass1(hp);
  1333. MaybeNextList(hp);
  1334. end;
  1335. {$ifdef GDB}
  1336. EndFileLineInfo;
  1337. {$endif GDB}
  1338. objectdata.afteralloc;
  1339. { check for undefined labels and reset }
  1340. objectlibrary.UsedAsmSymbolListCheckUndefined;
  1341. { leave if errors have occured }
  1342. if errorcount>0 then
  1343. goto doexit;
  1344. { Pass 2 }
  1345. currpass:=2;
  1346. objectdata.resetsections;
  1347. objectdata.beforewrite;
  1348. objectdata.createsection(sec_code,'',0,[]);
  1349. {$ifdef GDB}
  1350. StartFileLineInfo;
  1351. {$endif GDB}
  1352. { start with list 1 }
  1353. currlistidx:=1;
  1354. currlist:=list[currlistidx];
  1355. hp:=Tai(currList.first);
  1356. while assigned(hp) do
  1357. begin
  1358. hp:=TreePass2(hp);
  1359. MaybeNextList(hp);
  1360. end;
  1361. {$ifdef GDB}
  1362. EndFileLineInfo;
  1363. {$endif GDB}
  1364. objectdata.afterwrite;
  1365. { don't write the .o file if errors have occured }
  1366. if errorcount=0 then
  1367. begin
  1368. { write objectfile }
  1369. objectoutput.startobjectfile(ObjFile);
  1370. objectoutput.writeobjectfile(objectdata);
  1371. objectdata.free;
  1372. objectdata:=nil;
  1373. end;
  1374. doexit:
  1375. { reset the used symbols back, must be after the .o has been
  1376. written }
  1377. objectlibrary.UsedAsmsymbolListReset;
  1378. objectlibrary.DestroyUsedAsmsymbolList;
  1379. end;
  1380. procedure TInternalAssembler.writetreesmart;
  1381. var
  1382. hp : Tai;
  1383. startsectype : TAsmSectionType;
  1384. place: tcutplace;
  1385. begin
  1386. NextSmartName(cut_normal);
  1387. objectdata:=objectoutput.newobjectdata(Objfile);
  1388. startsectype:=sec_code;
  1389. { start with list 1 }
  1390. currlistidx:=1;
  1391. currlist:=list[currlistidx];
  1392. hp:=Tai(currList.first);
  1393. while assigned(hp) do
  1394. begin
  1395. { reset the asmsymbol list }
  1396. objectlibrary.CreateUsedAsmSymbolList;
  1397. { Pass 0 }
  1398. currpass:=0;
  1399. objectdata.resetsections;
  1400. objectdata.beforealloc;
  1401. objectdata.createsection(startsectype,'',0,[]);
  1402. TreePass0(hp);
  1403. objectdata.afteralloc;
  1404. { leave if errors have occured }
  1405. if errorcount>0 then
  1406. exit;
  1407. { Pass 1 }
  1408. currpass:=1;
  1409. objectdata.resetsections;
  1410. objectdata.beforealloc;
  1411. objectdata.createsection(startsectype,'',0,[]);
  1412. {$ifdef GDB}
  1413. StartFileLineInfo;
  1414. {$endif GDB}
  1415. TreePass1(hp);
  1416. {$ifdef GDB}
  1417. EndFileLineInfo;
  1418. {$endif GDB}
  1419. objectdata.afteralloc;
  1420. { check for undefined labels }
  1421. objectlibrary.UsedAsmSymbolListCheckUndefined;
  1422. { leave if errors have occured }
  1423. if errorcount>0 then
  1424. exit;
  1425. { Pass 2 }
  1426. currpass:=2;
  1427. objectoutput.startobjectfile(Objfile);
  1428. objectdata.resetsections;
  1429. objectdata.beforewrite;
  1430. objectdata.createsection(startsectype,'',0,[]);
  1431. {$ifdef GDB}
  1432. StartFileLineInfo;
  1433. {$endif GDB}
  1434. hp:=TreePass2(hp);
  1435. { save section type for next loop, must be done before EndFileLineInfo
  1436. because that changes the section to sec_code }
  1437. startsectype:=objectdata.currsec.sectype;
  1438. {$ifdef GDB}
  1439. EndFileLineInfo;
  1440. {$endif GDB}
  1441. objectdata.afterwrite;
  1442. { leave if errors have occured }
  1443. if errorcount>0 then
  1444. exit;
  1445. { write the current objectfile }
  1446. objectoutput.writeobjectfile(objectdata);
  1447. objectdata.free;
  1448. objectdata:=nil;
  1449. { reset the used symbols back, must be after the .o has been
  1450. written }
  1451. objectlibrary.UsedAsmsymbolListReset;
  1452. objectlibrary.DestroyUsedAsmsymbolList;
  1453. { end of lists? }
  1454. if not MaybeNextList(hp) then
  1455. break;
  1456. { we will start a new objectfile so reset everything }
  1457. { The place can still change in the next while loop, so don't init }
  1458. { the writer yet (JM) }
  1459. if (hp.typ=ait_cutobject) then
  1460. place := Tai_cutobject(hp).place
  1461. else
  1462. place := cut_normal;
  1463. { avoid empty files }
  1464. while assigned(hp) and
  1465. (Tai(hp).typ in [ait_marker,ait_comment,ait_section,ait_cutobject]) do
  1466. begin
  1467. if Tai(hp).typ=ait_section then
  1468. startsectype:=Tai_section(hp).sectype
  1469. else if (Tai(hp).typ=ait_cutobject) then
  1470. place:=Tai_cutobject(hp).place;
  1471. hp:=Tai(hp.next);
  1472. end;
  1473. { there is a problem if startsectype is sec_none !! PM }
  1474. if startsectype=sec_none then
  1475. startsectype:=sec_code;
  1476. if not MaybeNextList(hp) then
  1477. break;
  1478. { start next objectfile }
  1479. NextSmartName(place);
  1480. objectdata:=objectoutput.newobjectdata(Objfile);
  1481. end;
  1482. end;
  1483. procedure TInternalAssembler.MakeObject;
  1484. procedure addlist(p:TAAsmoutput);
  1485. begin
  1486. inc(lists);
  1487. list[lists]:=p;
  1488. end;
  1489. begin
  1490. if cs_debuginfo in aktmoduleswitches then
  1491. addlist(debuglist);
  1492. addlist(codesegment);
  1493. addlist(datasegment);
  1494. addlist(consts);
  1495. addlist(rttilist);
  1496. addlist(picdata);
  1497. if assigned(resourcestringlist) then
  1498. addlist(resourcestringlist);
  1499. addlist(bsssegment);
  1500. if assigned(importssection) then
  1501. addlist(importssection);
  1502. if assigned(exportssection) and not UseDeffileForExports then
  1503. addlist(exportssection);
  1504. if assigned(resourcesection) then
  1505. addlist(resourcesection);
  1506. {$warning TODO internal writer support for dwarf}
  1507. {if assigned(dwarflist) then
  1508. addlist(dwarflist);}
  1509. if SmartAsm then
  1510. writetreesmart
  1511. else
  1512. writetree;
  1513. end;
  1514. {*****************************************************************************
  1515. Generate Assembler Files Main Procedure
  1516. *****************************************************************************}
  1517. Procedure GenerateAsm(smart:boolean);
  1518. var
  1519. a : TAssembler;
  1520. begin
  1521. if not assigned(CAssembler[target_asm.id]) then
  1522. Message(asmw_f_assembler_output_not_supported);
  1523. a:=CAssembler[target_asm.id].Create(smart);
  1524. a.MakeObject;
  1525. a.Free;
  1526. end;
  1527. Procedure OnlyAsm;
  1528. var
  1529. a : TExternalAssembler;
  1530. begin
  1531. a:=TExternalAssembler.Create(false);
  1532. a.DoAssemble;
  1533. a.Free;
  1534. end;
  1535. {*****************************************************************************
  1536. Init/Done
  1537. *****************************************************************************}
  1538. procedure RegisterAssembler(const r:tasminfo;c:TAssemblerClass);
  1539. var
  1540. t : tasm;
  1541. begin
  1542. t:=r.id;
  1543. if assigned(asminfos[t]) then
  1544. writeln('Warning: Assembler is already registered!')
  1545. else
  1546. Getmem(asminfos[t],sizeof(tasminfo));
  1547. asminfos[t]^:=r;
  1548. CAssembler[t]:=c;
  1549. end;
  1550. procedure InitAssembler;
  1551. begin
  1552. { target_asm is already set by readarguments }
  1553. initoutputformat:=target_asm.id;
  1554. aktoutputformat:=target_asm.id;
  1555. end;
  1556. procedure DoneAssembler;
  1557. begin
  1558. end;
  1559. end.