assemble.pas 11 KB

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