assemble.pas 16 KB

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