assemble.pas 12 KB

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