assemble.pas 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Peter Vreman
  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. {$ifdef Delphi}
  21. dmisc,
  22. {$else Delphi}
  23. dos,
  24. {$endif Delphi}
  25. cobjects,globtype,globals,aasm;
  26. const
  27. {$ifdef tp}
  28. AsmOutSize=1024;
  29. {$else}
  30. AsmOutSize=32768;
  31. {$endif}
  32. type
  33. PAsmList=^TAsmList;
  34. TAsmList=object
  35. {filenames}
  36. path : pathstr;
  37. name : namestr;
  38. asmfile, { current .s and .o file }
  39. objfile,
  40. as_bin : string;
  41. SmartAsm : boolean;
  42. smarthcount : longint;
  43. place : TCutPlace; { special 'end' file for import dir ? }
  44. {outfile}
  45. AsmSize,
  46. AsmStartSize,
  47. outcnt : longint;
  48. outbuf : array[0..AsmOutSize-1] of char;
  49. outfile : file;
  50. Constructor Init(smart:boolean);
  51. Destructor Done;
  52. Function FindAssembler:string;
  53. Function CallAssembler(const command,para:string):Boolean;
  54. Function DoAssemble:boolean;
  55. Procedure RemoveAsm;
  56. procedure NextSmartName;
  57. Procedure AsmFlush;
  58. Procedure AsmClear;
  59. Procedure AsmWrite(const s:string);
  60. Procedure AsmWritePChar(p:pchar);
  61. Procedure AsmWriteLn(const s:string);
  62. Procedure AsmLn;
  63. procedure AsmCreate(Aplace:tcutplace);
  64. procedure AsmClose;
  65. procedure Synchronize;
  66. procedure WriteTree(p:paasmoutput);virtual;
  67. procedure WriteAsmList;virtual;
  68. end;
  69. Procedure GenerateAsm(smart:boolean);
  70. Procedure OnlyAsm;
  71. var
  72. SmartLinkFilesCnt : longint;
  73. Implementation
  74. uses
  75. script,files,systems,verbose
  76. {$ifdef linux}
  77. ,linux
  78. {$endif}
  79. ,strings
  80. {$ifdef i386}
  81. {$ifndef NoAg386Bin}
  82. ,ag386bin
  83. {$endif}
  84. {$ifndef NoAg386Att}
  85. ,ag386att
  86. {$endif NoAg386Att}
  87. {$ifndef NoAg386Nsm}
  88. ,ag386nsm
  89. {$endif NoAg386Nsm}
  90. {$ifndef NoAg386Int}
  91. ,ag386int
  92. {$endif NoAg386Int}
  93. {$ifdef Ag386Cof}
  94. ,ag386cof
  95. {$endif Ag386Cof}
  96. {$endif}
  97. {$ifdef m68k}
  98. {$ifndef NoAg68kGas}
  99. ,ag68kgas
  100. {$endif NoAg68kGas}
  101. {$ifndef NoAg68kMot}
  102. ,ag68kmot
  103. {$endif NoAg68kMot}
  104. {$ifndef NoAg68kMit}
  105. ,ag68kmit
  106. {$endif NoAg68kMit}
  107. {$ifndef NoAg68kMpw}
  108. ,ag68kmpw
  109. {$endif NoAg68kMpw}
  110. {$endif}
  111. ;
  112. {*****************************************************************************
  113. TAsmList
  114. *****************************************************************************}
  115. Function DoPipe:boolean;
  116. begin
  117. DoPipe:=(cs_asm_pipe in aktglobalswitches) and
  118. not(cs_asm_leave in aktglobalswitches)
  119. {$ifdef i386}
  120. and (aktoutputformat=as_i386_as)
  121. {$endif i386}
  122. {$ifdef m68k}
  123. and (aktoutputformat=as_m68k_as);
  124. {$endif m68k}
  125. end;
  126. const
  127. lastas : byte=255;
  128. var
  129. LastASBin : pathstr;
  130. Function TAsmList.FindAssembler:string;
  131. var
  132. asfound : boolean;
  133. begin
  134. if lastas<>ord(target_asm.id) then
  135. begin
  136. lastas:=ord(target_asm.id);
  137. { is an assembler passed ? }
  138. if utilsdirectory<>'' then
  139. LastASBin:=FindFile(target_asm.asmbin+source_os.exeext,utilsdirectory,asfound)+
  140. target_asm.asmbin+source_os.exeext;
  141. if LastASBin='' then
  142. LastASBin:=FindExe(target_asm.asmbin,asfound);
  143. if (not asfound) and not(cs_asm_extern in aktglobalswitches) then
  144. begin
  145. Message1(exec_w_assembler_not_found,LastASBin);
  146. aktglobalswitches:=aktglobalswitches+[cs_asm_extern];
  147. end;
  148. if asfound then
  149. Message1(exec_t_using_assembler,LastASBin);
  150. end;
  151. FindAssembler:=LastASBin;
  152. end;
  153. Function TAsmList.CallAssembler(const command,para:string):Boolean;
  154. begin
  155. callassembler:=true;
  156. if not(cs_asm_extern in aktglobalswitches) then
  157. begin
  158. swapvectors;
  159. exec(command,para);
  160. swapvectors;
  161. if (doserror<>0) then
  162. begin
  163. Message1(exec_w_cant_call_assembler,tostr(doserror));
  164. aktglobalswitches:=aktglobalswitches+[cs_asm_extern];
  165. callassembler:=false;
  166. end
  167. else
  168. if (dosexitcode<>0) then
  169. begin
  170. Message1(exec_w_error_while_assembling,tostr(dosexitcode));
  171. callassembler:=false;
  172. end;
  173. end
  174. else
  175. AsmRes.AddAsmCommand(command,para,name);
  176. end;
  177. procedure TAsmList.RemoveAsm;
  178. var
  179. g : file;
  180. i : word;
  181. begin
  182. if cs_asm_leave in aktglobalswitches then
  183. exit;
  184. if cs_asm_extern in aktglobalswitches then
  185. AsmRes.AddDeleteCommand(AsmFile)
  186. else
  187. begin
  188. assign(g,AsmFile);
  189. {$I-}
  190. erase(g);
  191. {$I+}
  192. i:=ioresult;
  193. end;
  194. end;
  195. Function TAsmList.DoAssemble:boolean;
  196. var
  197. s : string;
  198. begin
  199. DoAssemble:=true;
  200. if DoPipe then
  201. exit;
  202. if not(cs_asm_extern in aktglobalswitches) then
  203. begin
  204. if SmartAsm then
  205. begin
  206. if (SmartLinkFilesCnt<=1) then
  207. Message1(exec_i_assembling_smart,name);
  208. end
  209. else
  210. Message1(exec_i_assembling,name);
  211. end;
  212. s:=target_asm.asmcmd;
  213. Replace(s,'$ASM',AsmFile);
  214. Replace(s,'$OBJ',ObjFile);
  215. if CallAssembler(FindAssembler,s) then
  216. RemoveAsm
  217. else
  218. begin
  219. DoAssemble:=false;
  220. GenerateError;
  221. end;
  222. end;
  223. procedure TAsmList.NextSmartName;
  224. var
  225. s : string;
  226. begin
  227. inc(SmartLinkFilesCnt);
  228. if SmartLinkFilesCnt>999999 then
  229. Message(asmw_f_too_many_asm_files);
  230. case place of
  231. cut_begin :
  232. begin
  233. inc(smarthcount);
  234. s:=current_module^.asmprefix^+tostr(smarthcount)+'h';
  235. end;
  236. cut_normal :
  237. s:=current_module^.asmprefix^+tostr(smarthcount)+'s';
  238. cut_end :
  239. s:=current_module^.asmprefix^+tostr(smarthcount)+'t';
  240. end;
  241. AsmFile:=Path+FixFileName(s+tostr(SmartLinkFilesCnt)+target_info.asmext);
  242. ObjFile:=Path+FixFileName(s+tostr(SmartLinkFilesCnt)+target_info.objext);
  243. end;
  244. {*****************************************************************************
  245. TAsmList AsmFile Writing
  246. *****************************************************************************}
  247. Procedure TAsmList.AsmFlush;
  248. begin
  249. if outcnt>0 then
  250. begin
  251. BlockWrite(outfile,outbuf,outcnt);
  252. outcnt:=0;
  253. end;
  254. end;
  255. Procedure TAsmList.AsmClear;
  256. begin
  257. outcnt:=0;
  258. end;
  259. Procedure TAsmList.AsmWrite(const s:string);
  260. begin
  261. if OutCnt+length(s)>=AsmOutSize then
  262. AsmFlush;
  263. Move(s[1],OutBuf[OutCnt],length(s));
  264. inc(OutCnt,length(s));
  265. inc(AsmSize,length(s));
  266. end;
  267. Procedure TAsmList.AsmWriteLn(const s:string);
  268. begin
  269. AsmWrite(s);
  270. AsmLn;
  271. end;
  272. Procedure TAsmList.AsmWritePChar(p:pchar);
  273. var
  274. i,j : longint;
  275. begin
  276. i:=StrLen(p);
  277. j:=i;
  278. while j>0 do
  279. begin
  280. i:=min(j,AsmOutSize);
  281. if OutCnt+i>=AsmOutSize then
  282. AsmFlush;
  283. Move(p[0],OutBuf[OutCnt],i);
  284. inc(OutCnt,i);
  285. inc(AsmSize,i);
  286. dec(j,i);
  287. p:=pchar(@p[i]);
  288. end;
  289. end;
  290. Procedure TAsmList.AsmLn;
  291. begin
  292. if OutCnt>=AsmOutSize-2 then
  293. AsmFlush;
  294. OutBuf[OutCnt]:=target_os.newline[1];
  295. inc(OutCnt);
  296. inc(AsmSize);
  297. if length(target_os.newline)>1 then
  298. begin
  299. OutBuf[OutCnt]:=target_os.newline[2];
  300. inc(OutCnt);
  301. inc(AsmSize);
  302. end;
  303. end;
  304. procedure TAsmList.AsmCreate(Aplace:tcutplace);
  305. begin
  306. place:=Aplace;
  307. if SmartAsm then
  308. NextSmartName;
  309. {$ifdef linux}
  310. if DoPipe then
  311. begin
  312. Message1(exec_i_assembling_pipe,asmfile);
  313. POpen(outfile,'as -o '+objfile,'W');
  314. end
  315. else
  316. {$endif}
  317. begin
  318. Assign(outfile,asmfile);
  319. {$I-}
  320. Rewrite(outfile,1);
  321. {$I+}
  322. if ioresult<>0 then
  323. Message1(exec_d_cant_create_asmfile,asmfile);
  324. end;
  325. outcnt:=0;
  326. AsmSize:=0;
  327. AsmStartSize:=0;
  328. end;
  329. procedure TAsmList.AsmClose;
  330. var
  331. f : file;
  332. l : longint;
  333. begin
  334. AsmFlush;
  335. {$ifdef linux}
  336. if DoPipe then
  337. Close(outfile)
  338. else
  339. {$endif}
  340. begin
  341. {Touch Assembler time to ppu time is there is a ppufilename}
  342. if Assigned(current_module^.ppufilename) then
  343. begin
  344. Assign(f,current_module^.ppufilename^);
  345. {$I-}
  346. reset(f,1);
  347. {$I+}
  348. if ioresult=0 then
  349. begin
  350. getftime(f,l);
  351. close(f);
  352. reset(outfile,1);
  353. setftime(outfile,l);
  354. end;
  355. end;
  356. close(outfile);
  357. end;
  358. end;
  359. {Touch Assembler and object time to ppu time is there is a ppufilename}
  360. procedure TAsmList.Synchronize;
  361. begin
  362. {Touch Assembler time to ppu time is there is a ppufilename}
  363. if Assigned(current_module^.ppufilename) then
  364. begin
  365. SynchronizeFileTime(current_module^.ppufilename^,asmfile);
  366. if not(cs_asm_extern in aktglobalswitches) then
  367. SynchronizeFileTime(current_module^.ppufilename^,objfile);
  368. end;
  369. end;
  370. procedure TAsmList.WriteTree(p:paasmoutput);
  371. begin
  372. end;
  373. procedure TAsmList.WriteAsmList;
  374. begin
  375. end;
  376. Constructor TAsmList.Init(smart:boolean);
  377. var
  378. i : word;
  379. begin
  380. { load start values }
  381. asmfile:=current_module^.asmfilename^;
  382. objfile:=current_module^.objfilename^;
  383. name:=FixFileName(current_module^.modulename^);
  384. OutCnt:=0;
  385. SmartLinkFilesCnt:=0;
  386. place:=cut_normal;
  387. SmartAsm:=smart;
  388. SmartHCount:=0;
  389. { Which path will be used ? }
  390. if SmartAsm then
  391. begin
  392. path:=current_module^.path^+FixFileName(current_module^.modulename^)+target_info.smartext;
  393. {$I-}
  394. mkdir(path);
  395. {$I+}
  396. i:=ioresult;
  397. path:=FixPath(path,false);
  398. end
  399. else
  400. path:=current_module^.path^;
  401. end;
  402. Destructor TAsmList.Done;
  403. begin
  404. end;
  405. {*****************************************************************************
  406. Generate Assembler Files Main Procedure
  407. *****************************************************************************}
  408. Procedure GenerateAsm(smart:boolean);
  409. var
  410. a : PAsmList;
  411. {$ifdef i386}
  412. {$ifndef NoAg386Bin}
  413. b : Pi386binasmlist;
  414. {$endif}
  415. {$endif}
  416. begin
  417. case aktoutputformat of
  418. as_none : ;
  419. {$ifdef i386}
  420. {$ifndef NoAg386Bin}
  421. as_i386_dbg,
  422. as_i386_coff,
  423. as_i386_pecoff :
  424. begin
  425. case aktoutputformat of
  426. as_i386_dbg :
  427. b:=new(pi386binasmlist,Init(og_dbg,smart));
  428. as_i386_coff :
  429. b:=new(pi386binasmlist,Init(og_coff,smart));
  430. as_i386_pecoff :
  431. b:=new(pi386binasmlist,Init(og_pecoff,smart));
  432. end;
  433. b^.WriteBin;
  434. dispose(b,done);
  435. if assigned(current_module^.ppufilename) then
  436. begin
  437. if smart then
  438. SynchronizeFileTime(current_module^.ppufilename^,current_module^.staticlibfilename^)
  439. else
  440. SynchronizeFileTime(current_module^.ppufilename^,current_module^.objfilename^);
  441. end;
  442. exit;
  443. end;
  444. {$endif NoAg386Bin}
  445. {$ifndef NoAg386Att}
  446. as_i386_as,
  447. as_i386_as_aout,
  448. as_i386_asw :
  449. a:=new(pi386attasmlist,Init(smart));
  450. {$endif NoAg386Att}
  451. {$ifndef NoAg386Nsm}
  452. as_i386_nasmcoff,
  453. as_i386_nasmelf,
  454. as_i386_nasmobj :
  455. a:=new(pi386nasmasmlist,Init(smart));
  456. {$endif NoAg386Nsm}
  457. {$ifndef NoAg386Int}
  458. as_i386_tasm :
  459. a:=new(pi386intasmlist,Init(smart));
  460. {$endif NoAg386Int}
  461. {$endif}
  462. {$ifdef m68k}
  463. {$ifndef NoAg68kGas}
  464. as_m68k_as,
  465. as_m68k_gas :
  466. a:=new(pm68kgasasmlist,Init(smart));
  467. {$endif NoAg86KGas}
  468. {$ifndef NoAg68kMot}
  469. as_m68k_mot :
  470. a:=new(pm68kmotasmlist,Init(smart));
  471. {$endif NoAg86kMot}
  472. {$ifndef NoAg68kMit}
  473. as_m68k_mit :
  474. a:=new(pm68kmitasmlist,Init(smart));
  475. {$endif NoAg86KMot}
  476. {$ifndef NoAg68kMpw}
  477. as_m68k_mpw :
  478. a:=new(pm68kmpwasmlist,Init(smart));
  479. {$endif NoAg68kMpw}
  480. {$endif}
  481. else
  482. {$ifdef TP}
  483. exit;
  484. {$else}
  485. Message(asmw_f_assembler_output_not_supported);
  486. {$endif}
  487. end;
  488. a^.AsmCreate(cut_normal);
  489. a^.WriteAsmList;
  490. a^.AsmClose;
  491. a^.DoAssemble;
  492. a^.synchronize;
  493. dispose(a,Done);
  494. end;
  495. Procedure OnlyAsm;
  496. var
  497. a : PAsmList;
  498. begin
  499. a:=new(pasmlist,Init(false));
  500. a^.DoAssemble;
  501. dispose(a,Done);
  502. end;
  503. end.
  504. {
  505. $Log$
  506. Revision 1.59 2000-01-07 01:14:19 peter
  507. * updated copyright to 2000
  508. Revision 1.58 1999/11/12 11:03:49 peter
  509. * searchpaths changed to stringqueue object
  510. Revision 1.57 1999/11/08 10:37:12 peter
  511. * filename fixes for win32 imports for units with multiple needed dll's
  512. Revision 1.56 1999/11/06 14:34:17 peter
  513. * truncated log to 20 revs
  514. Revision 1.55 1999/11/02 15:06:57 peter
  515. * import library fixes for win32
  516. * alignment works again
  517. Revision 1.54 1999/09/16 11:34:44 pierre
  518. * typo correction
  519. Revision 1.53 1999/09/02 18:47:44 daniel
  520. * Could not compile with TP, some arrays moved to heap
  521. * NOAG386BIN default for TP
  522. * AG386* files were not compatible with TP, fixed.
  523. Revision 1.52 1999/07/18 10:19:42 florian
  524. * made it compilable with Dlephi 4 again
  525. + fixed problem with large stack allocations on win32
  526. Revision 1.51 1999/07/10 10:12:03 peter
  527. * assembler smartlink message
  528. Revision 1.50 1999/07/03 00:27:05 peter
  529. * better smartlinking support
  530. Revision 1.49 1999/06/28 16:02:29 peter
  531. * merged
  532. Revision 1.48.2.1 1999/06/28 15:55:39 peter
  533. * also search path if not found in utilsdirectory
  534. Revision 1.48 1999/05/27 19:44:03 peter
  535. * removed oldasm
  536. * plabel -> pasmlabel
  537. * -a switches to source writing automaticly
  538. * assembler readers OOPed
  539. * asmsymbol automaticly external
  540. * jumptables and other label fixes for asm readers
  541. Revision 1.47 1999/05/13 21:59:19 peter
  542. * removed oldppu code
  543. * warning if objpas is loaded from uses
  544. * first things for new deref writing
  545. Revision 1.46 1999/05/05 22:21:48 peter
  546. * updated messages
  547. Revision 1.45 1999/05/04 21:44:33 florian
  548. * changes to compile it with Delphi 4.0
  549. Revision 1.44 1999/05/02 23:28:42 peter
  550. * don't include ag386bin for oldasm
  551. Revision 1.43 1999/05/02 22:41:51 peter
  552. * moved section names to systems
  553. * fixed nasm,intel writer
  554. Revision 1.42 1999/05/01 13:24:00 peter
  555. * merged nasm compiler
  556. * old asm moved to oldasm/
  557. Revision 1.41 1999/03/24 23:16:42 peter
  558. * fixed bugs 212,222,225,227,229,231,233
  559. Revision 1.40 1999/03/18 20:30:44 peter
  560. + .a writer
  561. Revision 1.39 1999/03/01 15:43:48 peter
  562. * synchronize also the objfile for ag386bin
  563. Revision 1.38 1999/02/26 00:48:15 peter
  564. * assembler writers fixed for ag386bin
  565. Revision 1.37 1999/02/24 00:59:11 peter
  566. * small updates for ag386bin
  567. }