agjasmin.pas 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814
  1. {
  2. Copyright (c) 1998-2010 by the Free Pascal team
  3. This unit implements the Jasmin assembler writer
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. { Unit for writing Jasmin assembler (JVM bytecode) output.
  18. }
  19. unit agjasmin;
  20. {$i fpcdefs.inc}
  21. interface
  22. uses
  23. cclasses,
  24. globtype,globals,
  25. symbase,symdef,
  26. aasmbase,aasmtai,aasmdata,aasmcpu,
  27. assemble;
  28. type
  29. TJasminInstrWriter = class;
  30. {# This is a derived class which is used to write
  31. Jasmin-styled assembler.
  32. }
  33. { TJasminAssembler }
  34. TJasminAssembler=class(texternalassembler)
  35. protected
  36. jasminjar: tcmdstr;
  37. asmfiles: TCmdStrList;
  38. procedure WriteExtraHeader(obj: tobjectdef);
  39. procedure WriteInstruction(hp: tai);
  40. procedure NewAsmFileForObjectDef(obj: tobjectdef);
  41. function MethodDefinition(pd: tprocdef): string;
  42. procedure WriteProcDef(pd: tprocdef);
  43. procedure WriteSymtableProcdefs(st: TSymtable);
  44. procedure WriteSymtableObjectDefs(st: TSymtable);
  45. public
  46. constructor Create(smart: boolean); override;
  47. function MakeCmdLine: TCmdStr;override;
  48. procedure WriteTree(p:TAsmList);override;
  49. procedure WriteAsmList;override;
  50. destructor destroy; override;
  51. protected
  52. InstrWriter: TJasminInstrWriter;
  53. end;
  54. {# This is the base class for writing instructions.
  55. The WriteInstruction() method must be overridden
  56. to write a single instruction to the assembler
  57. file.
  58. }
  59. { TJasminInstrWriter }
  60. TJasminInstrWriter = class
  61. constructor create(_owner: TJasminAssembler);
  62. procedure WriteInstruction(hp : tai); virtual;
  63. protected
  64. owner: TJasminAssembler;
  65. end;
  66. implementation
  67. uses
  68. SysUtils,
  69. cutils,cfileutl,systems,script,
  70. fmodule,finput,verbose,
  71. symconst,symtype,
  72. itcpujas,cpubase,cgutils,
  73. widestr
  74. ;
  75. const
  76. line_length = 70;
  77. type
  78. t64bitarray = array[0..7] of byte;
  79. t32bitarray = array[0..3] of byte;
  80. {****************************************************************************}
  81. { Support routines }
  82. {****************************************************************************}
  83. function fixline(s:string):string;
  84. {
  85. return s with all leading and ending spaces and tabs removed
  86. }
  87. var
  88. i,j,k : integer;
  89. begin
  90. i:=length(s);
  91. while (i>0) and (s[i] in [#9,' ']) do
  92. dec(i);
  93. j:=1;
  94. while (j<i) and (s[j] in [#9,' ']) do
  95. inc(j);
  96. for k:=j to i do
  97. if s[k] in [#0..#31,#127..#255] then
  98. s[k]:='.';
  99. fixline:=Copy(s,j,i-j+1);
  100. end;
  101. {****************************************************************************}
  102. { Jasmin Assembler writer }
  103. {****************************************************************************}
  104. destructor TJasminAssembler.Destroy;
  105. begin
  106. InstrWriter.free;
  107. asmfiles.free;
  108. inherited destroy;
  109. end;
  110. procedure TJasminAssembler.WriteTree(p:TAsmList);
  111. var
  112. ch : char;
  113. hp : tai;
  114. hp1 : tailineinfo;
  115. constdef : taiconst_type;
  116. s,t : string;
  117. i,pos,l : longint;
  118. InlineLevel : longint;
  119. last_align : longint;
  120. co : comp;
  121. sin : single;
  122. d : double;
  123. do_line : boolean;
  124. sepChar : char;
  125. begin
  126. if not assigned(p) then
  127. exit;
  128. last_align := 2;
  129. InlineLevel:=0;
  130. { lineinfo is only needed for al_procedures (PFV) }
  131. do_line:=(cs_asm_source in current_settings.globalswitches) or
  132. ((cs_lineinfo in current_settings.moduleswitches)
  133. and (p=current_asmdata.asmlists[al_procedures]));
  134. hp:=tai(p.first);
  135. while assigned(hp) do
  136. begin
  137. prefetch(pointer(hp.next)^);
  138. if not(hp.typ in SkipLineInfo) then
  139. begin
  140. hp1 := hp as tailineinfo;
  141. current_filepos:=hp1.fileinfo;
  142. { no line info for inlined code }
  143. if do_line and (inlinelevel=0) then
  144. begin
  145. { load infile }
  146. if lastfileinfo.fileindex<>hp1.fileinfo.fileindex then
  147. begin
  148. infile:=current_module.sourcefiles.get_file(hp1.fileinfo.fileindex);
  149. if assigned(infile) then
  150. begin
  151. { open only if needed !! }
  152. if (cs_asm_source in current_settings.globalswitches) then
  153. infile.open;
  154. end;
  155. { avoid unnecessary reopens of the same file !! }
  156. lastfileinfo.fileindex:=hp1.fileinfo.fileindex;
  157. { be sure to change line !! }
  158. lastfileinfo.line:=-1;
  159. end;
  160. { write source }
  161. if (cs_asm_source in current_settings.globalswitches) and
  162. assigned(infile) then
  163. begin
  164. if (infile<>lastinfile) then
  165. begin
  166. AsmWriteLn(target_asm.comment+'['+infile.name^+']');
  167. if assigned(lastinfile) then
  168. lastinfile.close;
  169. end;
  170. if (hp1.fileinfo.line<>lastfileinfo.line) and
  171. ((hp1.fileinfo.line<infile.maxlinebuf) or (InlineLevel>0)) then
  172. begin
  173. if (hp1.fileinfo.line<>0) and
  174. ((infile.linebuf^[hp1.fileinfo.line]>=0) or (InlineLevel>0)) then
  175. AsmWriteLn(target_asm.comment+'['+tostr(hp1.fileinfo.line)+'] '+
  176. fixline(infile.GetLineStr(hp1.fileinfo.line)));
  177. { set it to a negative value !
  178. to make that is has been read already !! PM }
  179. if (infile.linebuf^[hp1.fileinfo.line]>=0) then
  180. infile.linebuf^[hp1.fileinfo.line]:=-infile.linebuf^[hp1.fileinfo.line]-1;
  181. end;
  182. end;
  183. lastfileinfo:=hp1.fileinfo;
  184. lastinfile:=infile;
  185. end;
  186. end;
  187. case hp.typ of
  188. ait_comment :
  189. Begin
  190. AsmWrite(target_asm.comment);
  191. AsmWritePChar(tai_comment(hp).str);
  192. AsmLn;
  193. End;
  194. ait_regalloc :
  195. begin
  196. if (cs_asm_regalloc in current_settings.globalswitches) then
  197. begin
  198. AsmWrite(#9+target_asm.comment+'Register ');
  199. repeat
  200. AsmWrite(std_regname(Tai_regalloc(hp).reg));
  201. if (hp.next=nil) or
  202. (tai(hp.next).typ<>ait_regalloc) or
  203. (tai_regalloc(hp.next).ratype<>tai_regalloc(hp).ratype) then
  204. break;
  205. hp:=tai(hp.next);
  206. AsmWrite(',');
  207. until false;
  208. AsmWrite(' ');
  209. AsmWriteLn(regallocstr[tai_regalloc(hp).ratype]);
  210. end;
  211. end;
  212. ait_tempalloc :
  213. begin
  214. if (cs_asm_tempalloc in current_settings.globalswitches) then
  215. begin
  216. {$ifdef EXTDEBUG}
  217. if assigned(tai_tempalloc(hp).problem) then
  218. AsmWriteLn(target_asm.comment+'Temp '+tostr(tai_tempalloc(hp).temppos)+','+
  219. tostr(tai_tempalloc(hp).tempsize)+' '+tai_tempalloc(hp).problem^)
  220. else
  221. {$endif EXTDEBUG}
  222. AsmWriteLn(target_asm.comment+'Temp '+tostr(tai_tempalloc(hp).temppos)+','+
  223. tostr(tai_tempalloc(hp).tempsize)+' '+tempallocstr[tai_tempalloc(hp).allocation]);
  224. end;
  225. end;
  226. ait_align :
  227. begin
  228. end;
  229. ait_section :
  230. begin
  231. end;
  232. ait_datablock :
  233. begin
  234. internalerror(2010122701);
  235. end;
  236. ait_const:
  237. begin
  238. AsmWriteln('constant');
  239. // internalerror(2010122702);
  240. end;
  241. ait_real_64bit :
  242. begin
  243. internalerror(2010122703);
  244. end;
  245. ait_real_32bit :
  246. begin
  247. internalerror(2010122703);
  248. end;
  249. ait_comp_64bit :
  250. begin
  251. internalerror(2010122704);
  252. end;
  253. ait_string :
  254. begin
  255. pos:=0;
  256. for i:=1 to tai_string(hp).len do
  257. begin
  258. if pos=0 then
  259. begin
  260. AsmWrite(#9'strconst: '#9'"');
  261. pos:=20;
  262. end;
  263. ch:=tai_string(hp).str[i-1];
  264. case ch of
  265. #0, {This can't be done by range, because a bug in FPC}
  266. #1..#31,
  267. #128..#255 : s:='\'+tostr(ord(ch) shr 6)+tostr((ord(ch) and 63) shr 3)+tostr(ord(ch) and 7);
  268. '"' : s:='\"';
  269. '\' : s:='\\';
  270. else
  271. s:=ch;
  272. end;
  273. AsmWrite(s);
  274. inc(pos,length(s));
  275. if (pos>line_length) or (i=tai_string(hp).len) then
  276. begin
  277. AsmWriteLn('"');
  278. pos:=0;
  279. end;
  280. end;
  281. end;
  282. ait_label :
  283. begin
  284. if (tai_label(hp).labsym.is_used) then
  285. begin
  286. AsmWrite(tai_label(hp).labsym.name);
  287. AsmWriteLn(':');
  288. end;
  289. end;
  290. ait_symbol :
  291. begin
  292. if (tai_symbol(hp).sym.typ = AT_FUNCTION) then
  293. begin
  294. end
  295. else
  296. begin
  297. AsmWrite('data symbol: ');
  298. AsmWriteln(tai_symbol(hp).sym.name);
  299. // internalerror(2010122706);
  300. end;
  301. end;
  302. ait_symbol_end :
  303. begin
  304. end;
  305. ait_instruction :
  306. begin
  307. WriteInstruction(hp);
  308. end;
  309. ait_force_line,
  310. ait_function_name : ;
  311. ait_cutobject :
  312. begin
  313. end;
  314. ait_marker :
  315. if tai_marker(hp).kind=mark_NoLineInfoStart then
  316. inc(InlineLevel)
  317. else if tai_marker(hp).kind=mark_NoLineInfoEnd then
  318. dec(InlineLevel);
  319. ait_directive :
  320. begin
  321. AsmWrite('.'+directivestr[tai_directive(hp).directive]+' ');
  322. if assigned(tai_directive(hp).name) then
  323. AsmWrite(tai_directive(hp).name^);
  324. AsmLn;
  325. end;
  326. else
  327. internalerror(2010122707);
  328. end;
  329. hp:=tai(hp.next);
  330. end;
  331. end;
  332. procedure TJasminAssembler.WriteExtraHeader(obj: tobjectdef);
  333. var
  334. superclass,
  335. intf: tobjectdef;
  336. n: string;
  337. i: longint;
  338. begin
  339. { JVM 1.5+ }
  340. AsmWriteLn('.bytecode 49.0');
  341. // include files are not support by Java, and the directory of the main
  342. // source file must not be specified
  343. if assigned(current_module.mainsource) then
  344. n:=ExtractFileName(current_module.mainsource^)
  345. else
  346. n:=InputFileName;
  347. AsmWriteLn('.source '+ExtractFileName(n));
  348. { class/interface name }
  349. if not assigned(obj) then
  350. begin
  351. { fake class type for unit -> name=unitname and
  352. superclass=java.lang.object }
  353. AsmWriteLn('.class '+ChangeFileExt(ExtractFileName(n),''));
  354. AsmWriteLn('.super java/lang/Object');
  355. end
  356. else
  357. begin
  358. case obj.objecttype of
  359. odt_javaclass:
  360. begin
  361. AsmWriteLn('.class '+obj.objextname^);
  362. superclass:=obj.childof;
  363. end;
  364. odt_interfacejava:
  365. begin
  366. AsmWriteLn('.interface abstract '+obj.objextname^);
  367. { interfaces must always specify Java.lang.object as
  368. superclass }
  369. superclass:=java_jlobject;
  370. end
  371. else
  372. internalerror(2011010906);
  373. end;
  374. { superclass }
  375. if assigned(superclass) then
  376. begin
  377. AsmWrite('.super ');
  378. if assigned(superclass.import_lib) then
  379. AsmWrite(superclass.import_lib^+'/');
  380. AsmWriteln(superclass.objextname^);
  381. end;
  382. { implemented interfaces }
  383. if assigned(obj.ImplementedInterfaces) then
  384. begin
  385. for i:=0 to obj.ImplementedInterfaces.count-1 do
  386. begin
  387. intf:=TImplementedInterface(obj.ImplementedInterfaces[i]).IntfDef;
  388. AsmWrite('.implements ');
  389. if assigned(intf.import_lib) then
  390. AsmWrite(intf.import_lib^+'/');
  391. AsmWriteln(intf.objextname^);
  392. end;
  393. end;
  394. end;
  395. AsmLn;
  396. end;
  397. procedure TJasminAssembler.WriteInstruction(hp: tai);
  398. begin
  399. InstrWriter.WriteInstruction(hp);
  400. end;
  401. function TJasminAssembler.MakeCmdLine: TCmdStr;
  402. const
  403. jasminjarname = 'jasmin.jar';
  404. var
  405. filenames: tcmdstr;
  406. jasminjarfound: boolean;
  407. begin
  408. if jasminjar='' then
  409. begin
  410. jasminjarfound:=false;
  411. if utilsdirectory<>'' then
  412. jasminjarfound:=FindFile(jasminjarname,utilsdirectory,false,jasminjar);
  413. if not jasminjarfound then
  414. jasminjarfound:=FindFileInExeLocations(jasminjarname,false,jasminjar);
  415. if (not jasminjarfound) and not(cs_asm_extern in current_settings.globalswitches) then
  416. begin
  417. Message1(exec_e_assembler_not_found,jasminjarname);
  418. current_settings.globalswitches:=current_settings.globalswitches+[cs_asm_extern];
  419. end;
  420. if jasminjarfound then
  421. Message1(exec_t_using_assembler,jasminjar);
  422. end;
  423. result:=target_asm.asmcmd;
  424. filenames:=maybequoted(ScriptFixFileName(AsmFileName));
  425. while not asmfiles.empty do
  426. filenames:=filenames+' '+asmfiles.GetFirst;
  427. Replace(result,'$ASM',filenames);
  428. if (path<>'') then
  429. Replace(result,'$OBJDIR',maybequoted(ScriptFixFileName(path)))
  430. else
  431. Replace(result,'$OBJDIR','.');
  432. Replace(result,'$JASMINJAR',maybequoted(ScriptFixFileName(jasminjar)));
  433. end;
  434. procedure TJasminAssembler.NewAsmFileForObjectDef(obj: tobjectdef);
  435. var
  436. enclosingobj: tobjectdef;
  437. st: tsymtable;
  438. begin
  439. if AsmSize<>AsmStartSize then
  440. begin
  441. AsmClose;
  442. asmfiles.Concat(maybequoted(ScriptFixFileName(AsmFileName)));
  443. end
  444. else
  445. AsmClear;
  446. AsmFileName:=obj.objextname^;
  447. st:=obj.owner;
  448. while assigned(st) and
  449. (st.symtabletype=objectsymtable) do
  450. begin
  451. { nested classes are named as "OuterClass$InnerClass" }
  452. enclosingobj:=tobjectdef(st.defowner);
  453. AsmFileName:=enclosingobj.objextname^+'$'+AsmFileName;
  454. st:=enclosingobj.owner;
  455. end;
  456. AsmFileName:=Path+FixFileName(AsmFileName)+target_info.asmext;
  457. AsmCreate(cut_normal);
  458. end;
  459. function TJasminAssembler.MethodDefinition(pd: tprocdef): string;
  460. begin
  461. case pd.visibility of
  462. vis_hidden,
  463. vis_strictprivate:
  464. result:='private ';
  465. vis_strictprotected:
  466. result:='protected ';
  467. vis_protected,
  468. vis_private,
  469. vis_public:
  470. result:='public ';
  471. else
  472. internalerror(2010122609);
  473. end;
  474. if (pd.procsym.owner.symtabletype in [globalsymtable,staticsymtable,localsymtable]) or
  475. (po_staticmethod in pd.procoptions) then
  476. result:=result+'static ';
  477. if is_javainterface(tdef(pd.owner.defowner)) then
  478. result:=result+'abstract ';
  479. result:=result+pd.jvmmangledbasename;
  480. end;
  481. procedure TJasminAssembler.WriteProcDef(pd: tprocdef);
  482. var
  483. procname: string;
  484. begin
  485. if not assigned(pd.exprasmlist) and
  486. (not is_javainterface(pd.struct) or
  487. (pd.proctypeoption in [potype_unitinit,potype_unitfinalize])) then
  488. exit;
  489. AsmWrite('.method ');
  490. AsmWriteln(MethodDefinition(pd));
  491. WriteTree(pd.exprasmlist);
  492. AsmWriteln('.end method');
  493. AsmLn;
  494. end;
  495. procedure TJasminAssembler.WriteSymtableProcdefs(st: TSymtable);
  496. var
  497. i : longint;
  498. def : tdef;
  499. obj : tobjectdef;
  500. begin
  501. if not assigned(st) then
  502. exit;
  503. for i:=0 to st.DefList.Count-1 do
  504. begin
  505. def:=tdef(st.DefList[i]);
  506. case def.typ of
  507. procdef :
  508. begin
  509. { methods are also in the static/globalsymtable of the unit
  510. -> make sure they are only written for the objectdefs that
  511. own them }
  512. if not(st.symtabletype in [staticsymtable,globalsymtable]) or
  513. (def.owner=st) then
  514. begin
  515. WriteProcDef(tprocdef(def));
  516. if assigned(tprocdef(def).localst) then
  517. WriteSymtableProcdefs(tprocdef(def).localst);
  518. end;
  519. end;
  520. end;
  521. end;
  522. end;
  523. procedure TJasminAssembler.WriteSymtableObjectDefs(st: TSymtable);
  524. var
  525. i : longint;
  526. def : tdef;
  527. obj : tobjectdef;
  528. nestedclasses: tfpobjectlist;
  529. begin
  530. if not assigned(st) then
  531. exit;
  532. nestedclasses:=tfpobjectlist.create(false);
  533. for i:=0 to st.DefList.Count-1 do
  534. begin
  535. def:=tdef(st.DefList[i]);
  536. case def.typ of
  537. objectdef:
  538. if not(oo_is_external in tobjectdef(def).objectoptions) then
  539. nestedclasses.add(def);
  540. end;
  541. end;
  542. for i:=0 to nestedclasses.count-1 do
  543. begin
  544. obj:=tobjectdef(nestedclasses[i]);
  545. NewAsmFileForObjectDef(obj);
  546. WriteExtraHeader(obj);
  547. WriteSymtableProcDefs(obj.symtable);
  548. WriteSymtableObjectDefs(obj.symtable);
  549. end;
  550. nestedclasses.free;
  551. end;
  552. constructor TJasminAssembler.Create(smart: boolean);
  553. begin
  554. inherited create(smart);
  555. InstrWriter:=TJasminInstrWriter.Create(self);
  556. asmfiles:=TCmdStrList.Create;
  557. end;
  558. procedure TJasminAssembler.WriteAsmList;
  559. var
  560. hal : tasmlisttype;
  561. i: longint;
  562. begin
  563. {$ifdef EXTDEBUG}
  564. if assigned(current_module.mainsource) then
  565. Comment(V_Debug,'Start writing Jasmin-styled assembler output for '+current_module.mainsource^);
  566. {$endif}
  567. AsmStartSize:=AsmSize;
  568. WriteExtraHeader(nil);
  569. (*
  570. for hal:=low(TasmlistType) to high(TasmlistType) do
  571. begin
  572. AsmWriteLn(target_asm.comment+'Begin asmlist '+AsmlistTypeStr[hal]);
  573. writetree(current_asmdata.asmlists[hal]);
  574. AsmWriteLn(target_asm.comment+'End asmlist '+AsmlistTypeStr[hal]);
  575. end;
  576. *)
  577. { print all global procedures/functions }
  578. WriteSymtableProcdefs(current_module.globalsymtable);
  579. WriteSymtableProcdefs(current_module.localsymtable);
  580. WriteSymtableObjectDefs(current_module.globalsymtable);
  581. WriteSymtableObjectDefs(current_module.localsymtable);
  582. AsmLn;
  583. {$ifdef EXTDEBUG}
  584. if assigned(current_module.mainsource) then
  585. Comment(V_Debug,'Done writing gas-styled assembler output for '+current_module.mainsource^);
  586. {$endif EXTDEBUG}
  587. end;
  588. {****************************************************************************}
  589. { Jasmin Instruction Writer }
  590. {****************************************************************************}
  591. constructor TJasminInstrWriter.create(_owner: TJasminAssembler);
  592. begin
  593. inherited create;
  594. owner := _owner;
  595. end;
  596. function getreferencestring(var ref : treference) : string;
  597. begin
  598. if (ref.arrayreftype<>art_none) or
  599. (ref.index<>NR_NO) then
  600. internalerror(2010122809);
  601. if assigned(ref.symbol) then
  602. begin
  603. // global symbol -> full type/name
  604. if (ref.base<>NR_NO) or
  605. (ref.offset<>0) then
  606. internalerror(2010122811);
  607. result:=ref.symbol.name;
  608. end
  609. else
  610. begin
  611. // local symbol -> stack slot, stored in offset
  612. if ref.base<>NR_STACK_POINTER_REG then
  613. internalerror(2010122810);
  614. result:=tostr(ref.offset);
  615. end;
  616. end;
  617. function getopstr(const o:toper) : ansistring;
  618. var
  619. i,runstart,runlen: longint;
  620. num: string[4];
  621. begin
  622. case o.typ of
  623. top_reg:
  624. // should have been translated into a memory location by the
  625. // register allocator)
  626. if (cs_no_regalloc in current_settings.globalswitches) then
  627. getopstr:=std_regname(o.reg)
  628. else
  629. internalerror(2010122803);
  630. top_const:
  631. str(o.val,result);
  632. top_ref:
  633. getopstr:=getreferencestring(o.ref^);
  634. top_single:
  635. str(o.sval:0:20,result);
  636. top_double:
  637. begin
  638. str(o.dval:0:20,result);
  639. // force interpretation as double
  640. result:=result+'d';
  641. end;
  642. top_string:
  643. begin
  644. { escape control codes }
  645. runlen:=0;
  646. runstart:=0;
  647. for i:=1 to o.pcvallen do
  648. begin
  649. if o.pcval[i]<#32 then
  650. begin
  651. if runlen>0 then
  652. begin
  653. setlength(result,length(result)+runlen);
  654. move(result[length(result)-runlen],o.pcval[runstart],runlen);
  655. runlen:=0;
  656. end;
  657. result:=result+'\u'+hexstr(ord(o.pcval[i]),4);
  658. end
  659. else if o.pcval[i]<#127 then
  660. begin
  661. if runlen=0 then
  662. runstart:=i;
  663. inc(runlen);
  664. end
  665. else
  666. // since Jasmin expects an UTF-16 string, we can't safely
  667. // have high ASCII characters since they'll be
  668. // re-interpreted as utf-16 anyway
  669. internalerror(2010122808);
  670. end;
  671. if runlen>0 then
  672. begin
  673. setlength(result,length(result)+runlen);
  674. move(result[length(result)-runlen],o.pcval[runstart],runlen);
  675. end;
  676. end;
  677. top_wstring:
  678. begin
  679. { escape control codes }
  680. for i:=1 to getlengthwidestring(o.pwstrval) do
  681. begin
  682. if (o.pwstrval^.data[i]<32) or
  683. (o.pwstrval^.data[i]>127) then
  684. result:=result+'\u'+hexstr(o.pwstrval^.data[i],4)
  685. else
  686. result:=result+char(o.pwstrval^.data[i]);
  687. end;
  688. end
  689. else
  690. internalerror(2010122802);
  691. end;
  692. end;
  693. procedure TJasminInstrWriter.WriteInstruction(hp: tai);
  694. var
  695. s: ansistring;
  696. i: byte;
  697. sep: string[3];
  698. begin
  699. s:=#9+jas_op2str[taicpu(hp).opcode];
  700. if taicpu(hp).ops<>0 then
  701. begin
  702. sep:=#9;
  703. for i:=0 to taicpu(hp).ops-1 do
  704. begin
  705. s:=s+sep+getopstr(taicpu(hp).oper[i]^);
  706. sep:=',';
  707. end;
  708. end;
  709. owner.AsmWriteLn(s);
  710. end;
  711. {****************************************************************************}
  712. { Jasmin Instruction Writer }
  713. {****************************************************************************}
  714. const
  715. as_jvm_jasmin_info : tasminfo =
  716. (
  717. id : as_jvm_jasmin;
  718. idtxt : 'Jasmin';
  719. asmbin : 'java';
  720. asmcmd : '-jar $JASMINJAR $ASM -d $OBJDIR';
  721. supported_targets : [system_jvm_java32];
  722. flags : [];
  723. labelprefix : 'L';
  724. comment : ' ; ';
  725. );
  726. begin
  727. RegisterAssembler(as_jvm_jasmin_info,TJasminAssembler);
  728. end.