assemble.pas 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  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. Comment(V_Fatal,'Too many assembler 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. Comment(V_Fatal,'Selected 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.12 1998-07-08 14:58:34 daniel
  395. * First check if call to assembler is succesfull, then check it's exit code.
  396. This is more logical than first checking the exit code. For some mysterious
  397. reason this did not give problems on DOS & Linux. On OS/2 it did.
  398. Revision 1.11 1998/06/08 22:59:43 peter
  399. * smartlinking works for win32
  400. * some defines to exclude some compiler parts
  401. Revision 1.10 1998/06/04 23:51:33 peter
  402. * m68k compiles
  403. + .def file creation moved to gendef.pas so it could also be used
  404. for win32
  405. Revision 1.9 1998/05/23 01:21:01 peter
  406. + aktasmmode, aktoptprocessor, aktoutputformat
  407. + smartlink per module $SMARTLINK-/+ (like MMX) and moved to aktswitches
  408. + $LIBNAME to set the library name where the unit will be put in
  409. * splitted cgi386 a bit (codeseg to large for bp7)
  410. * nasm, tasm works again. nasm moved to ag386nsm.pas
  411. Revision 1.8 1998/05/11 13:07:53 peter
  412. + $ifdef NEWPPU for the new ppuformat
  413. + $define GDB not longer required
  414. * removed all warnings and stripped some log comments
  415. * no findfirst/findnext anymore to remove smartlink *.o files
  416. Revision 1.7 1998/05/07 00:17:00 peter
  417. * smartlinking for sets
  418. + consts labels are now concated/generated in hcodegen
  419. * moved some cpu code to cga and some none cpu depended code from cga
  420. to tree and hcodegen and cleanup of hcodegen
  421. * assembling .. output reduced for smartlinking ;)
  422. Revision 1.6 1998/05/04 17:54:24 peter
  423. + smartlinking works (only case jumptable left todo)
  424. * redesign of systems.pas to support assemblers and linkers
  425. + Unitname is now also in the PPU-file, increased version to 14
  426. Revision 1.5 1998/04/29 10:33:44 pierre
  427. + added some code for ansistring (not complete nor working yet)
  428. * corrected operator overloading
  429. * corrected nasm output
  430. + started inline procedures
  431. + added starstarn : use ** for exponentiation (^ gave problems)
  432. + started UseTokenInfo cond to get accurate positions
  433. Revision 1.4 1998/04/27 23:10:27 peter
  434. + new scanner
  435. * $makelib -> if smartlink
  436. * small filename fixes pmodule.setfilename
  437. * moved import from files.pas -> import.pas
  438. Revision 1.3 1998/04/10 14:41:43 peter
  439. * removed some Hints
  440. * small speed optimization for AsmLn
  441. Revision 1.2 1998/04/08 11:34:18 peter
  442. * nasm works (linux only tested)
  443. }