assemble.pas 12 KB

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