assemble.pas 12 KB

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