assemble.pas 14 KB

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