assemble.pas 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  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. SmartExt='.sl';
  28. {$ifdef i386}
  29. { tof = (of_none,of_o,of_obj,of_masm,of_att,of_nasm,of_win32) }
  30. AsBin : array[tof] of string[8]=('','as','nasm','tasm','as','nasm','asw');
  31. { I hope that all I386 assembler recongnize this as
  32. a comment begin (PM) }
  33. As_comment : string[2] = '# ';
  34. {$endif}
  35. {$ifdef m68k}
  36. { tof = (of_none,of_o,of_gas,of_mot,of_mit) }
  37. AsBin : array[tof] of string[8]=('','','as68k','','');
  38. { I hope that all M68K assembler recongnize this as
  39. a comment begin (PM) }
  40. As_comment : string[2] = '| ';
  41. {$endif}
  42. type
  43. PAsmList=^TAsmList;
  44. TAsmList=object
  45. {filenames}
  46. path : dirstr;
  47. name : namestr;
  48. asmfile,
  49. objfile,
  50. srcfile,
  51. as_bin : string;
  52. smartcnt : longint;
  53. {outfile}
  54. outcnt : longint;
  55. outbuf : array[0..AsmOutSize-1] of char;
  56. outfile : file;
  57. Constructor Init(const fn:string);
  58. Destructor Done;
  59. Function FindAssembler(curr_of:tof):string;
  60. Function CallAssembler(const command,para:string):Boolean;
  61. Function DoAssemble:boolean;
  62. Procedure RemoveAsm;
  63. procedure NextSmartName;
  64. Procedure AsmFlush;
  65. Procedure AsmWrite(const s:string);
  66. Procedure AsmWritePChar(p:pchar);
  67. Procedure AsmWriteLn(const s:string);
  68. Procedure AsmLn;
  69. procedure AsmCreate;
  70. procedure AsmClose;
  71. procedure WriteTree(p:paasmoutput);virtual;
  72. procedure WriteAsmList;virtual;
  73. end;
  74. Procedure GenerateAsm(const fn:string);
  75. Procedure OnlyAsm(const fn:string);
  76. Implementation
  77. uses
  78. script,files,systems,verbose
  79. {$ifdef linux}
  80. ,linux
  81. {$endif}
  82. ,strings
  83. {$ifdef i386}
  84. ,ag386att,ag386int
  85. {$endif}
  86. {$ifdef m68k}
  87. ,ag68kmot,ag68kgas,ag68kmit
  88. {$endif}
  89. ;
  90. Function DoPipe:boolean;
  91. begin
  92. DoPipe:=use_pipe and (not WriteAsmFile) and (current_module^.output_format=of_o);
  93. end;
  94. {*****************************************************************************
  95. TAsmList Calling and Name
  96. *****************************************************************************}
  97. const
  98. last_of : tof=of_none;
  99. var
  100. LastASBin : string;
  101. Function TAsmList.FindAssembler(curr_of:tof):string;
  102. var
  103. asfound : boolean;
  104. begin
  105. if last_of<>curr_of then
  106. begin
  107. last_of:=curr_of;
  108. LastASBin:=FindExe(asbin[curr_of],asfound);
  109. if (not asfound) and (not externasm) then
  110. begin
  111. Message1(exec_w_assembler_not_found,LastASBin);
  112. externasm:=true;
  113. end;
  114. if asfound then
  115. Message1(exec_u_using_assembler,LastASBin);
  116. end;
  117. FindAssembler:=LastASBin;
  118. end;
  119. Function TAsmList.CallAssembler(const command,para:string):Boolean;
  120. begin
  121. if not externasm then
  122. begin
  123. swapvectors;
  124. exec(command,para);
  125. swapvectors;
  126. if (dosexitcode<>0) then
  127. begin
  128. Message(exec_w_error_while_assembling);
  129. callassembler:=false;
  130. exit;
  131. end
  132. else
  133. if (doserror<>0) then
  134. begin
  135. Message(exec_w_cant_call_assembler);
  136. externasm:=true;
  137. end;
  138. end;
  139. if externasm then
  140. AsmRes.AddAsmCommand(command,para,asmfile);
  141. callassembler:=true;
  142. end;
  143. procedure TAsmList.RemoveAsm;
  144. var
  145. g : file;
  146. i : word;
  147. begin
  148. if writeasmfile then
  149. exit;
  150. if ExternAsm then
  151. AsmRes.AddDeleteCommand(asmfile)
  152. else
  153. begin
  154. assign(g,asmfile);
  155. {$I-}
  156. erase(g);
  157. {$I+}
  158. i:=ioresult;
  159. end;
  160. end;
  161. Function TAsmList.DoAssemble:boolean;
  162. begin
  163. if DoPipe then
  164. exit;
  165. if not externasm then
  166. Message1(exec_i_assembling,asmfile);
  167. case current_module^.output_format of
  168. {$ifdef i386}
  169. of_att : begin
  170. externasm:=true; {Force Extern Asm}
  171. if CallAssembler(FindAssembler(of_att),' -D -o '+objfile+' '+AsmFile) then
  172. RemoveAsm;
  173. end;
  174. of_o : begin
  175. if CallAssembler(FindAssembler(of_o),'-D -o '+objfile+' '+AsmFile) then
  176. RemoveAsm;
  177. end;
  178. of_win32 : begin
  179. if CallAssembler(FindAssembler(of_win32),'-D -o '+objfile+' '+AsmFile) then
  180. RemoveAsm;
  181. end;
  182. of_nasm : begin
  183. {$ifdef linux}
  184. if CallAssembler(FindAssembler(of_nasm),' -f elf -o '+objfile+' '+AsmFile) then
  185. RemoveAsm;
  186. {$else}
  187. if CallAssembler(FindAssembler(of_nasm),' -f coff -o '+objfile+' '+AsmFile) then
  188. RemoveAsm;
  189. {$endif}
  190. end;
  191. of_obj : begin
  192. if CallAssembler(FindAssembler(of_nasm),' -f obj -o '+objfile+' '+AsmFile) then
  193. RemoveAsm;
  194. end;
  195. of_masm : begin
  196. { !! Nothing yet !! }
  197. end;
  198. {$endif}
  199. {$ifdef m68k}
  200. of_mot,
  201. of_mit : begin
  202. { !! Nothing yet !! }
  203. end;
  204. of_o,of_gas : begin
  205. if CallAssembler(FindAssembler(of_gas),' --register-prefix-optional'+
  206. ' -o '+objfile+' '+asmfile) then
  207. RemoveAsm;
  208. end;
  209. {$endif}
  210. else
  211. internalerror(30000);
  212. end;
  213. DoAssemble:=true;
  214. end;
  215. procedure TAsmList.NextSmartName;
  216. begin
  217. inc(smartcnt);
  218. if smartcnt>999999 then
  219. Comment(V_Fatal,'Too many assembler files');
  220. AsmFile:=Path+FixFileName('as'+tostr(smartcnt)+target_info.asmext);
  221. ObjFile:=Path+FixFileName('as'+tostr(smartcnt)+target_info.objext);
  222. end;
  223. {*****************************************************************************
  224. TAsmList AsmFile Writing
  225. *****************************************************************************}
  226. Procedure TAsmList.AsmFlush;
  227. begin
  228. if outcnt>0 then
  229. begin
  230. BlockWrite(outfile,outbuf,outcnt);
  231. outcnt:=0;
  232. end;
  233. end;
  234. Procedure TAsmList.AsmWrite(const s:string);
  235. begin
  236. if OutCnt+length(s)>=AsmOutSize then
  237. AsmFlush;
  238. Move(s[1],OutBuf[OutCnt],length(s));
  239. inc(OutCnt,length(s));
  240. end;
  241. Procedure TAsmList.AsmWriteLn(const s:string);
  242. begin
  243. AsmWrite(s);
  244. AsmLn;
  245. end;
  246. Procedure TAsmList.AsmWritePChar(p:pchar);
  247. var
  248. i,j : longint;
  249. begin
  250. i:=StrLen(p);
  251. j:=i;
  252. while j>0 do
  253. begin
  254. i:=min(j,AsmOutSize);
  255. if OutCnt+i>=AsmOutSize then
  256. AsmFlush;
  257. Move(p[0],OutBuf[OutCnt],i);
  258. inc(OutCnt,i);
  259. dec(j,i);
  260. p:=pchar(@p[i]);
  261. end;
  262. end;
  263. Procedure TAsmList.AsmLn;
  264. begin
  265. if OutCnt>=AsmOutSize-2 then
  266. AsmFlush;
  267. OutBuf[OutCnt]:=target_info.newline[1];
  268. inc(OutCnt);
  269. if length(target_info.newline)>1 then
  270. begin
  271. OutBuf[OutCnt]:=target_info.newline[2];
  272. inc(OutCnt);
  273. end;
  274. end;
  275. procedure TAsmList.AsmCreate;
  276. begin
  277. if SmartLink then
  278. NextSmartName;
  279. {$ifdef linux}
  280. if DoPipe then
  281. begin
  282. Message1(exec_i_assembling_pipe,asmfile);
  283. POpen(outfile,'as -o '+objfile,'W');
  284. end
  285. else
  286. {$endif}
  287. begin
  288. Assign(outfile,asmfile);
  289. {$I-}
  290. Rewrite(outfile,1);
  291. {$I+}
  292. if ioresult<>0 then
  293. Message1(exec_d_cant_create_asmfile,asmfile);
  294. end;
  295. outcnt:=0;
  296. end;
  297. procedure TAsmList.AsmClose;
  298. var
  299. f : file;
  300. l : longint;
  301. begin
  302. AsmFlush;
  303. {$ifdef linux}
  304. if DoPipe then
  305. Close(outfile)
  306. else
  307. {$endif}
  308. begin
  309. {Touch Assembler time to ppu time is there is a ppufilename}
  310. if Assigned(current_module^.ppufilename) then
  311. begin
  312. Assign(f,current_module^.ppufilename^);
  313. {$I-}
  314. reset(f,1);
  315. {$I+}
  316. if ioresult=0 then
  317. begin
  318. getftime(f,l);
  319. close(f);
  320. reset(outfile,1);
  321. setftime(outfile,l);
  322. end;
  323. end;
  324. close(outfile);
  325. end;
  326. end;
  327. procedure TAsmList.WriteTree(p:paasmoutput);
  328. begin
  329. end;
  330. procedure TAsmList.WriteAsmList;
  331. begin
  332. end;
  333. Constructor TAsmList.Init(const fn:string);
  334. var
  335. ext : extstr;
  336. i : word;
  337. begin
  338. {Create filenames for easier access}
  339. fsplit(fn,path,name,ext);
  340. srcfile:=fn;
  341. asmfile:=path+name+target_info.asmext;
  342. objfile:=path+name+target_info.objext;
  343. OutCnt:=0;
  344. {Smartlinking}
  345. smartcnt:=0;
  346. if smartlink then
  347. begin
  348. path:=FixPath(path)+FixFileName(name+smartext);
  349. {$I-}
  350. mkdir(path);
  351. {$I+}
  352. i:=ioresult;
  353. end;
  354. path:=FixPath(path);
  355. end;
  356. Destructor TAsmList.Done;
  357. begin
  358. end;
  359. {*****************************************************************************
  360. Generate Assembler Files Main Procedure
  361. *****************************************************************************}
  362. Procedure GenerateAsm(const fn:string);
  363. var
  364. a : PAsmList;
  365. begin
  366. case current_module^.output_format of
  367. {$ifdef i386}
  368. of_o,
  369. of_win32,
  370. of_att : a:=new(pi386attasmlist,Init(fn));
  371. of_obj,
  372. of_masm,
  373. of_nasm : a:=new(pi386intasmlist,Init(fn));
  374. {$endif}
  375. {$ifdef m68k}
  376. of_o,
  377. of_gas : a:=new(pm68kgasasmlist,Init(fn));
  378. of_mot : a:=new(pm68kmotasmlist,Init(fn));
  379. of_mit : a:=new(pm68kmitasmlist,Init(fn));
  380. {$endif}
  381. else
  382. internalerror(30000);
  383. end;
  384. a^.AsmCreate;
  385. a^.WriteAsmList;
  386. a^.AsmClose;
  387. a^.DoAssemble;
  388. dispose(a,Done);
  389. end;
  390. Procedure OnlyAsm(const fn:string);
  391. var
  392. a : PAsmList;
  393. begin
  394. case current_module^.output_format of
  395. {$ifdef i386}
  396. of_o,
  397. of_win32,
  398. of_att : a:=new(pi386attasmlist,Init(fn));
  399. of_obj,
  400. of_masm,
  401. of_nasm : a:=new(pi386intasmlist,Init(fn));
  402. {$endif}
  403. {$ifdef m68k}
  404. of_o,
  405. of_gas : a:=new(pm68kgasasmlist,Init(fn));
  406. of_mot : a:=new(pm68kmotasmlist,Init(fn));
  407. of_mit : a:=new(pm68kmitasmlist,Init(fn));
  408. {$endif}
  409. else
  410. internalerror(30000);
  411. end;
  412. a^.DoAssemble;
  413. dispose(a,Done);
  414. end;
  415. end.
  416. {
  417. $Log$
  418. Revision 1.5 1998-04-29 10:33:44 pierre
  419. + added some code for ansistring (not complete nor working yet)
  420. * corrected operator overloading
  421. * corrected nasm output
  422. + started inline procedures
  423. + added starstarn : use ** for exponentiation (^ gave problems)
  424. + started UseTokenInfo cond to get accurate positions
  425. Revision 1.4 1998/04/27 23:10:27 peter
  426. + new scanner
  427. * $makelib -> if smartlink
  428. * small filename fixes pmodule.setfilename
  429. * moved import from files.pas -> import.pas
  430. Revision 1.3 1998/04/10 14:41:43 peter
  431. * removed some Hints
  432. * small speed optimization for AsmLn
  433. Revision 1.2 1998/04/08 11:34:18 peter
  434. * nasm works (linux only tested)
  435. Revision 1.1.1.1 1998/03/25 11:18:16 root
  436. * Restored version
  437. Revision 1.17 1998/03/10 13:23:00 florian
  438. * small win32 problems fixed
  439. Revision 1.16 1998/03/10 01:17:14 peter
  440. * all files have the same header
  441. * messages are fully implemented, EXTDEBUG uses Comment()
  442. + AG... files for the Assembler generation
  443. Revision 1.15 1998/03/09 10:37:41 peter
  444. * fixed very long pchar writing (> outbufsize)
  445. Revision 1.14 1998/03/05 22:43:45 florian
  446. * some win32 support stuff added
  447. Revision 1.13 1998/03/04 14:18:58 michael
  448. * modified messaging system
  449. Revision 1.12 1998/03/04 01:34:51 peter
  450. * messages for unit-handling and assembler/linker
  451. * the compiler compiles without -dGDB, but doesn't work yet
  452. + -vh for Hint
  453. Revision 1.11 1998/03/02 01:48:05 peter
  454. * renamed target_DOS to target_GO32V1
  455. + new verbose system, merged old errors and verbose units into one new
  456. verbose.pas, so errors.pas is obsolete
  457. Revision 1.10 1998/02/26 11:57:00 daniel
  458. * New assembler optimizations commented out, because of bugs.
  459. * Use of dir-/name- and extstr.
  460. Revision 1.9 1998/02/24 10:29:12 peter
  461. * -a works again
  462. Revision 1.8 1998/02/21 03:31:40 carl
  463. + mit68k asm support.
  464. Revision 1.7 1998/02/18 14:18:16 michael
  465. + added log at end of file (retroactively)
  466. revision 1.6
  467. date: 1998/02/18 13:43:11; author: michael; state: Exp; lines: +3 -19
  468. + Implemented an OS independent AsmRes object.
  469. ----------------------------
  470. revision 1.5
  471. date: 1998/02/17 21:20:28; author: peter; state: Exp; lines: +60 -54
  472. + Script unit
  473. + __EXIT is called again to exit a program
  474. - target_info.link/assembler calls
  475. * linking works again for dos
  476. * optimized a few filehandling functions
  477. * fixed stabs generation for procedures
  478. ----------------------------
  479. revision 1.4
  480. date: 1998/02/16 12:51:27; author: michael; state: Exp; lines: +2 -2
  481. + Implemented linker object
  482. ----------------------------
  483. revision 1.3
  484. date: 1998/02/15 21:15:58; author: peter; state: Exp; lines: +8 -9
  485. * all assembler outputs supported by assemblerobject
  486. * cleanup with assembleroutputs, better .ascii generation
  487. * help_constructor/destructor are now added to the externals
  488. - generation of asmresponse is not outputformat depended
  489. ----------------------------
  490. revision 1.2
  491. date: 1998/02/14 01:45:04; author: peter; state: Exp; lines: +3 -14
  492. * more fixes
  493. - pmode target is removed
  494. - search_as_ld is removed, this is done in the link.pas/assemble.pas
  495. + findexe() to search for an executable (linker,assembler,binder)
  496. ----------------------------
  497. revision 1.1
  498. date: 1998/02/13 22:28:16; author: peter; state: Exp;
  499. + Initial implementation
  500. }