assemble.pas 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638
  1. {
  2. $Id$
  3. Copyright (c) 1998 by the FPC development team
  4. This unit handles the assemblerfile write and assembler calls of FPC
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************}
  17. unit assemble;
  18. interface
  19. uses
  20. {$ifdef Delphi}
  21. dmisc,
  22. {$else Delphi}
  23. dos,
  24. {$endif Delphi}
  25. cobjects,globtype,globals,aasm;
  26. const
  27. {$ifdef tp}
  28. AsmOutSize=1024;
  29. {$else}
  30. AsmOutSize=32768;
  31. {$endif}
  32. type
  33. PAsmList=^TAsmList;
  34. TAsmList=object
  35. {filenames}
  36. path : pathstr;
  37. name : namestr;
  38. asmfile, { current .s and .o file }
  39. objfile,
  40. as_bin : string;
  41. SmartAsm : boolean;
  42. place : TCutPlace; { special 'end' file for import dir ? }
  43. {outfile}
  44. AsmSize,
  45. AsmStartSize,
  46. outcnt : longint;
  47. outbuf : array[0..AsmOutSize-1] of char;
  48. outfile : file;
  49. Constructor Init(smart:boolean);
  50. Destructor Done;
  51. Function FindAssembler:string;
  52. Function CallAssembler(const command,para:string):Boolean;
  53. Function DoAssemble:boolean;
  54. Procedure RemoveAsm;
  55. procedure NextSmartName;
  56. Procedure AsmFlush;
  57. Procedure AsmClear;
  58. Procedure AsmWrite(const s:string);
  59. Procedure AsmWritePChar(p:pchar);
  60. Procedure AsmWriteLn(const s:string);
  61. Procedure AsmLn;
  62. procedure AsmCreate(Aplace:tcutplace);
  63. procedure AsmClose;
  64. procedure Synchronize;
  65. procedure WriteTree(p:paasmoutput);virtual;
  66. procedure WriteAsmList;virtual;
  67. end;
  68. Procedure GenerateAsm(smart:boolean);
  69. Procedure OnlyAsm;
  70. var
  71. SmartLinkFilesCnt : longint;
  72. Implementation
  73. uses
  74. script,files,systems,verbose
  75. {$ifdef linux}
  76. ,linux
  77. {$endif}
  78. ,strings
  79. {$ifdef i386}
  80. {$ifndef NoAg386Bin}
  81. ,ag386bin
  82. {$endif}
  83. {$ifndef NoAg386Att}
  84. ,ag386att
  85. {$endif NoAg386Att}
  86. {$ifndef NoAg386Nsm}
  87. ,ag386nsm
  88. {$endif NoAg386Nsm}
  89. {$ifndef NoAg386Int}
  90. ,ag386int
  91. {$endif NoAg386Int}
  92. {$ifdef Ag386Cof}
  93. ,ag386cof
  94. {$endif Ag386Cof}
  95. {$endif}
  96. {$ifdef m68k}
  97. {$ifndef NoAg68kGas}
  98. ,ag68kgas
  99. {$endif NoAg68kGas}
  100. {$ifndef NoAg68kMot}
  101. ,ag68kmot
  102. {$endif NoAg68kMot}
  103. {$ifndef NoAg68kMit}
  104. ,ag68kmit
  105. {$endif NoAg68kMit}
  106. {$ifndef NoAg68kMpw}
  107. ,ag68kmpw
  108. {$endif NoAg68kMpw}
  109. {$endif}
  110. ;
  111. {*****************************************************************************
  112. TAsmList
  113. *****************************************************************************}
  114. Function DoPipe:boolean;
  115. begin
  116. DoPipe:=(cs_asm_pipe in aktglobalswitches) and
  117. not(cs_asm_leave in aktglobalswitches)
  118. {$ifdef i386}
  119. and (aktoutputformat=as_i386_as)
  120. {$endif i386}
  121. {$ifdef m68k}
  122. and (aktoutputformat=as_m68k_as);
  123. {$endif m68k}
  124. end;
  125. const
  126. lastas : byte=255;
  127. var
  128. LastASBin : pathstr;
  129. Function TAsmList.FindAssembler:string;
  130. var
  131. asfound : boolean;
  132. begin
  133. if lastas<>ord(target_asm.id) then
  134. begin
  135. lastas:=ord(target_asm.id);
  136. { is an assembler passed ? }
  137. if utilsdirectory<>'' then
  138. LastASBin:=Search(target_asm.asmbin+source_os.exeext,utilsdirectory,asfound)+
  139. target_asm.asmbin+source_os.exeext;
  140. if LastASBin='' then
  141. LastASBin:=FindExe(target_asm.asmbin,asfound);
  142. if (not asfound) and not(cs_asm_extern in aktglobalswitches) then
  143. begin
  144. Message1(exec_w_assembler_not_found,LastASBin);
  145. aktglobalswitches:=aktglobalswitches+[cs_asm_extern];
  146. end;
  147. if asfound then
  148. Message1(exec_t_using_assembler,LastASBin);
  149. end;
  150. FindAssembler:=LastASBin;
  151. end;
  152. Function TAsmList.CallAssembler(const command,para:string):Boolean;
  153. begin
  154. callassembler:=true;
  155. if not(cs_asm_extern in aktglobalswitches) then
  156. begin
  157. swapvectors;
  158. exec(command,para);
  159. swapvectors;
  160. if (doserror<>0) then
  161. begin
  162. Message1(exec_w_cant_call_assembler,tostr(doserror));
  163. aktglobalswitches:=aktglobalswitches+[cs_asm_extern];
  164. callassembler:=false;
  165. end
  166. else
  167. if (dosexitcode<>0) then
  168. begin
  169. Message1(exec_w_error_while_assembling,tostr(dosexitcode));
  170. callassembler:=false;
  171. end;
  172. end
  173. else
  174. AsmRes.AddAsmCommand(command,para,name);
  175. end;
  176. procedure TAsmList.RemoveAsm;
  177. var
  178. g : file;
  179. i : word;
  180. begin
  181. if cs_asm_leave in aktglobalswitches then
  182. exit;
  183. if cs_asm_extern in aktglobalswitches then
  184. AsmRes.AddDeleteCommand(AsmFile)
  185. else
  186. begin
  187. assign(g,AsmFile);
  188. {$I-}
  189. erase(g);
  190. {$I+}
  191. i:=ioresult;
  192. end;
  193. end;
  194. Function TAsmList.DoAssemble:boolean;
  195. var
  196. s : string;
  197. begin
  198. DoAssemble:=true;
  199. if DoPipe then
  200. exit;
  201. if not(cs_asm_extern in aktglobalswitches) then
  202. begin
  203. if SmartAsm then
  204. begin
  205. if (SmartLinkFilesCnt<=1) then
  206. Message1(exec_i_assembling_smart,name);
  207. end
  208. else
  209. Message1(exec_i_assembling,name);
  210. end;
  211. s:=target_asm.asmcmd;
  212. Replace(s,'$ASM',AsmFile);
  213. Replace(s,'$OBJ',ObjFile);
  214. if CallAssembler(FindAssembler,s) then
  215. RemoveAsm
  216. else
  217. begin
  218. DoAssemble:=false;
  219. GenerateError;
  220. end;
  221. end;
  222. procedure TAsmList.NextSmartName;
  223. var
  224. s : string;
  225. begin
  226. inc(SmartLinkFilesCnt);
  227. if SmartLinkFilesCnt>999999 then
  228. Message(asmw_f_too_many_asm_files);
  229. case place of
  230. cut_begin :
  231. s:=current_module^.asmprefix^+'h';
  232. cut_normal :
  233. s:=current_module^.asmprefix^+'s';
  234. cut_end :
  235. s:=current_module^.asmprefix^+'t';
  236. end;
  237. AsmFile:=Path+FixFileName(s+tostr(SmartLinkFilesCnt)+target_info.asmext);
  238. ObjFile:=Path+FixFileName(s+tostr(SmartLinkFilesCnt)+target_info.objext);
  239. end;
  240. {*****************************************************************************
  241. TAsmList AsmFile Writing
  242. *****************************************************************************}
  243. Procedure TAsmList.AsmFlush;
  244. begin
  245. if outcnt>0 then
  246. begin
  247. BlockWrite(outfile,outbuf,outcnt);
  248. outcnt:=0;
  249. end;
  250. end;
  251. Procedure TAsmList.AsmClear;
  252. begin
  253. outcnt:=0;
  254. end;
  255. Procedure TAsmList.AsmWrite(const s:string);
  256. begin
  257. if OutCnt+length(s)>=AsmOutSize then
  258. AsmFlush;
  259. Move(s[1],OutBuf[OutCnt],length(s));
  260. inc(OutCnt,length(s));
  261. inc(AsmSize,length(s));
  262. end;
  263. Procedure TAsmList.AsmWriteLn(const s:string);
  264. begin
  265. AsmWrite(s);
  266. AsmLn;
  267. end;
  268. Procedure TAsmList.AsmWritePChar(p:pchar);
  269. var
  270. i,j : longint;
  271. begin
  272. i:=StrLen(p);
  273. j:=i;
  274. while j>0 do
  275. begin
  276. i:=min(j,AsmOutSize);
  277. if OutCnt+i>=AsmOutSize then
  278. AsmFlush;
  279. Move(p[0],OutBuf[OutCnt],i);
  280. inc(OutCnt,i);
  281. inc(AsmSize,i);
  282. dec(j,i);
  283. p:=pchar(@p[i]);
  284. end;
  285. end;
  286. Procedure TAsmList.AsmLn;
  287. begin
  288. if OutCnt>=AsmOutSize-2 then
  289. AsmFlush;
  290. OutBuf[OutCnt]:=target_os.newline[1];
  291. inc(OutCnt);
  292. inc(AsmSize);
  293. if length(target_os.newline)>1 then
  294. begin
  295. OutBuf[OutCnt]:=target_os.newline[2];
  296. inc(OutCnt);
  297. inc(AsmSize);
  298. end;
  299. end;
  300. procedure TAsmList.AsmCreate(Aplace:tcutplace);
  301. begin
  302. place:=Aplace;
  303. if SmartAsm then
  304. NextSmartName;
  305. {$ifdef linux}
  306. if DoPipe then
  307. begin
  308. Message1(exec_i_assembling_pipe,asmfile);
  309. POpen(outfile,'as -o '+objfile,'W');
  310. end
  311. else
  312. {$endif}
  313. begin
  314. Assign(outfile,asmfile);
  315. {$I-}
  316. Rewrite(outfile,1);
  317. {$I+}
  318. if ioresult<>0 then
  319. Message1(exec_d_cant_create_asmfile,asmfile);
  320. end;
  321. outcnt:=0;
  322. AsmSize:=0;
  323. AsmStartSize:=0;
  324. end;
  325. procedure TAsmList.AsmClose;
  326. var
  327. f : file;
  328. l : longint;
  329. begin
  330. AsmFlush;
  331. {$ifdef linux}
  332. if DoPipe then
  333. Close(outfile)
  334. else
  335. {$endif}
  336. begin
  337. {Touch Assembler time to ppu time is there is a ppufilename}
  338. if Assigned(current_module^.ppufilename) then
  339. begin
  340. Assign(f,current_module^.ppufilename^);
  341. {$I-}
  342. reset(f,1);
  343. {$I+}
  344. if ioresult=0 then
  345. begin
  346. getftime(f,l);
  347. close(f);
  348. reset(outfile,1);
  349. setftime(outfile,l);
  350. end;
  351. end;
  352. close(outfile);
  353. end;
  354. end;
  355. {Touch Assembler and object time to ppu time is there is a ppufilename}
  356. procedure TAsmList.Synchronize;
  357. begin
  358. {Touch Assembler time to ppu time is there is a ppufilename}
  359. if Assigned(current_module^.ppufilename) then
  360. begin
  361. SynchronizeFileTime(current_module^.ppufilename^,asmfile);
  362. if not(cs_asm_extern in aktglobalswitches) then
  363. SynchronizeFileTime(current_module^.ppufilename^,objfile);
  364. end;
  365. end;
  366. procedure TAsmList.WriteTree(p:paasmoutput);
  367. begin
  368. end;
  369. procedure TAsmList.WriteAsmList;
  370. begin
  371. end;
  372. Constructor TAsmList.Init(smart:boolean);
  373. var
  374. i : word;
  375. begin
  376. { load start values }
  377. asmfile:=current_module^.asmfilename^;
  378. objfile:=current_module^.objfilename^;
  379. name:=FixFileName(current_module^.modulename^);
  380. OutCnt:=0;
  381. SmartLinkFilesCnt:=0;
  382. place:=cut_normal;
  383. SmartAsm:=smart;
  384. { Which path will be used ? }
  385. if SmartAsm then
  386. begin
  387. path:=current_module^.path^+FixFileName(current_module^.modulename^)+target_info.smartext;
  388. {$I-}
  389. mkdir(path);
  390. {$I+}
  391. i:=ioresult;
  392. path:=FixPath(path,false);
  393. end
  394. else
  395. path:=current_module^.path^;
  396. end;
  397. Destructor TAsmList.Done;
  398. begin
  399. end;
  400. {*****************************************************************************
  401. Generate Assembler Files Main Procedure
  402. *****************************************************************************}
  403. Procedure GenerateAsm(smart:boolean);
  404. var
  405. a : PAsmList;
  406. {$ifdef i386}
  407. {$ifndef NoAg386Bin}
  408. b : Pi386binasmlist;
  409. {$endif}
  410. {$endif}
  411. begin
  412. case aktoutputformat of
  413. as_none : ;
  414. {$ifdef i386}
  415. {$ifndef NoAg386Bin}
  416. as_i386_dbg,
  417. as_i386_coff,
  418. as_i386_pecoff :
  419. begin
  420. case aktoutputformat of
  421. as_i386_dbg :
  422. b:=new(pi386binasmlist,Init(og_dbg,smart));
  423. as_i386_coff :
  424. b:=new(pi386binasmlist,Init(og_coff,smart));
  425. as_i386_pecoff :
  426. b:=new(pi386binasmlist,Init(og_pecoff,smart));
  427. end;
  428. b^.WriteBin;
  429. dispose(b,done);
  430. if assigned(current_module^.ppufilename) then
  431. begin
  432. if smart then
  433. SynchronizeFileTime(current_module^.ppufilename^,current_module^.staticlibfilename^)
  434. else
  435. SynchronizeFileTime(current_module^.ppufilename^,current_module^.objfilename^);
  436. end;
  437. exit;
  438. end;
  439. {$endif NoAg386Bin}
  440. {$ifndef NoAg386Att}
  441. as_i386_as,
  442. as_i386_as_aout,
  443. as_i386_asw :
  444. a:=new(pi386attasmlist,Init(smart));
  445. {$endif NoAg386Att}
  446. {$ifndef NoAg386Nsm}
  447. as_i386_nasmcoff,
  448. as_i386_nasmelf,
  449. as_i386_nasmobj :
  450. a:=new(pi386nasmasmlist,Init(smart));
  451. {$endif NoAg386Nsm}
  452. {$ifndef NoAg386Int}
  453. as_i386_tasm :
  454. a:=new(pi386intasmlist,Init(smart));
  455. {$endif NoAg386Int}
  456. {$endif}
  457. {$ifdef m68k}
  458. {$ifndef NoAg68kGas}
  459. as_m68k_as,
  460. as_m68k_gas :
  461. a:=new(pm68kgasasmlist,Init(smart));
  462. {$endif NoAg86KGas}
  463. {$ifndef NoAg68kMot}
  464. as_m68k_mot :
  465. a:=new(pm68kmotasmlist,Init(smart));
  466. {$endif NoAg86kMot}
  467. {$ifndef NoAg68kMit}
  468. as_m68k_mit :
  469. a:=new(pm68kmitasmlist,Init(smart));
  470. {$endif NoAg86KMot}
  471. {$ifndef NoAg68kMpw}
  472. as_m68k_mpw :
  473. a:=new(pm68kmpwasmlist,Init(smart));
  474. {$endif NoAg68kMpw}
  475. {$endif}
  476. else
  477. {$ifdef TP}
  478. exit;
  479. {$else}
  480. Message(asmw_f_assembler_output_not_supported);
  481. {$endif}
  482. end;
  483. a^.AsmCreate(cut_normal);
  484. a^.WriteAsmList;
  485. a^.AsmClose;
  486. a^.DoAssemble;
  487. a^.synchronize;
  488. dispose(a,Done);
  489. end;
  490. Procedure OnlyAsm;
  491. var
  492. a : PAsmList;
  493. begin
  494. a:=new(pasmlist,Init(false));
  495. a^.DoAssemble;
  496. dispose(a,Done);
  497. end;
  498. end.
  499. {
  500. $Log$
  501. Revision 1.56 1999-11-06 14:34:17 peter
  502. * truncated log to 20 revs
  503. Revision 1.55 1999/11/02 15:06:57 peter
  504. * import library fixes for win32
  505. * alignment works again
  506. Revision 1.54 1999/09/16 11:34:44 pierre
  507. * typo correction
  508. Revision 1.53 1999/09/02 18:47:44 daniel
  509. * Could not compile with TP, some arrays moved to heap
  510. * NOAG386BIN default for TP
  511. * AG386* files were not compatible with TP, fixed.
  512. Revision 1.52 1999/07/18 10:19:42 florian
  513. * made it compilable with Dlephi 4 again
  514. + fixed problem with large stack allocations on win32
  515. Revision 1.51 1999/07/10 10:12:03 peter
  516. * assembler smartlink message
  517. Revision 1.50 1999/07/03 00:27:05 peter
  518. * better smartlinking support
  519. Revision 1.49 1999/06/28 16:02:29 peter
  520. * merged
  521. Revision 1.48.2.1 1999/06/28 15:55:39 peter
  522. * also search path if not found in utilsdirectory
  523. Revision 1.48 1999/05/27 19:44:03 peter
  524. * removed oldasm
  525. * plabel -> pasmlabel
  526. * -a switches to source writing automaticly
  527. * assembler readers OOPed
  528. * asmsymbol automaticly external
  529. * jumptables and other label fixes for asm readers
  530. Revision 1.47 1999/05/13 21:59:19 peter
  531. * removed oldppu code
  532. * warning if objpas is loaded from uses
  533. * first things for new deref writing
  534. Revision 1.46 1999/05/05 22:21:48 peter
  535. * updated messages
  536. Revision 1.45 1999/05/04 21:44:33 florian
  537. * changes to compile it with Delphi 4.0
  538. Revision 1.44 1999/05/02 23:28:42 peter
  539. * don't include ag386bin for oldasm
  540. Revision 1.43 1999/05/02 22:41:51 peter
  541. * moved section names to systems
  542. * fixed nasm,intel writer
  543. Revision 1.42 1999/05/01 13:24:00 peter
  544. * merged nasm compiler
  545. * old asm moved to oldasm/
  546. Revision 1.41 1999/03/24 23:16:42 peter
  547. * fixed bugs 212,222,225,227,229,231,233
  548. Revision 1.40 1999/03/18 20:30:44 peter
  549. + .a writer
  550. Revision 1.39 1999/03/01 15:43:48 peter
  551. * synchronize also the objfile for ag386bin
  552. Revision 1.38 1999/02/26 00:48:15 peter
  553. * assembler writers fixed for ag386bin
  554. Revision 1.37 1999/02/24 00:59:11 peter
  555. * small updates for ag386bin
  556. }