assemble.pas 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  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. {outfile}
  38. AsmSize,
  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. var
  62. SmartLinkFilesCnt : longint;
  63. Function SmartLinkPath(const s:string):string;
  64. Implementation
  65. uses
  66. script,files,systems,verbose
  67. {$ifdef linux}
  68. ,linux
  69. {$endif}
  70. ,strings
  71. {$ifdef i386}
  72. {$ifndef NoAg386Att}
  73. ,ag386att
  74. {$endif NoAg386Att}
  75. {$ifndef NoAg386Nsm}
  76. ,ag386nsm
  77. {$endif NoAg386Nsm}
  78. {$ifndef NoAg386Int}
  79. ,ag386int
  80. {$endif NoAg386Int}
  81. {$endif}
  82. {$ifdef m68k}
  83. {$ifndef NoAg68kGas}
  84. ,ag68kgas
  85. {$endif NoAg68kGas}
  86. {$ifndef NoAg68kMot}
  87. ,ag68kmot
  88. {$endif NoAg68kMot}
  89. {$ifndef NoAg68kMit}
  90. ,ag68kmit
  91. {$endif NoAg68kMit}
  92. {$endif}
  93. ;
  94. {*****************************************************************************
  95. SmartLink Helpers
  96. *****************************************************************************}
  97. Function SmartLinkPath(const s:string):string;
  98. var
  99. p : dirstr;
  100. n : namestr;
  101. e : extstr;
  102. begin
  103. FSplit(s,p,n,e);
  104. SmartLinkPath:=FixFileName(n+target_info.smartext);
  105. end;
  106. {*****************************************************************************
  107. TAsmList
  108. *****************************************************************************}
  109. Function DoPipe:boolean;
  110. begin
  111. DoPipe:=use_pipe and (not WriteAsmFile) and (aktoutputformat=as_o);
  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 externasm) then
  126. begin
  127. Message1(exec_w_assembler_not_found,LastASBin);
  128. externasm:=true;
  129. end;
  130. if asfound then
  131. Message1(exec_u_using_assembler,LastASBin);
  132. end;
  133. FindAssembler:=LastASBin;
  134. end;
  135. Function TAsmList.CallAssembler(const command,para:string):Boolean;
  136. begin
  137. if not externasm then
  138. begin
  139. swapvectors;
  140. exec(command,para);
  141. swapvectors;
  142. if (doserror<>0) then
  143. begin
  144. Message(exec_w_cant_call_assembler);
  145. externasm:=true;
  146. exit;
  147. end
  148. else
  149. if (dosexitcode<>0) then
  150. begin
  151. Message(exec_w_error_while_assembling);
  152. callassembler:=false;
  153. end;
  154. end;
  155. if externasm then
  156. AsmRes.AddAsmCommand(command,para,name);
  157. callassembler:=true;
  158. end;
  159. procedure TAsmList.RemoveAsm;
  160. var
  161. g : file;
  162. i : word;
  163. begin
  164. if writeasmfile then
  165. exit;
  166. if ExternAsm 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 externasm) 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. begin
  194. inc(SmartLinkFilesCnt);
  195. if SmartLinkFilesCnt>999999 then
  196. Message(assem_f_too_many_asm_files);
  197. AsmFile:=Path+FixFileName('as'+tostr(SmartLinkFilesCnt)+target_info.asmext);
  198. ObjFile:=Path+FixFileName('as'+tostr(SmartLinkFilesCnt)+target_info.objext);
  199. end;
  200. {*****************************************************************************
  201. TAsmList AsmFile Writing
  202. *****************************************************************************}
  203. Procedure TAsmList.AsmFlush;
  204. begin
  205. if outcnt>0 then
  206. begin
  207. BlockWrite(outfile,outbuf,outcnt);
  208. outcnt:=0;
  209. end;
  210. end;
  211. Procedure TAsmList.AsmWrite(const s:string);
  212. begin
  213. if OutCnt+length(s)>=AsmOutSize then
  214. AsmFlush;
  215. Move(s[1],OutBuf[OutCnt],length(s));
  216. inc(OutCnt,length(s));
  217. inc(AsmSize,length(s));
  218. end;
  219. Procedure TAsmList.AsmWriteLn(const s:string);
  220. begin
  221. AsmWrite(s);
  222. AsmLn;
  223. end;
  224. Procedure TAsmList.AsmWritePChar(p:pchar);
  225. var
  226. i,j : longint;
  227. begin
  228. i:=StrLen(p);
  229. j:=i;
  230. while j>0 do
  231. begin
  232. i:=min(j,AsmOutSize);
  233. if OutCnt+i>=AsmOutSize then
  234. AsmFlush;
  235. Move(p[0],OutBuf[OutCnt],i);
  236. inc(OutCnt,i);
  237. inc(AsmSize,i);
  238. dec(j,i);
  239. p:=pchar(@p[i]);
  240. end;
  241. end;
  242. Procedure TAsmList.AsmLn;
  243. begin
  244. if OutCnt>=AsmOutSize-2 then
  245. AsmFlush;
  246. OutBuf[OutCnt]:=target_os.newline[1];
  247. inc(OutCnt);
  248. inc(AsmSize);
  249. if length(target_os.newline)>1 then
  250. begin
  251. OutBuf[OutCnt]:=target_os.newline[2];
  252. inc(OutCnt);
  253. inc(AsmSize);
  254. end;
  255. end;
  256. procedure TAsmList.AsmCreate;
  257. begin
  258. if (cs_smartlink in aktswitches) then
  259. NextSmartName;
  260. {$ifdef linux}
  261. if DoPipe then
  262. begin
  263. Message1(exec_i_assembling_pipe,asmfile);
  264. POpen(outfile,'as -o '+objfile,'W');
  265. end
  266. else
  267. {$endif}
  268. begin
  269. Assign(outfile,asmfile);
  270. {$I-}
  271. Rewrite(outfile,1);
  272. {$I+}
  273. if ioresult<>0 then
  274. Message1(exec_d_cant_create_asmfile,asmfile);
  275. end;
  276. outcnt:=0;
  277. AsmSize:=0;
  278. end;
  279. procedure TAsmList.AsmClose;
  280. var
  281. f : file;
  282. l : longint;
  283. begin
  284. AsmFlush;
  285. {$ifdef linux}
  286. if DoPipe then
  287. Close(outfile)
  288. else
  289. {$endif}
  290. begin
  291. {Touch Assembler time to ppu time is there is a ppufilename}
  292. if Assigned(current_module^.ppufilename) then
  293. begin
  294. Assign(f,current_module^.ppufilename^);
  295. {$I-}
  296. reset(f,1);
  297. {$I+}
  298. if ioresult=0 then
  299. begin
  300. getftime(f,l);
  301. close(f);
  302. reset(outfile,1);
  303. setftime(outfile,l);
  304. end;
  305. end;
  306. close(outfile);
  307. end;
  308. end;
  309. procedure TAsmList.WriteTree(p:paasmoutput);
  310. begin
  311. end;
  312. procedure TAsmList.WriteAsmList;
  313. begin
  314. end;
  315. Constructor TAsmList.Init(const fn:string);
  316. var
  317. ext : extstr;
  318. i : word;
  319. begin
  320. {Create filenames for easier access}
  321. fsplit(fn,path,name,ext);
  322. srcfile:=fn;
  323. asmfile:=path+name+target_info.asmext;
  324. objfile:=path+name+target_info.objext;
  325. OutCnt:=0;
  326. {Smartlinking}
  327. SmartLinkFilesCnt:=0;
  328. if (cs_smartlink in aktswitches) then
  329. begin
  330. path:=SmartLinkPath(name);
  331. {$I-}
  332. mkdir(path);
  333. {$I+}
  334. i:=ioresult;
  335. end;
  336. path:=FixPath(path);
  337. end;
  338. Destructor TAsmList.Done;
  339. begin
  340. end;
  341. {*****************************************************************************
  342. Generate Assembler Files Main Procedure
  343. *****************************************************************************}
  344. Procedure GenerateAsm(const fn:string);
  345. var
  346. a : PAsmList;
  347. begin
  348. case aktoutputformat of
  349. {$ifdef i386}
  350. {$ifndef NoAg386Att}
  351. as_o : a:=new(pi386attasmlist,Init(fn));
  352. {$endif NoAg386Att}
  353. {$ifndef NoAg386Nsm}
  354. as_nasmcoff,
  355. as_nasmelf,
  356. as_nasmobj : a:=new(pi386nasmasmlist,Init(fn));
  357. {$endif NoAg386Nsm}
  358. {$ifndef NoAg386Int}
  359. as_tasm : a:=new(pi386intasmlist,Init(fn));
  360. {$endif NoAg386Int}
  361. {$endif}
  362. {$ifdef m68k}
  363. {$ifndef NoAg68kGas}
  364. as_o,
  365. as_gas : a:=new(pm68kgasasmlist,Init(fn));
  366. {$endif NoAg86KGas}
  367. {$ifndef NoAg68kMot}
  368. as_mot : a:=new(pm68kmotasmlist,Init(fn));
  369. {$endif NoAg86kMot}
  370. {$ifndef NoAg68kMit}
  371. as_mit : a:=new(pm68kmitasmlist,Init(fn));
  372. {$endif NoAg86KMot}
  373. {$endif}
  374. else
  375. Message(assem_f_assembler_output_not_supported);
  376. end;
  377. a^.AsmCreate;
  378. a^.WriteAsmList;
  379. a^.AsmClose;
  380. a^.DoAssemble;
  381. dispose(a,Done);
  382. end;
  383. Procedure OnlyAsm(const fn:string);
  384. var
  385. a : PAsmList;
  386. begin
  387. a:=new(pasmlist,Init(fn));
  388. a^.DoAssemble;
  389. dispose(a,Done);
  390. end;
  391. end.
  392. {
  393. $Log$
  394. Revision 1.13 1998-07-14 21:46:40 peter
  395. * updated messages file
  396. Revision 1.12 1998/07/08 14:58:34 daniel
  397. * First check if call to assembler is succesfull, then check it's exit code.
  398. This is more logical than first checking the exit code. For some mysterious
  399. reason this did not give problems on DOS & Linux. On OS/2 it did.
  400. Revision 1.11 1998/06/08 22:59:43 peter
  401. * smartlinking works for win32
  402. * some defines to exclude some compiler parts
  403. Revision 1.10 1998/06/04 23:51:33 peter
  404. * m68k compiles
  405. + .def file creation moved to gendef.pas so it could also be used
  406. for win32
  407. Revision 1.9 1998/05/23 01:21:01 peter
  408. + aktasmmode, aktoptprocessor, aktoutputformat
  409. + smartlink per module $SMARTLINK-/+ (like MMX) and moved to aktswitches
  410. + $LIBNAME to set the library name where the unit will be put in
  411. * splitted cgi386 a bit (codeseg to large for bp7)
  412. * nasm, tasm works again. nasm moved to ag386nsm.pas
  413. Revision 1.8 1998/05/11 13:07:53 peter
  414. + $ifdef NEWPPU for the new ppuformat
  415. + $define GDB not longer required
  416. * removed all warnings and stripped some log comments
  417. * no findfirst/findnext anymore to remove smartlink *.o files
  418. Revision 1.7 1998/05/07 00:17:00 peter
  419. * smartlinking for sets
  420. + consts labels are now concated/generated in hcodegen
  421. * moved some cpu code to cga and some none cpu depended code from cga
  422. to tree and hcodegen and cleanup of hcodegen
  423. * assembling .. output reduced for smartlinking ;)
  424. Revision 1.6 1998/05/04 17:54:24 peter
  425. + smartlinking works (only case jumptable left todo)
  426. * redesign of systems.pas to support assemblers and linkers
  427. + Unitname is now also in the PPU-file, increased version to 14
  428. Revision 1.5 1998/04/29 10:33:44 pierre
  429. + added some code for ansistring (not complete nor working yet)
  430. * corrected operator overloading
  431. * corrected nasm output
  432. + started inline procedures
  433. + added starstarn : use ** for exponentiation (^ gave problems)
  434. + started UseTokenInfo cond to get accurate positions
  435. Revision 1.4 1998/04/27 23:10:27 peter
  436. + new scanner
  437. * $makelib -> if smartlink
  438. * small filename fixes pmodule.setfilename
  439. * moved import from files.pas -> import.pas
  440. Revision 1.3 1998/04/10 14:41:43 peter
  441. * removed some Hints
  442. * small speed optimization for AsmLn
  443. Revision 1.2 1998/04/08 11:34:18 peter
  444. * nasm works (linux only tested)
  445. }