assemble.pas 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691
  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. dos,cobjects,globtype,globals,aasm;
  21. const
  22. {$ifdef tp}
  23. AsmOutSize=1024;
  24. {$else}
  25. AsmOutSize=32768;
  26. {$endif}
  27. type
  28. PAsmList=^TAsmList;
  29. TAsmList=object
  30. {filenames}
  31. path : pathstr;
  32. name : namestr;
  33. asmfile, { current .s and .o file }
  34. objfile,
  35. as_bin : string;
  36. IsEndFile : boolean; { special 'end' file for import dir ? }
  37. {outfile}
  38. AsmSize,
  39. AsmStartSize,
  40. outcnt : longint;
  41. outbuf : array[0..AsmOutSize-1] of char;
  42. outfile : file;
  43. Constructor Init;
  44. Destructor Done;
  45. Function FindAssembler:string;
  46. Function CallAssembler(const command,para:string):Boolean;
  47. Function DoAssemble:boolean;
  48. Procedure RemoveAsm;
  49. procedure NextSmartName;
  50. Procedure AsmFlush;
  51. Procedure AsmClear;
  52. Procedure AsmWrite(const s:string);
  53. Procedure AsmWritePChar(p:pchar);
  54. Procedure AsmWriteLn(const s:string);
  55. Procedure AsmLn;
  56. procedure AsmCreate;
  57. procedure AsmClose;
  58. procedure Synchronize;
  59. procedure WriteTree(p:paasmoutput);virtual;
  60. procedure WriteAsmList;virtual;
  61. end;
  62. Procedure GenerateAsm;
  63. Procedure OnlyAsm;
  64. var
  65. SmartLinkFilesCnt : longint;
  66. Implementation
  67. uses
  68. script,files,systems,verbose,comphook
  69. {$ifdef linux}
  70. ,linux
  71. {$endif}
  72. ,strings
  73. {$ifdef i386}
  74. {$ifndef NoAg386Att}
  75. ,ag386att
  76. {$endif NoAg386Att}
  77. {$ifndef NoAg386Nsm}
  78. ,ag386nsm
  79. {$endif NoAg386Nsm}
  80. {$ifndef NoAg386Int}
  81. ,ag386int
  82. {$endif NoAg386Int}
  83. {$ifdef Ag386Cof}
  84. ,ag386cof
  85. {$endif Ag386Cof}
  86. {$endif}
  87. {$ifdef m68k}
  88. {$ifndef NoAg68kGas}
  89. ,ag68kgas
  90. {$endif NoAg68kGas}
  91. {$ifndef NoAg68kMot}
  92. ,ag68kmot
  93. {$endif NoAg68kMot}
  94. {$ifndef NoAg68kMit}
  95. ,ag68kmit
  96. {$endif NoAg68kMit}
  97. {$ifndef NoAg68kMpw}
  98. ,ag68kmpw
  99. {$endif NoAg68kMpw}
  100. {$endif}
  101. ;
  102. {*****************************************************************************
  103. TAsmList
  104. *****************************************************************************}
  105. Function DoPipe:boolean;
  106. begin
  107. DoPipe:=(cs_asm_pipe in aktglobalswitches) and
  108. not(cs_asm_leave in aktglobalswitches)
  109. {$ifdef i386}
  110. and (aktoutputformat=as_i386_o)
  111. {$endif i386}
  112. {$ifdef m68k}
  113. and (aktoutputformat=as_m68k_o);
  114. {$endif m68k}
  115. end;
  116. const
  117. lastas : byte=255;
  118. var
  119. LastASBin : string;
  120. Function TAsmList.FindAssembler:string;
  121. var
  122. asfound : boolean;
  123. begin
  124. if lastas<>ord(target_asm.id) then
  125. begin
  126. lastas:=ord(target_asm.id);
  127. { is an assembler passed ? }
  128. if utilsdirectory<>'' then
  129. begin
  130. LastASBin:=Search(target_asm.asmbin+source_os.exeext,
  131. utilsdirectory,asfound)+target_asm.asmbin+source_os.exeext;
  132. end
  133. else
  134. LastASBin:=FindExe(target_asm.asmbin,asfound);
  135. if (not asfound) and not(cs_asm_extern in aktglobalswitches) then
  136. begin
  137. Message1(exec_w_assembler_not_found,LastASBin);
  138. aktglobalswitches:=aktglobalswitches+[cs_asm_extern];
  139. end;
  140. if asfound then
  141. Message1(exec_t_using_assembler,LastASBin);
  142. end;
  143. FindAssembler:=LastASBin;
  144. end;
  145. Function TAsmList.CallAssembler(const command,para:string):Boolean;
  146. begin
  147. callassembler:=true;
  148. if not(cs_asm_extern in aktglobalswitches) then
  149. begin
  150. swapvectors;
  151. exec(command,para);
  152. swapvectors;
  153. if (doserror<>0) then
  154. begin
  155. Message1(exec_w_cant_call_assembler,tostr(doserror));
  156. aktglobalswitches:=aktglobalswitches+[cs_asm_extern];
  157. callassembler:=false;
  158. end
  159. else
  160. if (dosexitcode<>0) then
  161. begin
  162. Message1(exec_w_error_while_assembling,tostr(dosexitcode));
  163. callassembler:=false;
  164. end;
  165. end
  166. else
  167. AsmRes.AddAsmCommand(command,para,name);
  168. end;
  169. procedure TAsmList.RemoveAsm;
  170. var
  171. g : file;
  172. i : word;
  173. begin
  174. if cs_asm_leave in aktglobalswitches then
  175. exit;
  176. if cs_asm_extern in aktglobalswitches then
  177. AsmRes.AddDeleteCommand(AsmFile)
  178. else
  179. begin
  180. assign(g,AsmFile);
  181. {$I-}
  182. erase(g);
  183. {$I+}
  184. i:=ioresult;
  185. end;
  186. end;
  187. Function TAsmList.DoAssemble:boolean;
  188. var
  189. s : string;
  190. begin
  191. DoAssemble:=true;
  192. if DoPipe then
  193. exit;
  194. if (SmartLinkFilesCnt<=1) and not(cs_asm_extern in aktglobalswitches) then
  195. Message1(exec_i_assembling,name);
  196. s:=target_asm.asmcmd;
  197. Replace(s,'$ASM',AsmFile);
  198. Replace(s,'$OBJ',ObjFile);
  199. if CallAssembler(FindAssembler,s) then
  200. RemoveAsm
  201. else
  202. begin
  203. DoAssemble:=false;
  204. inc(status.errorcount);
  205. end;
  206. end;
  207. procedure TAsmList.NextSmartName;
  208. var
  209. s : string;
  210. begin
  211. inc(SmartLinkFilesCnt);
  212. if SmartLinkFilesCnt>999999 then
  213. Message(assem_f_too_many_asm_files);
  214. if IsEndFile then
  215. begin
  216. s:=current_module^.asmprefix^+'e';
  217. IsEndFile:=false;
  218. end
  219. else
  220. s:=current_module^.asmprefix^;
  221. AsmFile:=Path+FixFileName(s+tostr(SmartLinkFilesCnt)+target_info.asmext);
  222. ObjFile:=Path+FixFileName(s+tostr(SmartLinkFilesCnt)+target_info.objext);
  223. end;
  224. {*****************************************************************************
  225. TAsmList AsmFile Writing
  226. *****************************************************************************}
  227. Procedure TAsmList.AsmFlush;
  228. begin
  229. if outcnt>0 then
  230. begin
  231. BlockWrite(outfile,outbuf,outcnt);
  232. outcnt:=0;
  233. end;
  234. end;
  235. Procedure TAsmList.AsmClear;
  236. begin
  237. outcnt:=0;
  238. end;
  239. Procedure TAsmList.AsmWrite(const s:string);
  240. begin
  241. if OutCnt+length(s)>=AsmOutSize then
  242. AsmFlush;
  243. Move(s[1],OutBuf[OutCnt],length(s));
  244. inc(OutCnt,length(s));
  245. inc(AsmSize,length(s));
  246. end;
  247. Procedure TAsmList.AsmWriteLn(const s:string);
  248. begin
  249. AsmWrite(s);
  250. AsmLn;
  251. end;
  252. Procedure TAsmList.AsmWritePChar(p:pchar);
  253. var
  254. i,j : longint;
  255. begin
  256. i:=StrLen(p);
  257. j:=i;
  258. while j>0 do
  259. begin
  260. i:=min(j,AsmOutSize);
  261. if OutCnt+i>=AsmOutSize then
  262. AsmFlush;
  263. Move(p[0],OutBuf[OutCnt],i);
  264. inc(OutCnt,i);
  265. inc(AsmSize,i);
  266. dec(j,i);
  267. p:=pchar(@p[i]);
  268. end;
  269. end;
  270. Procedure TAsmList.AsmLn;
  271. begin
  272. if OutCnt>=AsmOutSize-2 then
  273. AsmFlush;
  274. OutBuf[OutCnt]:=target_os.newline[1];
  275. inc(OutCnt);
  276. inc(AsmSize);
  277. if length(target_os.newline)>1 then
  278. begin
  279. OutBuf[OutCnt]:=target_os.newline[2];
  280. inc(OutCnt);
  281. inc(AsmSize);
  282. end;
  283. end;
  284. procedure TAsmList.AsmCreate;
  285. begin
  286. if (cs_smartlink in aktmoduleswitches) then
  287. NextSmartName;
  288. {$ifdef linux}
  289. if DoPipe then
  290. begin
  291. Message1(exec_i_assembling_pipe,asmfile);
  292. POpen(outfile,'as -o '+objfile,'W');
  293. end
  294. else
  295. {$endif}
  296. begin
  297. Assign(outfile,asmfile);
  298. {$I-}
  299. Rewrite(outfile,1);
  300. {$I+}
  301. if ioresult<>0 then
  302. Message1(exec_d_cant_create_asmfile,asmfile);
  303. end;
  304. outcnt:=0;
  305. AsmSize:=0;
  306. AsmStartSize:=0;
  307. end;
  308. procedure TAsmList.AsmClose;
  309. var
  310. f : file;
  311. l : longint;
  312. begin
  313. AsmFlush;
  314. {$ifdef linux}
  315. if DoPipe then
  316. Close(outfile)
  317. else
  318. {$endif}
  319. begin
  320. {Touch Assembler time to ppu time is there is a ppufilename}
  321. if Assigned(current_module^.ppufilename) then
  322. begin
  323. Assign(f,current_module^.ppufilename^);
  324. {$I-}
  325. reset(f,1);
  326. {$I+}
  327. if ioresult=0 then
  328. begin
  329. getftime(f,l);
  330. close(f);
  331. reset(outfile,1);
  332. setftime(outfile,l);
  333. end;
  334. end;
  335. close(outfile);
  336. end;
  337. end;
  338. {Touch Assembler and object time to ppu time is there is a ppufilename}
  339. procedure TAsmList.Synchronize;
  340. var
  341. f : file;
  342. l : longint;
  343. begin
  344. {Touch Assembler time to ppu time is there is a ppufilename}
  345. if Assigned(current_module^.ppufilename) then
  346. begin
  347. Assign(f,current_module^.ppufilename^);
  348. {$I-}
  349. reset(f,1);
  350. {$I+}
  351. if ioresult=0 then
  352. begin
  353. getftime(f,l);
  354. close(f);
  355. assign(f,asmfile);
  356. {$I-}
  357. reset(f,1);
  358. {$I+}
  359. if ioresult=0 then
  360. begin
  361. setftime(f,l);
  362. close(f);
  363. end;
  364. if not(cs_asm_extern in aktglobalswitches) then
  365. begin
  366. assign(f,objfile);
  367. {$I-}
  368. reset(f,1);
  369. {$I+}
  370. if ioresult=0 then
  371. begin
  372. setftime(f,l);
  373. close(f);
  374. end;
  375. end;
  376. end;
  377. end;
  378. end;
  379. procedure TAsmList.WriteTree(p:paasmoutput);
  380. begin
  381. end;
  382. procedure TAsmList.WriteAsmList;
  383. begin
  384. end;
  385. Constructor TAsmList.Init;
  386. var
  387. i : word;
  388. begin
  389. { load start values }
  390. asmfile:=current_module^.asmfilename^;
  391. objfile:=current_module^.objfilename^;
  392. name:=FixFileName(current_module^.modulename^);
  393. OutCnt:=0;
  394. SmartLinkFilesCnt:=0;
  395. IsEndFile:=false;
  396. { Which path will be used ? }
  397. if (cs_smartlink in aktmoduleswitches) then
  398. begin
  399. path:=current_module^.path^+FixFileName(current_module^.modulename^)+target_info.smartext;
  400. {$I-}
  401. mkdir(path);
  402. {$I+}
  403. i:=ioresult;
  404. path:=FixPath(path,false);
  405. end
  406. else
  407. path:=current_module^.path^;
  408. end;
  409. Destructor TAsmList.Done;
  410. begin
  411. end;
  412. {*****************************************************************************
  413. Generate Assembler Files Main Procedure
  414. *****************************************************************************}
  415. Procedure GenerateAsm;
  416. var
  417. a : PAsmList;
  418. begin
  419. case aktoutputformat of
  420. {$ifdef i386}
  421. {$ifdef Ag386Cof}
  422. as_i386_coff :
  423. a:=new(pi386coffasmlist,Init);
  424. {$endif Ag386Cof}
  425. {$ifndef NoAg386Att}
  426. as_i386_o,
  427. as_i386_o_aout,
  428. as_i386_asw :
  429. a:=new(pi386attasmlist,Init);
  430. {$endif NoAg386Att}
  431. {$ifndef NoAg386Nsm}
  432. as_i386_nasmcoff,
  433. as_i386_nasmelf,
  434. as_i386_nasmobj :
  435. a:=new(pi386nasmasmlist,Init);
  436. {$endif NoAg386Nsm}
  437. {$ifndef NoAg386Int}
  438. as_i386_tasm :
  439. a:=new(pi386intasmlist,Init);
  440. {$endif NoAg386Int}
  441. {$endif}
  442. {$ifdef m68k}
  443. {$ifndef NoAg68kGas}
  444. as_m68k_o,
  445. as_m68k_gas :
  446. a:=new(pm68kgasasmlist,Init);
  447. {$endif NoAg86KGas}
  448. {$ifndef NoAg68kMot}
  449. as_m68k_mot :
  450. a:=new(pm68kmotasmlist,Init);
  451. {$endif NoAg86kMot}
  452. {$ifndef NoAg68kMit}
  453. as_m68k_mit :
  454. a:=new(pm68kmitasmlist,Init);
  455. {$endif NoAg86KMot}
  456. {$ifndef NoAg68kMpw}
  457. as_m68k_mpw :
  458. a:=new(pm68kmpwasmlist,Init);
  459. {$endif NoAg68kMpw}
  460. {$endif}
  461. else
  462. Message(assem_f_assembler_output_not_supported);
  463. end;
  464. a^.AsmCreate;
  465. a^.WriteAsmList;
  466. a^.AsmClose;
  467. a^.DoAssemble;
  468. a^.synchronize;
  469. dispose(a,Done);
  470. end;
  471. Procedure OnlyAsm;
  472. var
  473. a : PAsmList;
  474. begin
  475. a:=new(pasmlist,Init);
  476. a^.DoAssemble;
  477. dispose(a,Done);
  478. end;
  479. end.
  480. {
  481. $Log$
  482. Revision 1.34 1999-01-10 15:37:52 peter
  483. * moved some tables from ra386*.pas -> i386.pas
  484. + start of coff writer
  485. * renamed asmutils unit to rautils
  486. Revision 1.33 1998/12/11 00:02:45 peter
  487. + globtype,tokens,version unit splitted from globals
  488. Revision 1.32 1998/11/06 09:46:46 pierre
  489. * assemble failure increments status errorcount again !!
  490. Revision 1.31 1998/10/26 22:23:28 peter
  491. + fixpath() has an extra option to allow a ./ as path
  492. Revision 1.30 1998/10/16 13:37:14 florian
  493. + switch -FD added to specify the path for utilities
  494. Revision 1.29 1998/10/15 16:19:42 peter
  495. * fixed asmsynchronize
  496. Revision 1.28 1998/10/14 15:56:43 pierre
  497. * all references to comp suppressed for m68k
  498. Revision 1.27 1998/10/13 16:50:01 pierre
  499. * undid some changes of Peter that made the compiler wrong
  500. for m68k (I had to reinsert some ifdefs)
  501. * removed several memory leaks under m68k
  502. * removed the meory leaks for assembler readers
  503. * cross compiling shoud work again better
  504. ( crosscompiling sysamiga works
  505. but as68k still complain about some code !)
  506. Revision 1.26 1998/10/13 13:10:11 peter
  507. * new style for m68k/i386 infos and enums
  508. Revision 1.25 1998/10/13 08:19:24 pierre
  509. + source_os is now set correctly for cross-processor compilers
  510. (tos contains all target_infos and
  511. we use CPU86 and CPU68 conditionnals to
  512. get the source operating system
  513. this only works if you do not undefine
  514. the source target !!)
  515. * several cg68k memory leaks fixed
  516. + started to change the code so that it should be possible to have
  517. a complete compiler (both for m68k and i386 !!)
  518. Revision 1.24 1998/10/08 23:28:50 peter
  519. * -vu shows unit info, -vt shows tried/used files
  520. Revision 1.23 1998/10/07 04:27:37 carl
  521. + MPW support
  522. Revision 1.22 1998/09/16 16:41:39 peter
  523. * merged fixes
  524. Revision 1.21.2.1 1998/09/16 16:11:38 peter
  525. * missing isendfile reset in .init
  526. Revision 1.21 1998/09/07 18:33:32 peter
  527. + smartlinking for win95 imports
  528. Revision 1.20 1998/09/04 17:34:20 pierre
  529. * bug with datalabel corrected
  530. + assembler errors better commented
  531. * one nested record crash removed
  532. Revision 1.19 1998/08/26 10:06:34 peter
  533. * reduce amount of asmfiles generated
  534. * no stabs are written in writefilelineinfo when debuginfo is off
  535. Revision 1.18 1998/08/21 14:08:39 pierre
  536. + TEST_FUNCRET now default (old code removed)
  537. works also for m68k (at least compiles)
  538. Revision 1.17 1998/08/17 09:17:43 peter
  539. * static/shared linking updates
  540. Revision 1.16 1998/08/14 21:56:30 peter
  541. * setting the outputfile using -o works now to create static libs
  542. Revision 1.15 1998/08/14 18:16:09 peter
  543. * return after a failed call will now add it to ppas
  544. Revision 1.14 1998/08/10 14:49:41 peter
  545. + localswitches, moduleswitches, globalswitches splitting
  546. Revision 1.13 1998/07/14 21:46:40 peter
  547. * updated messages file
  548. Revision 1.12 1998/07/08 14:58:34 daniel
  549. * First check if call to assembler is succesfull, then check it's exit code.
  550. This is more logical than first checking the exit code. For some mysterious
  551. reason this did not give problems on DOS & Linux. On OS/2 it did.
  552. Revision 1.11 1998/06/08 22:59:43 peter
  553. * smartlinking works for win32
  554. * some defines to exclude some compiler parts
  555. Revision 1.10 1998/06/04 23:51:33 peter
  556. * m68k compiles
  557. + .def file creation moved to gendef.pas so it could also be used
  558. for win32
  559. Revision 1.9 1998/05/23 01:21:01 peter
  560. + aktasmmode, aktoptprocessor, aktoutputformat
  561. + smartlink per module $SMARTLINK-/+ (like MMX) and moved to aktswitches
  562. + $LIBNAME to set the library name where the unit will be put in
  563. * splitted cgi386 a bit (codeseg to large for bp7)
  564. * nasm, tasm works again. nasm moved to ag386nsm.pas
  565. Revision 1.8 1998/05/11 13:07:53 peter
  566. + $ifdef NEWPPU for the new ppuformat
  567. + $define GDB not longer required
  568. * removed all warnings and stripped some log comments
  569. * no findfirst/findnext anymore to remove smartlink *.o files
  570. Revision 1.7 1998/05/07 00:17:00 peter
  571. * smartlinking for sets
  572. + consts labels are now concated/generated in hcodegen
  573. * moved some cpu code to cga and some none cpu depended code from cga
  574. to tree and hcodegen and cleanup of hcodegen
  575. * assembling .. output reduced for smartlinking ;)
  576. Revision 1.6 1998/05/04 17:54:24 peter
  577. + smartlinking works (only case jumptable left todo)
  578. * redesign of systems.pas to support assemblers and linkers
  579. + Unitname is now also in the PPU-file, increased version to 14
  580. Revision 1.5 1998/04/29 10:33:44 pierre
  581. + added some code for ansistring (not complete nor working yet)
  582. * corrected operator overloading
  583. * corrected nasm output
  584. + started inline procedures
  585. + added starstarn : use ** for exponentiation (^ gave problems)
  586. + started UseTokenInfo cond to get accurate positions
  587. Revision 1.4 1998/04/27 23:10:27 peter
  588. + new scanner
  589. * $makelib -> if smartlink
  590. * small filename fixes pmodule.setfilename
  591. * moved import from files.pas -> import.pas
  592. Revision 1.3 1998/04/10 14:41:43 peter
  593. * removed some Hints
  594. * small speed optimization for AsmLn
  595. Revision 1.2 1998/04/08 11:34:18 peter
  596. * nasm works (linux only tested)
  597. }