assemble.pas 13 KB

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