assemble.pas 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  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. type
  28. PAsmList=^TAsmList;
  29. TAsmList=object
  30. {filenames}
  31. path : dirstr;
  32. name : namestr;
  33. asmfile,
  34. objfile,
  35. srcfile,
  36. as_bin : string;
  37. smartcnt : longint;
  38. {outfile}
  39. outcnt : longint;
  40. outbuf : array[0..AsmOutSize-1] of char;
  41. outfile : file;
  42. Constructor Init(const fn:string);
  43. Destructor Done;
  44. Function FindAssembler:string;
  45. Function CallAssembler(const command,para:string):Boolean;
  46. Function DoAssemble:boolean;
  47. Procedure RemoveAsm;
  48. procedure NextSmartName;
  49. Procedure AsmFlush;
  50. Procedure AsmWrite(const s:string);
  51. Procedure AsmWritePChar(p:pchar);
  52. Procedure AsmWriteLn(const s:string);
  53. Procedure AsmLn;
  54. procedure AsmCreate;
  55. procedure AsmClose;
  56. procedure WriteTree(p:paasmoutput);virtual;
  57. procedure WriteAsmList;virtual;
  58. end;
  59. Procedure GenerateAsm(const fn:string);
  60. Procedure OnlyAsm(const fn:string);
  61. Implementation
  62. uses
  63. script,files,systems,verbose
  64. {$ifdef linux}
  65. ,linux
  66. {$endif}
  67. ,strings
  68. {$ifdef i386}
  69. ,ag386att,ag386int
  70. {$endif}
  71. {$ifdef m68k}
  72. ,ag68kmot,ag68kgas,ag68kmit
  73. {$endif}
  74. ;
  75. Function DoPipe:boolean;
  76. begin
  77. DoPipe:=use_pipe and (not WriteAsmFile) and (current_module^.output_format=of_o);
  78. end;
  79. {*****************************************************************************
  80. TAsmList Calling and Name
  81. *****************************************************************************}
  82. const
  83. lastas : byte=255;
  84. var
  85. LastASBin : string;
  86. Function TAsmList.FindAssembler:string;
  87. var
  88. asfound : boolean;
  89. begin
  90. if lastas<>ord(target_asm.id) then
  91. begin
  92. lastas:=ord(target_asm.id);
  93. LastASBin:=FindExe(target_asm.asmbin,asfound);
  94. if (not asfound) and (not externasm) then
  95. begin
  96. Message1(exec_w_assembler_not_found,LastASBin);
  97. externasm:=true;
  98. end;
  99. if asfound then
  100. Message1(exec_u_using_assembler,LastASBin);
  101. end;
  102. FindAssembler:=LastASBin;
  103. end;
  104. Function TAsmList.CallAssembler(const command,para:string):Boolean;
  105. begin
  106. if not externasm then
  107. begin
  108. swapvectors;
  109. exec(command,para);
  110. swapvectors;
  111. if (dosexitcode<>0) then
  112. begin
  113. Message(exec_w_error_while_assembling);
  114. callassembler:=false;
  115. exit;
  116. end
  117. else
  118. if (doserror<>0) then
  119. begin
  120. Message(exec_w_cant_call_assembler);
  121. externasm:=true;
  122. end;
  123. end;
  124. if externasm then
  125. AsmRes.AddAsmCommand(command,para,asmfile);
  126. callassembler:=true;
  127. end;
  128. procedure TAsmList.RemoveAsm;
  129. var
  130. g : file;
  131. i : word;
  132. begin
  133. if writeasmfile then
  134. exit;
  135. if ExternAsm then
  136. AsmRes.AddDeleteCommand(asmfile)
  137. else
  138. begin
  139. assign(g,asmfile);
  140. {$I-}
  141. erase(g);
  142. {$I+}
  143. i:=ioresult;
  144. end;
  145. end;
  146. Function TAsmList.DoAssemble:boolean;
  147. var
  148. s : string;
  149. begin
  150. DoAssemble:=true;
  151. if DoPipe then
  152. exit;
  153. if (smartcnt<=1) and (not externasm) then
  154. Message1(exec_i_assembling,name);
  155. s:=target_asm.asmcmd;
  156. Replace(s,'$ASM',AsmFile);
  157. Replace(s,'$OBJ',ObjFile);
  158. if CallAssembler(FindAssembler,s) then
  159. RemoveAsm;
  160. end;
  161. procedure TAsmList.NextSmartName;
  162. begin
  163. inc(smartcnt);
  164. if smartcnt>999999 then
  165. Comment(V_Fatal,'Too many assembler files');
  166. AsmFile:=Path+FixFileName('as'+tostr(smartcnt)+target_info.asmext);
  167. ObjFile:=Path+FixFileName('as'+tostr(smartcnt)+target_info.objext);
  168. end;
  169. {*****************************************************************************
  170. TAsmList AsmFile Writing
  171. *****************************************************************************}
  172. Procedure TAsmList.AsmFlush;
  173. begin
  174. if outcnt>0 then
  175. begin
  176. BlockWrite(outfile,outbuf,outcnt);
  177. outcnt:=0;
  178. end;
  179. end;
  180. Procedure TAsmList.AsmWrite(const s:string);
  181. begin
  182. if OutCnt+length(s)>=AsmOutSize then
  183. AsmFlush;
  184. Move(s[1],OutBuf[OutCnt],length(s));
  185. inc(OutCnt,length(s));
  186. end;
  187. Procedure TAsmList.AsmWriteLn(const s:string);
  188. begin
  189. AsmWrite(s);
  190. AsmLn;
  191. end;
  192. Procedure TAsmList.AsmWritePChar(p:pchar);
  193. var
  194. i,j : longint;
  195. begin
  196. i:=StrLen(p);
  197. j:=i;
  198. while j>0 do
  199. begin
  200. i:=min(j,AsmOutSize);
  201. if OutCnt+i>=AsmOutSize then
  202. AsmFlush;
  203. Move(p[0],OutBuf[OutCnt],i);
  204. inc(OutCnt,i);
  205. dec(j,i);
  206. p:=pchar(@p[i]);
  207. end;
  208. end;
  209. Procedure TAsmList.AsmLn;
  210. begin
  211. if OutCnt>=AsmOutSize-2 then
  212. AsmFlush;
  213. OutBuf[OutCnt]:=target_os.newline[1];
  214. inc(OutCnt);
  215. if length(target_os.newline)>1 then
  216. begin
  217. OutBuf[OutCnt]:=target_os.newline[2];
  218. inc(OutCnt);
  219. end;
  220. end;
  221. procedure TAsmList.AsmCreate;
  222. begin
  223. if SmartLink then
  224. NextSmartName;
  225. {$ifdef linux}
  226. if DoPipe then
  227. begin
  228. Message1(exec_i_assembling_pipe,asmfile);
  229. POpen(outfile,'as -o '+objfile,'W');
  230. end
  231. else
  232. {$endif}
  233. begin
  234. Assign(outfile,asmfile);
  235. {$I-}
  236. Rewrite(outfile,1);
  237. {$I+}
  238. if ioresult<>0 then
  239. Message1(exec_d_cant_create_asmfile,asmfile);
  240. end;
  241. outcnt:=0;
  242. end;
  243. procedure TAsmList.AsmClose;
  244. var
  245. f : file;
  246. l : longint;
  247. begin
  248. AsmFlush;
  249. {$ifdef linux}
  250. if DoPipe then
  251. Close(outfile)
  252. else
  253. {$endif}
  254. begin
  255. {Touch Assembler time to ppu time is there is a ppufilename}
  256. if Assigned(current_module^.ppufilename) then
  257. begin
  258. Assign(f,current_module^.ppufilename^);
  259. {$I-}
  260. reset(f,1);
  261. {$I+}
  262. if ioresult=0 then
  263. begin
  264. getftime(f,l);
  265. close(f);
  266. reset(outfile,1);
  267. setftime(outfile,l);
  268. end;
  269. end;
  270. close(outfile);
  271. end;
  272. end;
  273. procedure TAsmList.WriteTree(p:paasmoutput);
  274. begin
  275. end;
  276. procedure TAsmList.WriteAsmList;
  277. begin
  278. end;
  279. Constructor TAsmList.Init(const fn:string);
  280. var
  281. ext : extstr;
  282. i : word;
  283. begin
  284. {Create filenames for easier access}
  285. fsplit(fn,path,name,ext);
  286. srcfile:=fn;
  287. asmfile:=path+name+target_info.asmext;
  288. objfile:=path+name+target_info.objext;
  289. OutCnt:=0;
  290. {Smartlinking}
  291. smartcnt:=0;
  292. if smartlink then
  293. begin
  294. path:=SmartLinkPath(name);
  295. {$I-}
  296. mkdir(path);
  297. {$I+}
  298. i:=ioresult;
  299. end;
  300. path:=FixPath(path);
  301. end;
  302. Destructor TAsmList.Done;
  303. begin
  304. end;
  305. {*****************************************************************************
  306. Generate Assembler Files Main Procedure
  307. *****************************************************************************}
  308. Procedure GenerateAsm(const fn:string);
  309. var
  310. a : PAsmList;
  311. begin
  312. case current_module^.output_format of
  313. {$ifdef i386}
  314. of_o,
  315. of_win32,
  316. of_att : a:=new(pi386attasmlist,Init(fn));
  317. of_obj,
  318. of_masm,
  319. of_nasm : a:=new(pi386intasmlist,Init(fn));
  320. {$endif}
  321. {$ifdef m68k}
  322. of_o,
  323. of_gas : a:=new(pm68kgasasmlist,Init(fn));
  324. of_mot : a:=new(pm68kmotasmlist,Init(fn));
  325. of_mit : a:=new(pm68kmitasmlist,Init(fn));
  326. {$endif}
  327. else
  328. internalerror(30000);
  329. end;
  330. a^.AsmCreate;
  331. a^.WriteAsmList;
  332. a^.AsmClose;
  333. a^.DoAssemble;
  334. dispose(a,Done);
  335. end;
  336. Procedure OnlyAsm(const fn:string);
  337. var
  338. a : PAsmList;
  339. begin
  340. a:=new(pasmlist,Init(fn));
  341. a^.DoAssemble;
  342. dispose(a,Done);
  343. end;
  344. end.
  345. {
  346. $Log$
  347. Revision 1.7 1998-05-07 00:17:00 peter
  348. * smartlinking for sets
  349. + consts labels are now concated/generated in hcodegen
  350. * moved some cpu code to cga and some none cpu depended code from cga
  351. to tree and hcodegen and cleanup of hcodegen
  352. * assembling .. output reduced for smartlinking ;)
  353. Revision 1.6 1998/05/04 17:54:24 peter
  354. + smartlinking works (only case jumptable left todo)
  355. * redesign of systems.pas to support assemblers and linkers
  356. + Unitname is now also in the PPU-file, increased version to 14
  357. Revision 1.5 1998/04/29 10:33:44 pierre
  358. + added some code for ansistring (not complete nor working yet)
  359. * corrected operator overloading
  360. * corrected nasm output
  361. + started inline procedures
  362. + added starstarn : use ** for exponentiation (^ gave problems)
  363. + started UseTokenInfo cond to get accurate positions
  364. Revision 1.4 1998/04/27 23:10:27 peter
  365. + new scanner
  366. * $makelib -> if smartlink
  367. * small filename fixes pmodule.setfilename
  368. * moved import from files.pas -> import.pas
  369. Revision 1.3 1998/04/10 14:41:43 peter
  370. * removed some Hints
  371. * small speed optimization for AsmLn
  372. Revision 1.2 1998/04/08 11:34:18 peter
  373. * nasm works (linux only tested)
  374. }