assemble.pas 13 KB

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