assemble.pas 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557
  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=10000;
  26. {$endif}
  27. SmartExt='.sl';
  28. {$ifdef i386}
  29. { tof = (of_none,of_o,of_obj,of_masm,of_att,of_nasm,of_win32) }
  30. AsBin : array[tof] of string[8]=('','as','nasm','masm','as','nasm','asw');
  31. {$endif}
  32. {$ifdef m68k}
  33. { tof = (of_none,of_o,of_gas,of_mot,of_mit) }
  34. AsBin : array[tof] of string[8]=('','','','','');
  35. {$endif}
  36. type
  37. PAsmList=^TAsmList;
  38. TAsmList=object
  39. {filenames}
  40. path : dirstr;
  41. name : namestr;
  42. asmfile,
  43. objfile,
  44. srcfile,
  45. as_bin : string;
  46. smartcnt : longint;
  47. {outfile}
  48. outcnt : longint;
  49. outbuf : array[0..AsmOutSize-1] of char;
  50. outfile : file;
  51. Constructor Init(const fn:string);
  52. Destructor Done;
  53. Function FindAssembler(curr_of:tof):string;
  54. Function CallAssembler(const command,para:string):Boolean;
  55. Function DoAssemble:boolean;
  56. Procedure RemoveAsm;
  57. procedure NextSmartName;
  58. Procedure AsmFlush;
  59. Procedure AsmWrite(const s:string);
  60. Procedure AsmWritePChar(p:pchar);
  61. Procedure AsmWriteLn(const s:string);
  62. Procedure AsmLn;
  63. procedure AsmCreate;
  64. procedure AsmClose;
  65. procedure WriteTree(p:paasmoutput);virtual;
  66. procedure WriteAsmList;virtual;
  67. end;
  68. Procedure GenerateAsm(const fn:string);
  69. Procedure OnlyAsm(const fn:string);
  70. Implementation
  71. uses
  72. script,files,systems,verbose
  73. {$ifdef linux}
  74. ,linux
  75. {$endif}
  76. ,strings
  77. {$ifdef i386}
  78. ,ag386att,ag386int
  79. {$endif}
  80. {$ifdef m68k}
  81. ,ag68kmot,ag68kgas,ag68kmit
  82. {$endif}
  83. ;
  84. Function DoPipe:boolean;
  85. begin
  86. DoPipe:=use_pipe and (not WriteAsmFile) and (current_module^.output_format=of_o);
  87. end;
  88. {*****************************************************************************
  89. TAsmList Calling and Name
  90. *****************************************************************************}
  91. const
  92. last_of : tof=of_none;
  93. var
  94. LastASBin : string;
  95. Function TAsmList.FindAssembler(curr_of:tof):string;
  96. var
  97. asfound : boolean;
  98. begin
  99. if last_of<>curr_of then
  100. begin
  101. last_of:=curr_of;
  102. LastASBin:=FindExe(asbin[curr_of],asfound);
  103. if (not asfound) and (not externasm) then
  104. begin
  105. Message1(exec_w_assembler_not_found,LastASBin);
  106. externasm:=true;
  107. end;
  108. if asfound then
  109. Message1(exec_u_using_assembler,LastASBin);
  110. end;
  111. FindAssembler:=LastASBin;
  112. end;
  113. Function TAsmList.CallAssembler(const command,para:string):Boolean;
  114. begin
  115. if not externasm then
  116. begin
  117. swapvectors;
  118. exec(command,para);
  119. swapvectors;
  120. if (dosexitcode<>0) then
  121. begin
  122. Message(exec_w_error_while_assembling);
  123. callassembler:=false;
  124. exit;
  125. end
  126. else
  127. if (doserror<>0) then
  128. begin
  129. Message(exec_w_cant_call_assembler);
  130. externasm:=true;
  131. end;
  132. end;
  133. if externasm then
  134. AsmRes.AddAsmCommand(command,para,asmfile);
  135. callassembler:=true;
  136. end;
  137. procedure TAsmList.RemoveAsm;
  138. var
  139. g : file;
  140. i : word;
  141. begin
  142. if writeasmfile then
  143. exit;
  144. if ExternAsm then
  145. AsmRes.AddDeleteCommand(asmfile)
  146. else
  147. begin
  148. assign(g,asmfile);
  149. {$I-}
  150. erase(g);
  151. {$I+}
  152. i:=ioresult;
  153. end;
  154. end;
  155. Function TAsmList.DoAssemble:boolean;
  156. begin
  157. if DoPipe then
  158. exit;
  159. if not externasm then
  160. Message1(exec_i_assembling,asmfile);
  161. case current_module^.output_format of
  162. {$ifdef i386}
  163. of_att : begin
  164. externasm:=true; {Force Extern Asm}
  165. if CallAssembler(FindAssembler(of_att),' -D -o '+objfile+' '+AsmFile) then
  166. RemoveAsm;
  167. end;
  168. of_o : begin
  169. if CallAssembler(FindAssembler(of_o),'-D -o '+objfile+' '+AsmFile) then
  170. RemoveAsm;
  171. end;
  172. of_win32 : begin
  173. if CallAssembler(FindAssembler(of_win32),'-D -o '+objfile+' '+AsmFile) then
  174. RemoveAsm;
  175. end;
  176. of_nasm : begin
  177. {$ifdef linux}
  178. if CallAssembler(FindAssembler(of_nasm),' -f elf -o '+objfile+' '+AsmFile) then
  179. RemoveAsm;
  180. {$else}
  181. if CallAssembler(FindAssembler(of_nasm),' -f coff -o '+objfile+' '+AsmFile) then
  182. RemoveAsm;
  183. {$endif}
  184. end;
  185. of_obj : begin
  186. if CallAssembler(FindAssembler(of_nasm),' -f obj -o '+objfile+' '+AsmFile) then
  187. RemoveAsm;
  188. end;
  189. of_masm : begin
  190. { !! Nothing yet !! }
  191. end;
  192. {$endif}
  193. {$ifdef m68k}
  194. of_o,
  195. of_mot,
  196. of_mit,
  197. of_gas : begin
  198. { !! Nothing yet !! }
  199. end;
  200. {$endif}
  201. else
  202. internalerror(30000);
  203. end;
  204. DoAssemble:=true;
  205. end;
  206. procedure TAsmList.NextSmartName;
  207. begin
  208. inc(smartcnt);
  209. if smartcnt>999999 then
  210. Comment(V_Fatal,'Too many assembler files');
  211. AsmFile:=Path+FixFileName('as'+tostr(smartcnt)+target_info.asmext);
  212. ObjFile:=Path+FixFileName('as'+tostr(smartcnt)+target_info.objext);
  213. end;
  214. {*****************************************************************************
  215. TAsmList AsmFile Writing
  216. *****************************************************************************}
  217. Procedure TAsmList.AsmFlush;
  218. begin
  219. if outcnt>0 then
  220. begin
  221. BlockWrite(outfile,outbuf,outcnt);
  222. outcnt:=0;
  223. end;
  224. end;
  225. Procedure TAsmList.AsmWrite(const s:string);
  226. begin
  227. if OutCnt+length(s)>=AsmOutSize then
  228. AsmFlush;
  229. Move(s[1],OutBuf[OutCnt],length(s));
  230. inc(OutCnt,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. dec(j,i);
  251. p:=pchar(@p[i]);
  252. end;
  253. end;
  254. Procedure TAsmList.AsmLn;
  255. begin
  256. if OutCnt>=AsmOutSize-2 then
  257. AsmFlush;
  258. OutBuf[OutCnt]:=target_info.newline[1];
  259. inc(OutCnt);
  260. if length(target_info.newline)>1 then
  261. begin
  262. OutBuf[OutCnt]:=target_info.newline[2];
  263. inc(OutCnt);
  264. end;
  265. end;
  266. procedure TAsmList.AsmCreate;
  267. begin
  268. if SmartLink then
  269. NextSmartName;
  270. {$ifdef linux}
  271. if DoPipe then
  272. begin
  273. Message1(exec_i_assembling_pipe,asmfile);
  274. POpen(outfile,'as -o '+objfile,'W');
  275. end
  276. else
  277. {$endif}
  278. begin
  279. Assign(outfile,asmfile);
  280. {$I-}
  281. Rewrite(outfile,1);
  282. {$I+}
  283. if ioresult<>0 then
  284. Message1(exec_d_cant_create_asmfile,asmfile);
  285. end;
  286. outcnt:=0;
  287. end;
  288. procedure TAsmList.AsmClose;
  289. var
  290. f : file;
  291. l : longint;
  292. begin
  293. AsmFlush;
  294. {$ifdef linux}
  295. if DoPipe then
  296. Close(outfile)
  297. else
  298. {$endif}
  299. begin
  300. {Touch Assembler time to ppu time is there is a ppufilename}
  301. if Assigned(current_module^.ppufilename) then
  302. begin
  303. Assign(f,current_module^.ppufilename^);
  304. {$I-}
  305. reset(f,1);
  306. {$I+}
  307. if ioresult=0 then
  308. begin
  309. getftime(f,l);
  310. close(f);
  311. reset(outfile,1);
  312. setftime(outfile,l);
  313. end;
  314. end;
  315. close(outfile);
  316. end;
  317. end;
  318. procedure TAsmList.WriteTree(p:paasmoutput);
  319. begin
  320. end;
  321. procedure TAsmList.WriteAsmList;
  322. begin
  323. end;
  324. Constructor TAsmList.Init(const fn:string);
  325. var
  326. ext : extstr;
  327. i : word;
  328. begin
  329. {Create filenames for easier access}
  330. fsplit(fn,path,name,ext);
  331. srcfile:=fn;
  332. asmfile:=path+name+target_info.asmext;
  333. objfile:=path+name+target_info.objext;
  334. OutCnt:=0;
  335. {Smartlinking}
  336. smartcnt:=0;
  337. if smartlink then
  338. begin
  339. path:=FixPath(path)+FixFileName(name+smartext);
  340. {$I-}
  341. mkdir(path);
  342. {$I+}
  343. i:=ioresult;
  344. end;
  345. path:=FixPath(path);
  346. end;
  347. Destructor TAsmList.Done;
  348. begin
  349. end;
  350. {*****************************************************************************
  351. Generate Assembler Files Main Procedure
  352. *****************************************************************************}
  353. Procedure GenerateAsm(const fn:string);
  354. var
  355. a : PAsmList;
  356. begin
  357. case current_module^.output_format of
  358. {$ifdef i386}
  359. of_o,
  360. of_win32,
  361. of_att : a:=new(pi386attasmlist,Init(fn));
  362. of_obj,
  363. of_masm,
  364. of_nasm : a:=new(pi386intasmlist,Init(fn));
  365. {$endif}
  366. {$ifdef m68k}
  367. of_o,
  368. of_gas : a:=new(pm68kgasasmlist,Init(fn));
  369. of_mot : a:=new(pm68kmotasmlist,Init(fn));
  370. of_mit : a:=new(pm68kmitasmlist,Init(fn));
  371. {$endif}
  372. else
  373. internalerror(30000);
  374. end;
  375. a^.AsmCreate;
  376. a^.WriteAsmList;
  377. a^.AsmClose;
  378. a^.DoAssemble;
  379. dispose(a,Done);
  380. end;
  381. Procedure OnlyAsm(const fn:string);
  382. var
  383. a : PAsmList;
  384. begin
  385. case current_module^.output_format of
  386. {$ifdef i386}
  387. of_o,
  388. of_win32,
  389. of_att : a:=new(pi386attasmlist,Init(fn));
  390. of_obj,
  391. of_masm,
  392. of_nasm : a:=new(pi386intasmlist,Init(fn));
  393. {$endif}
  394. {$ifdef m68k}
  395. of_o,
  396. of_gas : a:=new(pm68kgasasmlist,Init(fn));
  397. of_mot : a:=new(pm68kmotasmlist,Init(fn));
  398. of_mit : a:=new(pm68kmitasmlist,Init(fn));
  399. {$endif}
  400. else
  401. internalerror(30000);
  402. end;
  403. a^.DoAssemble;
  404. dispose(a,Done);
  405. end;
  406. end.
  407. {
  408. $Log$
  409. Revision 1.4 1998-04-27 23:10:27 peter
  410. + new scanner
  411. * $makelib -> if smartlink
  412. * small filename fixes pmodule.setfilename
  413. * moved import from files.pas -> import.pas
  414. Revision 1.3 1998/04/10 14:41:43 peter
  415. * removed some Hints
  416. * small speed optimization for AsmLn
  417. Revision 1.2 1998/04/08 11:34:18 peter
  418. * nasm works (linux only tested)
  419. Revision 1.1.1.1 1998/03/25 11:18:16 root
  420. * Restored version
  421. Revision 1.17 1998/03/10 13:23:00 florian
  422. * small win32 problems fixed
  423. Revision 1.16 1998/03/10 01:17:14 peter
  424. * all files have the same header
  425. * messages are fully implemented, EXTDEBUG uses Comment()
  426. + AG... files for the Assembler generation
  427. Revision 1.15 1998/03/09 10:37:41 peter
  428. * fixed very long pchar writing (> outbufsize)
  429. Revision 1.14 1998/03/05 22:43:45 florian
  430. * some win32 support stuff added
  431. Revision 1.13 1998/03/04 14:18:58 michael
  432. * modified messaging system
  433. Revision 1.12 1998/03/04 01:34:51 peter
  434. * messages for unit-handling and assembler/linker
  435. * the compiler compiles without -dGDB, but doesn't work yet
  436. + -vh for Hint
  437. Revision 1.11 1998/03/02 01:48:05 peter
  438. * renamed target_DOS to target_GO32V1
  439. + new verbose system, merged old errors and verbose units into one new
  440. verbose.pas, so errors.pas is obsolete
  441. Revision 1.10 1998/02/26 11:57:00 daniel
  442. * New assembler optimizations commented out, because of bugs.
  443. * Use of dir-/name- and extstr.
  444. Revision 1.9 1998/02/24 10:29:12 peter
  445. * -a works again
  446. Revision 1.8 1998/02/21 03:31:40 carl
  447. + mit68k asm support.
  448. Revision 1.7 1998/02/18 14:18:16 michael
  449. + added log at end of file (retroactively)
  450. revision 1.6
  451. date: 1998/02/18 13:43:11; author: michael; state: Exp; lines: +3 -19
  452. + Implemented an OS independent AsmRes object.
  453. ----------------------------
  454. revision 1.5
  455. date: 1998/02/17 21:20:28; author: peter; state: Exp; lines: +60 -54
  456. + Script unit
  457. + __EXIT is called again to exit a program
  458. - target_info.link/assembler calls
  459. * linking works again for dos
  460. * optimized a few filehandling functions
  461. * fixed stabs generation for procedures
  462. ----------------------------
  463. revision 1.4
  464. date: 1998/02/16 12:51:27; author: michael; state: Exp; lines: +2 -2
  465. + Implemented linker object
  466. ----------------------------
  467. revision 1.3
  468. date: 1998/02/15 21:15:58; author: peter; state: Exp; lines: +8 -9
  469. * all assembler outputs supported by assemblerobject
  470. * cleanup with assembleroutputs, better .ascii generation
  471. * help_constructor/destructor are now added to the externals
  472. - generation of asmresponse is not outputformat depended
  473. ----------------------------
  474. revision 1.2
  475. date: 1998/02/14 01:45:04; author: peter; state: Exp; lines: +3 -14
  476. * more fixes
  477. - pmode target is removed
  478. - search_as_ld is removed, this is done in the link.pas/assemble.pas
  479. + findexe() to search for an executable (linker,assembler,binder)
  480. ----------------------------
  481. revision 1.1
  482. date: 1998/02/13 22:28:16; author: peter; state: Exp;
  483. + Initial implementation
  484. }