1 (* ============================================================ *)
2 (* JsmnUtil is the module which writes jasmin file structures *)
3 (* Copyright (c) John Gough 1999, 2000. *)
4 (* ============================================================ *)
24 (* ============================================================ *)
28 pubStat
= Jvm
.att_public
+ Jvm
.att_static
;
29 modAttrib
= Jvm
.att_public
+ Jvm
.att_final
;
32 (* various Java-specific runtime name strings *)
34 initSuffix
* = "/<init>()V";
35 object
* = "java/lang/Object";
36 objectInit
* = "java/lang/Object/<init>()V";
37 mainStr
* = "main([Ljava/lang/String;)V";
38 jlExcept
* = "java/lang/Exception";
40 * jlError* = "java/lang/Error";
43 mkExcept
* = "java/lang/Exception/<init>(Ljava/lang/String;)V";
45 * mkError* = "java/lang/Error/<init>(Ljava/lang/String;)V";
48 putArgStr
* = "CP/CPmain/CPmain/PutArgs([Ljava/lang/String;)V";
50 (* ============================================================ *)
51 (* ============================================================ *)
53 TYPE ProcInfo
* = POINTER TO RECORD
54 prId
- : D
.Scope
; (* mth., prc. or mod. *)
55 lMax
: INTEGER; (* max locals for proc *)
56 lNum
: INTEGER; (* current locals proc *)
57 dMax
: INTEGER; (* max depth for proc. *)
58 dNum
: INTEGER; (* current depth proc. *)
59 attr
: SET; (* access attributes *)
64 (* ============================================================ *)
66 TYPE JsmnFile
* = POINTER TO RECORD (J
.JavaFile
)
67 file
* : GPTextFiles
.FILE
;
72 (* ============================================================ *)
74 TYPE TypeNameString
= ARRAY 12 OF CHAR;
75 ProcNameString
= ARRAY 90 OF CHAR;
77 (* ============================================================ *)
79 VAR typeName
: ARRAY 15 OF TypeNameString
; (* base type names *)
80 typeChar
: ARRAY 15 OF CHAR; (* base type chars *)
81 rtsProcs
: ARRAY 24 OF ProcNameString
;
83 (* ============================================================ *)
84 (* Constructor Method *)
85 (* ============================================================ *)
87 PROCEDURE newJsmnFile
*(fileName
: ARRAY OF CHAR) : JsmnFile
;
91 f
.file
:= GPTextFiles
.createFile(fileName
);
92 IF f
.file
= NIL THEN RETURN NIL; END;
96 (* ============================================================ *)
98 PROCEDURE^
(os
: JsmnFile
)Directive(dir
: INTEGER),NEW;
99 PROCEDURE^
(os
: JsmnFile
)DirectiveS(dir
: INTEGER;
100 IN str
: ARRAY OF CHAR),NEW;
101 PROCEDURE^
(os
: JsmnFile
)DirectiveIS(dir
: INTEGER; att
: SET;
102 IN str
: ARRAY OF CHAR),NEW;
103 PROCEDURE^
(os
: JsmnFile
)DirectiveISS(dir
: INTEGER; att
: SET;
104 IN s1
: ARRAY OF CHAR;
105 IN s2
: ARRAY OF CHAR),NEW;
106 PROCEDURE^
(os
: JsmnFile
)Call2
*(code
: INTEGER;
107 IN st1
: ARRAY OF CHAR;
108 IN st2
: ARRAY OF CHAR;
109 argL
,retL
: INTEGER),NEW;
111 (* ============================================================ *)
112 (* ============================================================ *)
113 (* ProcInfo Methods *)
114 (* ============================================================ *)
116 PROCEDURE newProcInfo
*(proc
: D
.Scope
) : ProcInfo
;
121 WITH proc
: Id
.Procs
DO
122 p
.lNum
:= proc
.rtsFram
;
123 p
.lMax
:= MAX(proc
.rtsFram
, 1);
134 (* ------------------------------------------------------------ *)
136 PROCEDURE (os
: JsmnFile
)StartProc
* (proc
: Id
.Procs
);
140 procName
: FileNames
.NameString
;
142 os
.proc
:= newProcInfo(proc
);
143 os
.Comment("PROCEDURE " + D
.getName
.ChPtr(proc
)^
);
145 * Compute the method attributes
147 IF proc
.kind
= Id
.conMth
THEN
148 method
:= proc(Id
.MthId
);
150 IF method
.mthAtt
* Id
.mask
= {} THEN attr
:= Jvm
.att_final
END;
151 IF method
.mthAtt
* Id
.mask
= Id
.isAbs
THEN
152 attr
:= attr
+ Jvm
.att_abstract
;
154 IF Id
.widen
IN method
.mthAtt
THEN attr
:= attr
+ Jvm
.att_public
END;
156 attr
:= Jvm
.att_static
;
159 * The following code fails for "implement-only" methods
160 * since the JVM places the "override method" in a different
161 * slot! We must thus live with the insecurity of public mode.
163 * IF proc.vMod = D.pubMode THEN (* explicitly public *)
165 IF (proc
.vMod
= D
.pubMode
) OR (* explicitly public *)
166 (proc
.vMod
= D
.rdoMode
) THEN (* "implement only" *)
167 attr
:= attr
+ Jvm
.att_public
;
168 ELSIF proc
.dfScp
IS Id
.PrcId
THEN (* nested procedure *)
169 attr
:= attr
+ Jvm
.att_private
;
171 FileNames
.StripUpToLast("/", proc
.prcNm
, procName
);
172 os
.DirectiveISS(Jvm
.dot_method
, attr
, procName$
, proc
.type
.xName
);
176 (* ------------------------------------------------------------ *)
178 PROCEDURE^
(os
: JsmnFile
)Locals(),NEW;
179 PROCEDURE^
(os
: JsmnFile
)Stack(),NEW;
180 PROCEDURE^
(os
: JsmnFile
)Blank(),NEW;
182 PROCEDURE (os
: JsmnFile
)EndProc
*();
184 IF (os
.proc
.attr
* Jvm
.att_abstract
# {}) THEN
185 os
.Comment("Abstract method");
190 os
.Directive(Jvm
.dot_end
);
194 PROCEDURE (os
: JsmnFile
)isAbstract
*() : BOOLEAN;
196 RETURN (os
.proc
.attr
* Jvm
.att_abstract
# {});
199 (* ------------------------------------------------------------ *)
201 PROCEDURE (os
: JsmnFile
)getScope
*() : D
.Scope
;
206 (* ------------------------------------------------------------ *)
208 PROCEDURE (os
: JsmnFile
)newLocal
*() : INTEGER;
215 IF info
.lNum
> info
.lMax
THEN info
.lMax
:= info
.lNum
END;
219 (* ------------------------------------------------------------ *)
221 PROCEDURE (os
: JsmnFile
)ReleaseLocal
*(i
: INTEGER);
224 * If you try to release not in LIFO order, the
225 * location will not be made free again. This is safe!
227 IF i
+1 = os
.proc
.lNum
THEN DEC(os
.proc
.lNum
) END;
230 (* ------------------------------------------------------------ *)
232 PROCEDURE (info
: ProcInfo
)numLocals
*() : INTEGER,NEW;
234 IF info
.lNum
= 0 THEN RETURN 1 ELSE RETURN info
.lNum
END;
237 (* ------------------------------------------------------------ *)
239 PROCEDURE (os
: JsmnFile
)markTop
*() : INTEGER;
244 (* ------------------------------------------------------------ *)
246 PROCEDURE (os
: JsmnFile
)ReleaseAll
*(m
: INTEGER);
251 (* ------------------------------------------------------------ *)
253 PROCEDURE (os
: JsmnFile
)getDepth
*() : INTEGER;
254 BEGIN RETURN os
.proc
.dNum
END getDepth
;
256 (* ------------------------------------------ *)
258 PROCEDURE (os
: JsmnFile
)setDepth
*(i
: INTEGER);
259 BEGIN os
.proc
.dNum
:= i
END setDepth
;
261 (* ============================================================ *)
263 (* ============================================================ *)
265 PROCEDURE (os
: JsmnFile
) ClinitHead
*();
267 os
.proc
:= newProcInfo(NIL);
268 os
.Comment("Class initializer");
269 os
.DirectiveIS(Jvm
.dot_method
, pubStat
, "<clinit>()V");
272 (* ============================================================ *)
274 PROCEDURE (os
: JsmnFile
)VoidTail
*();
276 os
.Code(Jvm
.opc_return
);
279 os
.Directive(Jvm
.dot_end
);
283 (* ============================================================ *)
285 PROCEDURE^
(os
: JsmnFile
)CallS
*(code
: INTEGER; IN str
: ARRAY OF CHAR;
286 argL
,retL
: INTEGER),NEW;
288 PROCEDURE (os
: JsmnFile
)MainHead
*();
290 os
.proc
:= newProcInfo(NIL);
291 os
.Comment("Main entry point");
292 os
.DirectiveIS(Jvm
.dot_method
, pubStat
, mainStr
);
294 * Save the command-line arguments to the RTS.
296 os
.Code(Jvm
.opc_aload_0
);
297 os
.CallS(Jvm
.opc_invokestatic
, putArgStr
, 1, 0);
300 (* ============================================================ *)
302 PROCEDURE (os
: JsmnFile
)ModNoArgInit
*();
305 os
.proc
:= newProcInfo(NIL);
306 os
.Comment("Standard no-arg constructor");
307 os
.DirectiveIS(Jvm
.dot_method
, Jvm
.att_public
, "<init>()V");
308 os
.Code(Jvm
.opc_aload_0
);
309 os
.CallS(Jvm
.opc_invokespecial
, objectInit
, 1, 0);
310 os
.Code(Jvm
.opc_return
);
312 os
.Directive(Jvm
.dot_end
);
316 (* ---------------------------------------------------- *)
318 PROCEDURE (os
: JsmnFile
)RecMakeInit
*(rec
: Ty
.Record
;
320 VAR pTp
: Ty
.Procedure
;
324 IF D
.noNew
IN rec
.xAttr
THEN
325 os
.Comment("There is no no-arg constructor for this class");
327 RETURN; (* PREMATURE RETURN HERE *)
328 ELSIF D
.xCtor
IN rec
.xAttr
THEN
329 os
.Comment("There is an explicit no-arg constructor for this class");
331 RETURN; (* PREMATURE RETURN HERE *)
334 os
.proc
:= newProcInfo(prc
);
336 * Get the procedure type, if any.
339 pTp
:= prc
.type(Ty
.Procedure
);
340 J
.MkCallAttr(prc
, pTp
);
341 os
.DirectiveISS(Jvm
.dot_method
, Jvm
.att_public
, initStr
, pTp
.xName
);
343 os
.Comment("Standard no-arg constructor");
345 os
.DirectiveIS(Jvm
.dot_method
, Jvm
.att_public
, "<init>()V");
347 os
.Code(Jvm
.opc_aload_0
);
353 * Copy the args to the super-constructor
355 FOR idx
:= 0 TO pNm
-1 DO os
.GetLocal(pTp
.formals
.a
[idx
]) END;
360 PROCEDURE (os
: JsmnFile
)CallSuperCtor
*(rec
: Ty
.Record
;
365 string2
: LitValue
.CharOpen
;
368 * Initialize the embedded superclass object.
370 IF (rec
.baseTp
# NIL) & (rec
.baseTp
# G
.anyRec
) THEN
372 string2
:= LitValue
.strToCharOpen("/" + initStr
+ pTy
.xName^
);
373 pNm
:= pTy
.formals
.tide
;
375 string2
:= LitValue
.strToCharOpen(initSuffix
);
378 os
.Call2(Jvm
.opc_invokespecial
,
379 rec
.baseTp(Ty
.Record
).xName
, string2
, pNm
+1, 0);
381 os
.CallS(Jvm
.opc_invokespecial
, objectInit
, 1, 0);
384 * Initialize fields, as necessary.
386 FOR idx
:= 0 TO rec
.fields
.tide
-1 DO
387 fld
:= rec
.fields
.a
[idx
];
388 IF (fld
.type
IS Ty
.Record
) OR (fld
.type
IS Ty
.Array
) THEN
389 os
.Comment("Initialize embedded object");
390 os
.Code(Jvm
.opc_aload_0
);
392 os
.PutGetF(Jvm
.opc_putfield
, rec
, fld(Id
.FldId
));
396 * os.Code(Jvm.opc_return);
398 * os.Directive(Jvm.dot_end);
403 (* ---------------------------------------------------- *)
405 PROCEDURE (os
: JsmnFile
)CopyProcHead
*(rec
: Ty
.Record
);
407 os
.proc
:= newProcInfo(NIL);
408 os
.Comment("standard record copy method");
409 os
.DirectiveIS(Jvm
.dot_method
, Jvm
.att_public
,
410 "__copy__(" + rec
.scopeNm^
+ ")V");
413 (* ============================================================ *)
414 (* Private Methods *)
415 (* ============================================================ *)
417 PROCEDURE (os
: JsmnFile
)Mark(),NEW;
419 GPTextFiles
.WriteChar(os
.file
, ";");
420 GPText
.WriteInt(os
.file
, os
.proc
.dNum
, 3);
421 GPText
.WriteInt(os
.file
, os
.proc
.dMax
, 3);
422 GPTextFiles
.WriteEOL(os
.file
);
425 (* ============================================================ *)
427 PROCEDURE (os
: JsmnFile
)CatStr(IN str
: ARRAY OF CHAR),NEW;
429 GPTextFiles
.WriteNChars(os
.file
, str
, LEN(str$
));
432 (* ============================================================ *)
434 PROCEDURE (os
: JsmnFile
)Tstring(IN str
: ARRAY OF CHAR),NEW;
436 GPTextFiles
.WriteChar(os
.file
, ASCII
.HT
);
437 GPTextFiles
.WriteNChars(os
.file
, str
, LEN(str$
));
440 (* ============================================================ *)
442 PROCEDURE (os
: JsmnFile
)Tint(int
: INTEGER),NEW;
444 GPTextFiles
.WriteChar(os
.file
, ASCII
.HT
);
445 GPText
.WriteInt(os
.file
, int
, 1);
448 (* ============================================================ *)
450 PROCEDURE (os
: JsmnFile
)Tlong(long
: LONGINT),NEW;
452 GPTextFiles
.WriteChar(os
.file
, ASCII
.HT
);
453 GPText
.WriteLong(os
.file
, long
, 1);
456 (* ============================================================ *)
458 PROCEDURE (os
: JsmnFile
)QuoteStr(IN str
: ARRAY OF CHAR),NEW;
464 GPTextFiles
.WriteChar(os
.file
, '
"');
467 | "\",'
"' : GPTextFiles.WriteChar(os.file, "\");
468 GPTextFiles
.WriteChar(os
.file
, ch
);
469 |
9X
: GPTextFiles
.WriteChar(os
.file
, "\");
470 GPTextFiles.WriteChar(os.file, "t
");
471 | 0AX : GPTextFiles.WriteChar(os.file, "\");
472 GPTextFiles
.WriteChar(os
.file
, "n");
474 GPTextFiles
.WriteChar(os
.file
, ch
);
479 GPTextFiles
.WriteChar(os
.file
, '
"');
482 (* ============================================================ *)
484 PROCEDURE (os : JsmnFile)Prefix(code : INTEGER),NEW;
486 GPTextFiles.WriteChar(os.file, ASCII.HT);
487 GPTextFiles.WriteNChars(os.file,Jvm.op[code],LEN(Jvm.op[code]$));
490 (* ============================================================ *)
492 PROCEDURE (os : JsmnFile)Suffix(code : INTEGER),NEW;
494 GPTextFiles.WriteEOL(os.file);
495 INC(os.proc.dNum, Jvm.dl[code]);
496 IF os.proc.dNum > os.proc.dMax THEN os.proc.dMax := os.proc.dNum END;
497 IF CompState.verbose THEN os.Mark() END;
500 (* ============================================================ *)
502 PROCEDURE (os : JsmnFile)Access(acc : SET),NEW;
505 FOR att := 0 TO 10 DO
507 GPText.WriteString(os.file, Jvm.access[att]);
508 GPTextFiles.WriteChar(os.file, ' ');
513 (* ============================================================ *)
515 PROCEDURE (os : JsmnFile)RefLab(l : J.Label),NEW;
517 GPTextFiles.WriteChar(os.file, ASCII.HT);
518 GPTextFiles.WriteChar(os.file, "l
");
519 GPTextFiles.WriteChar(os.file, "b
");
520 GPText.WriteInt(os.file, l.defIx, 1);
523 PROCEDURE (os : JsmnFile)AddSwitchLab*(l : J.Label; pos : INTEGER);
526 GPTextFiles.WriteEOL(os.file);
529 PROCEDURE (os : JsmnFile)LstDef*(l : J.Label);
531 GPText.WriteString(os.file, "default
:");
533 GPTextFiles.WriteEOL(os.file);
536 (* ============================================================ *)
538 PROCEDURE (os : JsmnFile)Idnt(idD : D.Idnt),NEW;
540 GPText.WriteString(os.file, D.getName.ChPtr(idD));
543 (* ============================================================ *)
545 PROCEDURE (os : JsmnFile)Type(typ : D.Type),NEW;
547 WITH typ : Ty.Base DO
548 GPText.WriteString(os.file, typ.xName);
550 IF typ.xName = NIL THEN J.MkVecName(typ) END;
551 GPText.WriteString(os.file, typ.xName);
552 | typ : Ty.Procedure DO
553 IF typ.xName = NIL THEN J.MkProcTypeName(typ) END;
554 GPText.WriteString(os.file, typ.hostClass.scopeNm);
556 GPTextFiles.WriteChar(os.file, "[");
559 IF typ.xName = NIL THEN J.MkRecName(typ) END;
560 GPText.WriteString(os.file, typ.scopeNm);
562 GPText.WriteString(os.file, G.intTp.xName);
563 | typ : Ty.Pointer DO
564 os.Type(typ.boundTp);
566 IF typ.xName = NIL THEN J.MkAliasName(typ) END;
567 GPText.WriteString(os.file, typ.scopeNm);
571 (* ============================================================ *)
573 PROCEDURE (os : JsmnFile)TypeTag(typ : D.Type),NEW;
575 WITH typ : Ty.Base DO
576 GPText.WriteString(os.file, typ.xName);
578 GPTextFiles.WriteChar(os.file, "[");
579 os.TypeTag(typ.elemTp);
581 IF typ.xName = NIL THEN J.MkRecName(typ) END;
582 GPText.WriteString(os.file, typ.xName);
583 | typ : Ty.Pointer DO
584 os.TypeTag(typ.boundTp);
586 IF typ.xName = NIL THEN J.MkAliasName(typ) END;
587 GPText.WriteString(os.file, typ.xName);
591 (* ============================================================ *)
592 (* Exported Methods *)
593 (* ============================================================ *)
595 PROCEDURE (os : JsmnFile)newLabel*() : J.Label;
601 lab.defIx := os.nxtLb;
605 (* ============================================================ *)
607 PROCEDURE (os : JsmnFile)getLabelRange*(VAR labs : ARRAY OF J.Label);
614 labNo := os.nxtLb + 1;
615 INC(os.nxtLb, count);
616 FOR i := 0 TO count-1 DO
618 labs[i].defIx := labNo;
623 (* ============================================================ *)
625 PROCEDURE (os : JsmnFile)Blank*(),NEW;
627 GPTextFiles.WriteEOL(os.file);
630 (* ============================================================ *)
632 PROCEDURE (os : JsmnFile)Directive(dir : INTEGER),NEW;
634 os.CatStr(Jvm.dirStr[dir]);
635 GPTextFiles.WriteEOL(os.file);
638 (* -------------------------------------------- *)
640 PROCEDURE (os : JsmnFile)DirectiveS(dir : INTEGER;
641 IN str : ARRAY OF CHAR),NEW;
643 os.CatStr(Jvm.dirStr[dir]);
644 GPTextFiles.WriteChar(os.file, " ");
645 GPTextFiles.WriteNChars(os.file, str, LEN(str$));
646 GPTextFiles.WriteEOL(os.file);
649 (* -------------------------------------------- *)
651 PROCEDURE (os : JsmnFile)DirectiveIS(dir : INTEGER;
653 IN str : ARRAY OF CHAR),NEW;
655 os.CatStr(Jvm.dirStr[dir]);
656 GPTextFiles.WriteChar(os.file, " ");
658 GPTextFiles.WriteNChars(os.file, str, LEN(str$));
659 GPTextFiles.WriteEOL(os.file);
662 (* -------------------------------------------- *)
664 PROCEDURE (os : JsmnFile)DirectiveISS(dir : INTEGER;
666 IN s1 : ARRAY OF CHAR;
667 IN s2 : ARRAY OF CHAR),NEW;
669 os.CatStr(Jvm.dirStr[dir]);
670 GPTextFiles.WriteChar(os.file, " ");
672 GPTextFiles.WriteNChars(os.file, s1, LEN(s1$));
673 GPTextFiles.WriteNChars(os.file, s2, LEN(s2$));
674 GPTextFiles.WriteEOL(os.file);
677 (* -------------------------------------------- *)
679 PROCEDURE (os : JsmnFile)Comment*(IN s : ARRAY OF CHAR);
681 GPTextFiles.WriteChar(os.file, ";");
682 GPTextFiles.WriteChar(os.file, " ");
683 GPTextFiles.WriteNChars(os.file, s, LEN(s$));
684 GPTextFiles.WriteEOL(os.file);
687 (* ============================================================ *)
689 PROCEDURE (os : JsmnFile)DefLab*(l : J.Label);
691 GPTextFiles.WriteChar(os.file, "l
");
692 GPTextFiles.WriteChar(os.file, "b
");
693 GPText.WriteInt(os.file, l.defIx, 1);
694 GPTextFiles.WriteChar(os.file, ":");
695 GPTextFiles.WriteEOL(os.file);
698 (* -------------------------------------------- *)
700 PROCEDURE (os : JsmnFile)DefLabC*(l : J.Label; IN c : ARRAY OF CHAR);
702 GPTextFiles.WriteChar(os.file, "l
");
703 GPTextFiles.WriteChar(os.file, "b
");
704 GPText.WriteInt(os.file, l.defIx, 1);
705 GPTextFiles.WriteChar(os.file, ":");
706 GPTextFiles.WriteChar(os.file, ASCII.HT);
710 (* ============================================================ *)
712 PROCEDURE (os : JsmnFile)Code*(code : INTEGER);
718 (* -------------------------------------------- *)
720 PROCEDURE (os : JsmnFile)CodeI*(code,int : INTEGER);
727 (* -------------------------------------------- *)
729 PROCEDURE (os : JsmnFile)CodeT*(code : INTEGER; type : D.Type);
732 GPTextFiles.WriteChar(os.file, ASCII.HT);
737 (* -------------------------------------------- *)
739 PROCEDURE (os : JsmnFile)CodeL*(code : INTEGER; long : LONGINT);
746 (* -------------------------------------------- *)
748 PROCEDURE (os : JsmnFile)CodeR*(code : INTEGER; real : REAL; short : BOOLEAN);
749 VAR nam : ARRAY 64 OF CHAR;
752 RTS.RealToStr(real, nam);
757 (* -------------------------------------------- *)
759 PROCEDURE (os : JsmnFile)CodeLb*(code : INTEGER; i2 : J.Label);
766 (* -------------------------------------------- *)
768 PROCEDURE (os : JsmnFile)CodeII*(code,i1,i2 : INTEGER),NEW;
776 (* -------------------------------------------- *)
778 PROCEDURE (os : JsmnFile)CodeInc*(localIx, incVal : INTEGER);
780 os.CodeII(Jvm.opc_iinc, localIx, incVal);
783 (* -------------------------------------------- *)
785 PROCEDURE (os : JsmnFile)CodeS*(code : INTEGER; IN str : ARRAY OF CHAR),NEW;
792 (* -------------------------------------------- *)
794 PROCEDURE (os : JsmnFile)CodeC*(code : INTEGER; IN str : ARRAY OF CHAR);
797 GPTextFiles.WriteNChars(os.file, str, LEN(str$));
801 (* -------------------------------------------- *)
803 PROCEDURE (os : JsmnFile)CodeSwitch*(loIx,hiIx : INTEGER; dfLb : J.Label);
805 os.CodeII(Jvm.opc_tableswitch,loIx,hiIx);
808 (* -------------------------------------------- *)
810 PROCEDURE (os : JsmnFile)PushStr*(IN str : LitValue.CharOpen);
811 (* Use target quoting conventions for the literal string *)
813 os.Prefix(Jvm.opc_ldc);
814 GPTextFiles.WriteChar(os.file, ASCII.HT);
816 os.Suffix(Jvm.opc_ldc);
819 (* ============================================================ *)
821 PROCEDURE (os : JsmnFile)CallS*(code : INTEGER;
822 IN str : ARRAY OF CHAR;
823 argL,retL : INTEGER),NEW;
827 IF code = Jvm.opc_invokeinterface THEN os.Tint(argL) END;
828 GPTextFiles.WriteEOL(os.file);
829 INC(os.proc.dNum, retL-argL);
830 IF os.proc.dNum > os.proc.dMax THEN os.proc.dMax := os.proc.dNum END;
831 IF CompState.verbose THEN os.Mark() END;
834 (* ============================================================ *)
836 PROCEDURE (os : JsmnFile)CallIT*(code : INTEGER;
838 type : Ty.Procedure);
839 VAR argL, retL : INTEGER;
840 clsNam : LitValue.CharOpen;
843 IF proc.scopeNm = NIL THEN J.MkProcName(proc) END;
844 os.Tstring(proc.scopeNm);
845 GPTextFiles.WriteChar(os.file, "/");
846 WITH proc : Id.PrcId DO clsNam := proc.clsNm;
847 | proc : Id.MthId DO clsNam := proc.bndType(Ty.Record).extrnNm;
850 GPTextFiles.WriteChar(os.file, "/");
851 os.CatStr(proc.prcNm);
852 os.CatStr(type.xName);
855 IF code = Jvm.opc_invokeinterface THEN os.Tint(type.argN) END;
856 GPTextFiles.WriteEOL(os.file);
857 INC(os.proc.dNum, retL-argL);
858 IF os.proc.dNum > os.proc.dMax THEN os.proc.dMax := os.proc.dNum END;
859 IF CompState.verbose THEN os.Mark() END;
862 (* ============================================================ *)
864 PROCEDURE (os : JsmnFile)Call2*(code : INTEGER;
865 IN st1 : ARRAY OF CHAR;
866 IN st2 : ARRAY OF CHAR;
867 argL,retL : INTEGER),NEW;
872 IF code = Jvm.opc_invokeinterface THEN os.Tint(argL) END;
873 GPTextFiles.WriteEOL(os.file);
874 INC(os.proc.dNum, retL-argL);
875 IF os.proc.dNum > os.proc.dMax THEN os.proc.dMax := os.proc.dNum END;
876 IF CompState.verbose THEN os.Mark() END;
879 (* ============================================================ *)
881 PROCEDURE (os : JsmnFile)MultiNew*(elT : D.Type;
883 (* dsc is the array descriptor, dms the number of dimensions *)
886 os.Prefix(Jvm.opc_multianewarray);
887 GPTextFiles.WriteChar(os.file, ASCII.HT);
888 FOR i := 1 TO dms DO GPTextFiles.WriteChar(os.file, "[") END;
891 GPTextFiles.WriteEOL(os.file);
892 DEC(os.proc.dNum, dms-1);
895 (* ============================================================ *)
897 PROCEDURE (os : JsmnFile)PutGetS*(code : INTEGER;
901 (* Emit putstatic and getstatic for static field *)
904 IF blk.xName = NIL THEN J.MkBlkName(blk) END;
905 IF fld.varNm = NIL THEN J.MkVarName(fld) END;
906 os.Tstring(blk.scopeNm);
907 GPTextFiles.WriteChar(os.file, "/");
908 os.CatStr(fld.clsNm);
909 GPTextFiles.WriteChar(os.file, "/");
910 os.CatStr(fld.varNm);
911 GPTextFiles.WriteChar(os.file, " ");
913 GPTextFiles.WriteEOL(os.file);
914 size := J.jvmSize(fld.type);
915 IF code = Jvm.opc_getstatic THEN INC(os.proc.dNum, size);
916 ELSIF code = Jvm.opc_putstatic THEN DEC(os.proc.dNum, size);
918 IF os.proc.dNum > os.proc.dMax THEN os.proc.dMax := os.proc.dNum END;
919 IF CompState.verbose THEN os.Mark() END;
922 (* -------------------------------------------- *)
924 PROCEDURE (os : JsmnFile)PutGetF*(code : INTEGER;
931 (* Emit putfield and getfield for record field *)
934 GPTextFiles.WriteChar(os.file, ASCII.HT);
936 GPTextFiles.WriteChar(os.file, "/");
938 GPTextFiles.WriteChar(os.file, " ");
940 GPTextFiles.WriteEOL(os.file);
941 size := J.jvmSize(fld.type);
942 IF code = Jvm.opc_getfield THEN INC(os.proc.dNum, size-1);
943 ELSIF code = Jvm.opc_putfield THEN DEC(os.proc.dNum, size+1);
945 IF os.proc.dNum > os.proc.dMax THEN os.proc.dMax := os.proc.dNum END;
946 IF CompState.verbose THEN os.Mark() END;
949 (* ============================================================ *)
951 PROCEDURE (os : JsmnFile)Alloc1d*(elTp : D.Type);
953 WITH elTp : Ty.Base DO
954 IF (elTp.tpOrd < Ty.anyRec) THEN
955 os.CodeS(Jvm.opc_newarray, typeName[elTp.tpOrd]);
957 os.Prefix(Jvm.opc_anewarray);
959 os.Suffix(Jvm.opc_anewarray);
962 os.Prefix(Jvm.opc_anewarray);
963 GPTextFiles.WriteChar(os.file, ASCII.HT);
965 os.Suffix(Jvm.opc_anewarray);
969 (* ============================================================ *)
971 PROCEDURE (os : JsmnFile)MkNewRecord*(typ : Ty.Record);
973 os.CodeT(Jvm.opc_new, typ);
974 os.Code(Jvm.opc_dup);
975 os.Prefix(Jvm.opc_invokespecial);
976 os.Tstring(typ.xName);
977 os.CatStr(initSuffix);
978 os.Suffix(Jvm.opc_invokespecial);
981 (* ============================================================ *)
983 PROCEDURE (os : JsmnFile)MkNewFixedArray*(topE : D.Type; len0 : INTEGER);
989 // Fixed-size, possibly multi-dimensional arrays.
990 // The code relies on the semantic property in CP
991 // that the element-type of a fixed array type cannot
992 // be an open array. This simplifies the code somewhat.
998 * Find the number of dimensions ...
1001 WITH elTp : Ty.Array DO arTp := elTp ELSE EXIT END;
1002 elTp := arTp.elemTp;
1003 os.PushInt(arTp.length);
1009 * Stack is (top) len0, ref...
1011 IF elTp.kind = Ty.recTp THEN os.Init1dArray(elTp, len0) END;
1014 * Allocate the array headers for all dimensions.
1015 * Stack is (top) lenN, ... len0, ref...
1017 os.MultiNew(elTp, dims);
1019 * Stack is (top) ref...
1021 IF elTp.kind = Ty.recTp THEN os.InitNdArray(topE, elTp) END;
1023 END MkNewFixedArray;
1025 (* ============================================================ *)
1027 PROCEDURE (os : JsmnFile)MkNewOpenArray*(arrT : Ty.Array; dims : INTEGER);
1032 * Assert: lengths are pushed already...
1033 * and we know from semantic analysis that
1034 * the number of open array dimensions match
1035 * the number of integer LENs in dims.
1039 * Find the number of dimensions ...
1041 FOR indx := 0 TO dims-1 DO
1042 elTp := elTp(Ty.Array).elemTp;
1045 * Allocate the array headers for all _open_ dimensions.
1050 * Stack is now (top) ref ...
1051 * and we _might_ need to initialize the elements.
1053 IF (elTp.kind = Ty.recTp) OR
1054 (elTp.kind = Ty.arrTp) THEN
1055 os.Init1dArray(elTp, 0);
1058 os.MultiNew(elTp, dims);
1060 * Stack is now (top) ref ...
1061 * Now we _might_ need to initialize the elements.
1063 IF (elTp.kind = Ty.recTp) OR
1064 (elTp.kind = Ty.arrTp) THEN
1065 os.InitNdArray(arrT.elemTp, elTp);
1071 (* ============================================================ *)
1073 PROCEDURE (os : JsmnFile)MkArrayCopy*(arrT : Ty.Array);
1078 * Assert: we must find the lengths from the runtime
1079 * descriptors. Find the number of dimensions. The
1080 * array to copy is on the top of stack, which reads -
1083 elTp := arrT.elemTp;
1084 IF elTp.kind # Ty.arrTp THEN
1085 os.Code(Jvm.opc_arraylength); (* (top) len0, aRef,... *)
1086 os.Alloc1d(elTp); (* (top) aRef, ... *)
1087 IF elTp.kind = Ty.recTp THEN os.Init1dArray(elTp, 0) END; (*0 ==> open*)
1092 * Invariant: an array reference is on the top of
1093 * of the stack, which reads:
1094 * (top) [arRf, lengths,] arRf ...
1097 elTp := elTp(Ty.Array).elemTp;
1098 os.Code(Jvm.opc_dup); (* arRf, arRf,... *)
1099 os.Code(Jvm.opc_arraylength); (* len0, arRf, arRf,... *)
1100 os.Code(Jvm.opc_swap); (* arRf, len0, arRf,... *)
1101 os.Code(Jvm.opc_iconst_0); (* 0, arRf, len0, arRf,... *)
1102 os.Code(Jvm.opc_aaload); (* arRf, len0, arRf,... *)
1104 * Stack reads: (top) arRf, lenN, [lengths,] arRf ...
1106 UNTIL elTp.kind # Ty.arrTp;
1108 * Now get the final length...
1110 os.Code(Jvm.opc_arraylength);
1112 * Stack reads: (top) lenM, lenN, [lengths,] arRf ...
1113 * Allocate the array headers for all dimensions.
1115 os.MultiNew(elTp, dims);
1117 * Stack is (top) ref...
1119 IF elTp.kind = Ty.recTp THEN os.InitNdArray(arrT.elemTp, elTp) END;
1123 (* ============================================================ *)
1125 PROCEDURE (os : JsmnFile)VarInit*(var : D.Idnt);
1129 * Precondition: var is of a type that needs initialization
1132 WITH typ : Ty.Record DO
1133 os.MkNewRecord(typ);
1135 os.MkNewFixedArray(typ.elemTp, typ.length);
1137 os.Code(Jvm.opc_aconst_null);
1141 (* ============================================================ *)
1143 PROCEDURE (os : JsmnFile)ValRecCopy*(typ : Ty.Record);
1144 VAR nam : LitValue.CharOpen;
1147 * Stack at entry is (top) srcRef, dstRef...
1149 IF typ.xName = NIL THEN J.MkRecName(typ) END;
1151 os.CallS(Jvm.opc_invokevirtual,
1152 nam^ + "/__copy__(L
" + nam^ + ";)V
", 2, 0);
1156 (* ============================================================ *)
1158 PROCEDURE (os : JsmnFile)CallRTS*(ix,args,ret : INTEGER);
1160 os.CallS(Jvm.opc_invokestatic, rtsProcs[ix], args, ret);
1163 (* ============================================================ *)
1165 PROCEDURE (os : JsmnFile)CallGetClass*();
1167 os.CallS(Jvm.opc_invokevirtual, rtsProcs[J.GetTpM], 1, 1);
1170 (* ============================================================ *)
1172 PROCEDURE (os : JsmnFile)Trap*(IN str : ARRAY OF CHAR);
1174 os.CodeS(Jvm.opc_new, jlError);
1175 os.Code(Jvm.opc_dup);
1176 (* Do we need the quotes? *)
1177 os.PushStr(LitValue.strToCharOpen('"'
+ str
+ '
"'));
1178 os.CallS(Jvm.opc_invokespecial, mkError,2,0);
1179 os.Code(Jvm.opc_athrow);
1182 (* ============================================================ *)
1184 PROCEDURE (os : JsmnFile)CaseTrap*(i : INTEGER);
1186 os.CodeS(Jvm.opc_new, jlError);
1187 os.Code(Jvm.opc_dup);
1188 os.LoadLocal(i, G.intTp);
1189 os.CallS(Jvm.opc_invokestatic,
1190 "CP
/CPJrts
/CPJrts
/CaseMesg(I
)Ljava
/lang
/String
;",1,1);
1191 os.CallS(Jvm.opc_invokespecial, mkError,2,0);
1192 os.Code(Jvm.opc_athrow);
1195 (* ============================================================ *)
1197 PROCEDURE (os : JsmnFile)WithTrap*(id : D.Idnt);
1199 os.CodeS(Jvm.opc_new, jlError);
1200 os.Code(Jvm.opc_dup);
1202 os.CallS(Jvm.opc_invokestatic,
1203 "CP
/CPJrts
/CPJrts
/WithMesg(Ljava
/lang
/Object
;)Ljava
/lang
/String
;",1,1);
1204 os.CallS(Jvm.opc_invokespecial, mkError,2,0);
1205 os.Code(Jvm.opc_athrow);
1208 (* ============================================================ *)
1210 PROCEDURE (os : JsmnFile)Header*(IN str : ARRAY OF CHAR);
1211 VAR date : ARRAY 64 OF CHAR;
1213 RTS.GetDateString(date);
1214 os.Comment("Jasmin output produced by CPascal
compiler (" +
1215 RTS.defaultTarget + " version
)");
1216 os.Comment("at date
: " + date);
1217 os.Comment("from source file
<" + str + '>');
1220 (* ============================================================ *)
1222 PROCEDURE (os : JsmnFile)StartRecClass*(rec : Ty.Record);
1231 os.DirectiveS(Jvm.dot_source, CompState.srcNam);
1233 * Account for the record attributes.
1236 | Ty.noAtt : attSet := Jvm.att_final;
1237 | Ty.isAbs : attSet := Jvm.att_abstract;
1238 | Ty.limit : attSet := Jvm.att_empty;
1239 | Ty.extns : attSet := Jvm.att_empty;
1242 * Get the pointer IdDesc, if this is anonymous.
1244 IF rec.bindTp # NIL THEN
1245 clsId := rec.bindTp.idnt;
1250 * Account for the identifier visibility.
1253 IF clsId.vMod = D.pubMode THEN
1254 attSet := attSet + Jvm.att_public;
1255 ELSIF clsId.vMod = D.prvMode THEN
1256 attSet := attSet + Jvm.att_private;
1259 os.DirectiveIS(Jvm.dot_class, attSet, rec.xName);
1261 * Compute the super class attribute.
1263 baseT := rec.baseTp;
1264 WITH baseT : Ty.Record DO
1265 IF baseT.xName = NIL THEN J.MkRecName(baseT) END;
1266 os.DirectiveS(Jvm.dot_super, baseT.xName);
1268 os.DirectiveS(Jvm.dot_super, object);
1271 * Emit interface declarations (if any)
1273 IF rec.interfaces.tide > 0 THEN
1274 FOR index := 0 TO rec.interfaces.tide-1 DO
1275 impRec := rec.interfaces.a[index];
1276 baseT := impRec.boundRecTp();
1277 IF baseT.xName = NIL THEN J.MkRecName(baseT(Ty.Record)) END;
1278 os.DirectiveS(Jvm.dot_implements, baseT.xName);
1284 PROCEDURE (os : JsmnFile)StartModClass*(mod : Id.BlkId);
1286 IF mod.main THEN os.Comment("This module implements CPmain
") END;
1288 os.DirectiveS(Jvm.dot_source, CompState.srcNam);
1289 IF mod.scopeNm[0] = 0X THEN
1290 os.DirectiveIS(Jvm.dot_class, modAttrib, mod.xName);
1292 os.DirectiveISS(Jvm.dot_class, modAttrib, mod.scopeNm^ + '/', mod.xName);
1294 os.DirectiveS(Jvm.dot_super, object);
1298 (* ============================================================ *)
1300 PROCEDURE (os : JsmnFile)EmitField*(id : Id.AbVar);
1304 IF id IS Id.FldId THEN att := Jvm.att_empty;
1305 ELSE att := Jvm.att_static; END;
1306 IF id.vMod # D.prvMode THEN (* any export ==> public in JVM *)
1307 att := att + Jvm.att_public;
1309 os.CatStr(Jvm.dirStr[Jvm.dot_field]);
1310 GPTextFiles.WriteChar(os.file, " ");
1312 GPTextFiles.WriteChar(os.file, " ");
1314 GPTextFiles.WriteChar(os.file, " ");
1316 GPTextFiles.WriteEOL(os.file);
1319 (* ============================================================ *)
1321 PROCEDURE (os : JsmnFile)Line*(nm : INTEGER);
1323 os.CatStr(Jvm.dirStr[Jvm.dot_line]);
1325 GPTextFiles.WriteEOL(os.file);
1328 (* ============================================================ *)
1330 PROCEDURE (os : JsmnFile)Locals(),NEW;
1332 os.CatStr(Jvm.dirStr[Jvm.dot_limit]);
1333 os.CatStr(" locals
");
1334 os.Tint(os.proc.lMax);
1335 GPTextFiles.WriteEOL(os.file);
1338 (* ============================================================ *)
1340 PROCEDURE (os : JsmnFile)Stack(),NEW;
1342 os.CatStr(Jvm.dirStr[Jvm.dot_limit]);
1343 os.CatStr(" stack
");
1344 os.Tint(os.proc.dMax);
1345 GPTextFiles.WriteEOL(os.file);
1348 (* ============================================================ *)
1349 (* Namehandling Methods *)
1350 (* ============================================================ *)
1352 PROCEDURE (os : JsmnFile)LoadConst*(num : INTEGER);
1354 IF (num >= MIN(SHORTINT)) & (num <= MAX(SHORTINT)) THEN
1355 os.CodeI(Jvm.opc_sipush, num);
1357 os.CodeI(Jvm.opc_ldc, num);
1361 (* ------------------------------------------------------------ *)
1363 PROCEDURE (os : JsmnFile)Try*();
1364 VAR start : J.Label;
1366 start := os.newLabel();
1367 os.proc.exLb := os.newLabel();
1368 os.proc.hnLb := os.newLabel();
1369 os.CatStr(Jvm.dirStr[Jvm.dot_catch]);
1370 os.CatStr(" java
/lang
/Exception from lb
");
1371 GPText.WriteInt(os.file, start.defIx, 1);
1372 os.CatStr(" to lb
");
1373 GPText.WriteInt(os.file, os.proc.exLb.defIx, 1);
1374 os.CatStr(" using lb
");
1375 GPText.WriteInt(os.file, os.proc.hnLb.defIx, 1);
1376 GPTextFiles.WriteEOL(os.file);
1380 (* ------------------------------------------------------------ *)
1382 PROCEDURE (os : JsmnFile)MkNewException*();
1384 os.CodeS(Jvm.opc_new, jlExcept);
1387 PROCEDURE (os : JsmnFile)InitException*();
1389 os.CallS(Jvm.opc_invokespecial, mkExcept, 2,0);
1392 (* ------------------------------------------------------------ *)
1394 PROCEDURE (os : JsmnFile)Catch*(prc : Id.Procs);
1396 os.DefLab(os.proc.exLb);
1397 os.DefLab(os.proc.hnLb);
1398 os.StoreLocal(prc.except.varOrd, NIL);
1400 * Now make sure that the overall stack
1401 * depth computation is correctly initialized
1403 IF os.proc.dMax < 1 THEN os.proc.dMax := 1 END;
1407 (* ============================================================ *)
1409 PROCEDURE (jf : JsmnFile)Dump*();
1412 jf.Comment("end output produced by CPascal
");
1413 GPTextFiles.CloseFile(jf.file);
1416 (* ============================================================ *)
1417 (* ============================================================ *)
1420 typeChar[ 0] := "?
";
1421 typeChar[ Ty.boolN] := "Z
";
1422 typeChar[ Ty.sChrN] := "C
";
1423 typeChar[ Ty.charN] := "C
";
1424 typeChar[ Ty.byteN] := "B
";
1425 typeChar[ Ty.sIntN] := "S
";
1426 typeChar[ Ty.intN] := "I
";
1427 typeChar[ Ty.lIntN] := "J
";
1428 typeChar[ Ty.sReaN] := "F
";
1429 typeChar[ Ty.realN] := "D
";
1430 typeChar[ Ty.setN] := "I
";
1431 typeChar[Ty.anyRec] := "?
";
1432 typeChar[Ty.anyPtr] := "?
";
1433 typeChar[ Ty.strN] := "?
";
1434 typeChar[ Ty.sStrN] := "?
";
1437 typeName[ Ty.boolN] := "boolean
";
1438 typeName[ Ty.sChrN] := "char
";
1439 typeName[ Ty.charN] := "char
";
1440 typeName[ Ty.byteN] := "byte
";
1441 typeName[ Ty.sIntN] := "short
";
1442 typeName[ Ty.intN] := "int
";
1443 typeName[ Ty.lIntN] := "long
";
1444 typeName[ Ty.sReaN] := "float
";
1445 typeName[ Ty.realN] := "double
";
1446 typeName[ Ty.setN] := "int
";
1447 typeName[Ty.anyRec] := "";
1448 typeName[Ty.anyPtr] := "";
1449 typeName[ Ty.strN] := "";
1450 typeName[ Ty.sStrN] := "";
1452 rtsProcs[J.StrCmp] := "CP
/CPJrts
/CPJrts
/strCmp([C
[C
)I
";
1453 rtsProcs[J.StrToChrOpen] :=
1454 "CP
/CPJrts
/CPJrts
/JavaStrToChrOpen(Ljava
/lang
/String
;)[C
";
1455 rtsProcs[J.StrToChrs] :=
1456 "CP
/CPJrts
/CPJrts
/JavaStrToFixChr([CLjava
/lang
/String
;)V
";
1457 rtsProcs[J.ChrsToStr] :=
1458 "CP
/CPJrts
/CPJrts
/FixChToJavaStr([C
)Ljava
/lang
/String
;";
1459 rtsProcs[J.StrCheck] := "CP
/CPJrts
/CPJrts
/ChrArrCheck([C
)V
";
1460 rtsProcs[J.StrLen] := "CP
/CPJrts
/CPJrts
/ChrArrLength([C
)I
";
1461 rtsProcs[J.ToUpper] := "java
/lang
/Character
/toUpperCase(C
)C
";
1462 rtsProcs[J.DFloor] := "java
/lang
/Math
/floor(D
)D
";
1463 rtsProcs[J.ModI] := "CP
/CPJrts
/CPJrts
/CpModI(II
)I
";
1464 rtsProcs[J.ModL] := "CP
/CPJrts
/CPJrts
/CpModL(JJ
)J
";
1465 rtsProcs[J.DivI] := "CP
/CPJrts
/CPJrts
/CpDivI(II
)I
";
1466 rtsProcs[J.DivL] := "CP
/CPJrts
/CPJrts
/CpDivL(JJ
)J
";
1467 rtsProcs[J.StrCatAA] :=
1468 "CP
/CPJrts
/CPJrts
/ArrArrToString([C
[C
)Ljava
/lang
/String
;";
1469 rtsProcs[J.StrCatSA] :=
1470 "CP
/CPJrts
/CPJrts
/StrArrToString(Ljava
/lang
/String
;[C
)Ljava
/lang
/String
;";
1471 rtsProcs[J.StrCatAS] :=
1472 "CP
/CPJrts
/CPJrts
/ArrStrToString([CLjava
/lang
/String
;)Ljava
/lang
/String
;";
1473 rtsProcs[J.StrCatSS] := "CP
/CPJrts
/CPJrts
/StrStrToString(Ljava
/lang
/String
;Ljava
/lang
/String
;)Ljava
/lang
/String
;";
1474 rtsProcs[J.StrLP1] := "CP
/CPJrts
/CPJrts
/ChrArrLplus1([C
)I
";
1475 rtsProcs[J.StrVal] := "CP
/CPJrts
/CPJrts
/ChrArrStrCopy([C
[C
)V
";
1476 rtsProcs[J.SysExit] := "java
/lang
/System
/exit(I
)V
";
1477 rtsProcs[J.LoadTp1] := "CP
/CPJrts
/CPJrts
/getClassByOrd(I
)Ljava
/lang
/Class
;";
1478 rtsProcs[J.LoadTp2] :=
1479 "CP
/CPJrts
/CPJrts
/getClassByName(Ljava
/lang
/String
;)Ljava
/lang
/Class
;";
1480 rtsProcs[J.GetTpM] := "java
/lang
/Object
/getClass()Ljava
/lang
/Class
;";
1482 (* ============================================================ *)
1483 (* ============================================================ *)