2 (* ============================================================ *)
3 (* JavaUtil is the module which writes java classs file *)
5 (* Copyright (c) John Gough 1999, 2000. *)
6 (* Modified DWC September, 2000. *)
7 (* ============================================================ *)
27 (* ============================================================ *)
32 retMarker
* = -1; (* ==> out param is func-return *)
33 StrCmp
* = 1; (* indexes for rts procs *)
52 LoadTp1
* = 20; (* getClassByOrd *)
53 LoadTp2
* = 21; (* getClassByName *)
56 (* ============================================================ *)
58 TYPE JavaFile
* = POINTER TO ABSTRACT
RECORD
62 (* ============================================================ *)
64 TYPE Label
* = POINTER TO RECORD
68 (* ============================================================ *)
71 typeRetn
- : ARRAY 16 OF INTEGER;
72 typeLoad
- : ARRAY 16 OF INTEGER;
73 typeStore
- : ARRAY 16 OF INTEGER;
74 typePutE
- : ARRAY 16 OF INTEGER;
75 typeGetE
- : ARRAY 16 OF INTEGER;
77 VAR nmArray
* : L
.CharOpenSeq
;
78 fmArray
* : L
.CharOpenSeq
;
80 VAR semi
-,comma
-,colon
-,lPar
-,rPar
-,rParV
-,
81 brac
-,lCap
-, void
-,lowL
-,dlar
-,slsh
-,prfx
- : L
.CharOpen
;
83 (* ============================================================ *)
89 VAR invokeHash
: INTEGER;
90 ptvIx
: INTEGER; (* Index number for procedure type literals *)
91 procLitPrefix
: L
.CharOpen
;
93 (* ============================================================ *)
95 VAR vecBlkId
: Id
.BlkId
;
97 vecTypes
: ARRAY Ty
.anyPtr
+1 OF Id
.TypId
;
99 vecElms
: ARRAY Ty
.anyPtr
+1 OF Id
.FldId
;
100 vecExpnd
: ARRAY Ty
.anyPtr
+1 OF Id
.MthId
;
102 (* ============================================================ *)
104 PROCEDURE (jf
: JavaFile
)StartModClass
*(mod
: Id
.BlkId
),NEW,ABSTRACT
;
105 PROCEDURE (jf
: JavaFile
)StartRecClass
*(rec
: Ty
.Record
),NEW,ABSTRACT
;
106 PROCEDURE (jf
: JavaFile
)StartProc
*(proc
: Id
.Procs
),NEW,ABSTRACT
;
107 PROCEDURE (jf
: JavaFile
)EndProc
*(),NEW,EMPTY
;
108 PROCEDURE (jf
: JavaFile
)isAbstract
*():BOOLEAN,NEW,ABSTRACT
;
110 PROCEDURE (jf
: JavaFile
)getScope
*():Sym
.Scope
,NEW,ABSTRACT
;
112 PROCEDURE (jf
: JavaFile
) EmitField
*(field
: Id
.AbVar
),NEW,ABSTRACT
;
114 PROCEDURE (jf
: JavaFile
)MkNewRecord
*(typ
: Ty
.Record
),NEW,ABSTRACT
;
115 PROCEDURE (jf
: JavaFile
)MkNewFixedArray
*(topE
: Sym
.Type
;
116 len0
: INTEGER),NEW,ABSTRACT
;
117 PROCEDURE (jf
: JavaFile
)MkNewOpenArray
*(arrT
: Ty
.Array
;
118 dims
: INTEGER),NEW,ABSTRACT
;
119 PROCEDURE (jf
: JavaFile
)MkArrayCopy
*(arrT
: Ty
.Array
),NEW,ABSTRACT
;
121 PROCEDURE (jf
: JavaFile
)newLocal
*() : INTEGER,NEW,ABSTRACT
;
122 PROCEDURE (jf
: JavaFile
)ReleaseLocal
*(i
: INTEGER),NEW,ABSTRACT
;
123 PROCEDURE (jf
: JavaFile
)ReleaseAll
*(m
: INTEGER),NEW,ABSTRACT
;
125 PROCEDURE (jf
: JavaFile
)markTop
*() : INTEGER,NEW,ABSTRACT
;
126 PROCEDURE (jf
: JavaFile
)getDepth
*() : INTEGER,NEW,ABSTRACT
;
127 PROCEDURE (jf
: JavaFile
)setDepth
*(i
: INTEGER),NEW,ABSTRACT
;
129 PROCEDURE (jf
: JavaFile
)newLabel
*() : Label
,NEW,ABSTRACT
;
130 PROCEDURE (jf
: JavaFile
)getLabelRange
*(VAR labs
:ARRAY OF Label
),NEW,ABSTRACT
;
131 PROCEDURE (jf
: JavaFile
)AddSwitchLab
*(lab
: Label
;
132 pos
: INTEGER),NEW,ABSTRACT
;
135 PROCEDURE (jf
: JavaFile
)Comment
*(IN msg
: ARRAY OF CHAR),NEW,EMPTY
;
136 PROCEDURE (jf
: JavaFile
)Header
*(IN str
: ARRAY OF CHAR),NEW,EMPTY
;
138 PROCEDURE (jf
: JavaFile
)Code
*(code
: INTEGER),NEW,ABSTRACT
;
139 PROCEDURE (jf
: JavaFile
)CodeI
*(code
,val
: INTEGER),NEW,ABSTRACT
;
140 PROCEDURE (jf
: JavaFile
)CodeL
*(code
: INTEGER; num
: LONGINT),NEW,ABSTRACT
;
141 PROCEDURE (jf
: JavaFile
)CodeC
*(code
: INTEGER;
142 IN str
: ARRAY OF CHAR),NEW,ABSTRACT
;
143 PROCEDURE (jf
: JavaFile
)CodeR
*(code
: INTEGER;
144 num
: REAL; short
: BOOLEAN),NEW,ABSTRACT
;
145 PROCEDURE (jf
: JavaFile
)CodeLb
*(code
: INTEGER; lab
: Label
),NEW,ABSTRACT
;
146 PROCEDURE (jf
: JavaFile
)LstDef
*(l
: Label
),NEW,EMPTY
;
147 PROCEDURE (jf
: JavaFile
)DefLab
*(lab
: Label
),NEW,ABSTRACT
;
148 PROCEDURE (jf
: JavaFile
)DefLabC
*(lab
: Label
;
149 IN c
: ARRAY OF CHAR),NEW,ABSTRACT
;
150 PROCEDURE (jf
: JavaFile
)CodeInc
*(localIx
,incVal
: INTEGER),NEW,ABSTRACT
;
151 PROCEDURE (jf
: JavaFile
)CodeT
*(code
: INTEGER; ty
: Sym
.Type
),NEW,ABSTRACT
;
152 PROCEDURE (jf
: JavaFile
)CodeSwitch
*(low
,high
: INTEGER;
153 defLab
: Label
),NEW,ABSTRACT
;
155 PROCEDURE (jf
: JavaFile
)PushStr
*(IN str
: L
.CharOpen
),NEW,ABSTRACT
;
156 PROCEDURE (jf
: JavaFile
)LoadConst
*(num
: INTEGER),NEW,ABSTRACT
;
159 PROCEDURE (jf
: JavaFile
)CallGetClass
*(),NEW,ABSTRACT
;
160 PROCEDURE (jf
: JavaFile
)CallRTS
*(ix
,args
,ret
: INTEGER),NEW,ABSTRACT
;
161 PROCEDURE (jf
: JavaFile
)CallIT
*(code
: INTEGER;
163 type
: Ty
.Procedure
),NEW,ABSTRACT
;
166 PROCEDURE (jf
: JavaFile
)ClinitHead
*(),NEW,ABSTRACT
;
167 PROCEDURE (jf
: JavaFile
)MainHead
*(),NEW,ABSTRACT
;
168 PROCEDURE (jf
: JavaFile
)VoidTail
*(),NEW,ABSTRACT
;
169 PROCEDURE (jf
: JavaFile
)ModNoArgInit
*(),NEW,ABSTRACT
;
170 PROCEDURE (jf
: JavaFile
)RecMakeInit
*(rec
: Ty
.Record
;
171 prc
: Id
.PrcId
),NEW,ABSTRACT
;
172 PROCEDURE (jf
: JavaFile
)CallSuperCtor
*(rec
: Ty
.Record
;
173 pTy
: Ty
.Procedure
),NEW,ABSTRACT
;
174 PROCEDURE (jf
: JavaFile
)CopyProcHead
*(rec
: Ty
.Record
),NEW,ABSTRACT
;
175 PROCEDURE (jf
: JavaFile
)ValRecCopy
*(typ
: Ty
.Record
),NEW,ABSTRACT
;
177 PROCEDURE (jf
: JavaFile
)InitFields
*(num
: INTEGER),NEW,EMPTY
;
178 PROCEDURE (jf
: JavaFile
)InitMethods
*(num
: INTEGER),NEW,EMPTY
;
180 PROCEDURE (jf
: JavaFile
)Try
*(),NEW,ABSTRACT
;
181 PROCEDURE (jf
: JavaFile
)Catch
*(prc
: Id
.Procs
),NEW,ABSTRACT
;
182 PROCEDURE (jf
: JavaFile
)MkNewException
*(),NEW,ABSTRACT
;
183 PROCEDURE (jf
: JavaFile
)InitException
*(),NEW,ABSTRACT
;
185 PROCEDURE (jf
: JavaFile
)Dump
*(),NEW,ABSTRACT
;
187 (* ============================================================ *)
189 PROCEDURE (jf
: JavaFile
)PutGetS
*(code
: INTEGER; (* static field *)
191 fld
: Id
.VarId
),NEW,ABSTRACT
;
193 PROCEDURE (jf
: JavaFile
)PutGetF
*(code
: INTEGER; (* instance field *)
195 fld
: Id
.AbVar
),NEW,ABSTRACT
;
197 (* ============================================================ *)
199 PROCEDURE (jf
: JavaFile
)Alloc1d
*(elTp
: Sym
.Type
),NEW,ABSTRACT
;
200 PROCEDURE (jf
: JavaFile
)VarInit
*(var
: Sym
.Idnt
),NEW,ABSTRACT
;
201 PROCEDURE (jf
: JavaFile
)Trap
*(IN str
: ARRAY OF CHAR),NEW,ABSTRACT
;
202 PROCEDURE (jf
: JavaFile
)CaseTrap
*(i
: INTEGER),NEW,ABSTRACT
;
203 PROCEDURE (jf
: JavaFile
)WithTrap
*(id
: Sym
.Idnt
),NEW,ABSTRACT
;
204 PROCEDURE (jf
: JavaFile
)Line
*(nm
: INTEGER),NEW,ABSTRACT
;
206 (* ============================================================ *)
207 (* Some XHR utilities *)
208 (* ============================================================ *)
210 PROCEDURE^
(jf
: JavaFile
)PutUplevel
*(var
: Id
.LocId
),NEW;
211 PROCEDURE^
(jf
: JavaFile
)GetUplevel
*(var
: Id
.LocId
),NEW;
212 PROCEDURE^
(jf
: JavaFile
)PushInt
*(num
: INTEGER),NEW;
213 PROCEDURE^
(jf
: JavaFile
)PutElement
*(typ
: Sym
.Type
),NEW;
214 PROCEDURE^
(jf
: JavaFile
)GetElement
*(typ
: Sym
.Type
),NEW;
215 PROCEDURE^
(jf
: JavaFile
)ConvertDn
*(inT
, outT
: Sym
.Type
),NEW;
217 PROCEDURE^ cat2
*(i
,j
: L
.CharOpen
) : L
.CharOpen
;
218 PROCEDURE^ MkRecName
*(typ
: Ty
.Record
);
219 PROCEDURE^ MkProcName
*(proc
: Id
.Procs
);
220 PROCEDURE^
NumberParams(pIdn
: Id
.Procs
; pTyp
: Ty
.Procedure
);
221 PROCEDURE^
typeToChOpen(typ
: Sym
.Type
) : L
.CharOpen
;
224 (* ============================================================ *)
226 PROCEDURE xhrCount(tgt
, ths
: Id
.Procs
) : INTEGER;
229 IF ths
.lxDepth
= 0 THEN RETURN 0 END;
231 * "ths" is the calling procedure.
232 * "tgt" is the procedure with the uplevel data.
236 ths
:= ths
.dfScp(Id
.Procs
);
237 IF Id
.hasXHR
IN ths
.pAttr
THEN INC(count
) END;
238 UNTIL (ths
.lxDepth
= 0) OR
239 ((ths
.lxDepth
<= tgt
.lxDepth
) & (Id
.hasXHR
IN ths
.pAttr
));
243 PROCEDURE newXHR() : L
.CharOpen
;
246 RETURN cat2(xhrDl
, L
.intToCharOpen(xhrIx
));
249 PROCEDURE MkXHR(scp
: Id
.Procs
);
250 VAR typId
: Id
.TypId
;
256 Blt
.MkDummyClass(newXHR(), Cst
.thisMod
, Ty
.noAtt
, typId
);
257 typId
.SetMode(Sym
.prvMode
);
258 scp
.xhrType
:= typId
.type
;
259 recTp
:= typId
.type
.boundRecTp()(Ty
.Record
);
260 recTp
.baseTp
:= Cst
.rtsXHR
.boundRecTp();
261 INCL(recTp
.xAttr
, Sym
.noCpy
);
263 FOR index
:= 0 TO scp
.locals
.tide
-1 DO
264 locVr
:= scp
.locals
.a
[index
](Id
.LocId
);
265 IF Id
.uplevA
IN locVr
.locAtt
THEN
266 fldVr
:= Id
.newFldId();
267 fldVr
.hash
:= locVr
.hash
;
268 fldVr
.type
:= locVr
.type
;
269 fldVr
.recTyp
:= recTp
;
270 Sym
.AppendIdnt(recTp
.fields
, fldVr
);
275 (* ============================================================ *)
276 (* Some vector utilities *)
277 (* ============================================================ *)
279 PROCEDURE mapVecElTp(typ
: Sym
.Type
) : INTEGER;
281 WITH typ
: Ty
.Base
DO
283 | Ty
.sChrN
: RETURN Ty
.charN
;
284 | Ty
.boolN
, Ty
.byteN
, Ty
.sIntN
, Ty
.setN
, Ty
.uBytN
: RETURN Ty
.intN
;
285 | Ty
.charN
, Ty
.intN
, Ty
.lIntN
, Ty
.sReaN
, Ty
.realN
: RETURN typ
.tpOrd
;
286 ELSE RETURN Ty
.anyPtr
;
288 ELSE RETURN Ty
.anyPtr
;
292 PROCEDURE mapOrdRepT(ord
: INTEGER) : Sym
.Type
;
295 | Ty
.charN
: RETURN Blt
.charTp
;
296 | Ty
.intN
: RETURN Blt
.intTp
;
297 | Ty
.lIntN
: RETURN Blt
.lIntTp
;
298 | Ty
.sReaN
: RETURN Blt
.sReaTp
;
299 | Ty
.realN
: RETURN Blt
.realTp
;
300 | Ty
.anyPtr
: RETURN Blt
.anyPtr
;
304 (* ------------------------------------------------------------ *)
306 PROCEDURE InitVecDescriptors
;
312 FOR i
:= 0 TO Ty
.anyPtr
DO
317 END InitVecDescriptors
;
319 PROCEDURE vecModId() : Id
.BlkId
;
321 IF vecBlkId
= NIL THEN
322 Blt
.MkDummyImport("$CPJvec$", "CP.CPJvec", vecBlkId
);
323 Blt
.MkDummyClass("VecBase", vecBlkId
, Ty
.noAtt
, vecBase
);
325 * Initialize vecTide while we are at it ...
327 vecTide
:= Id
.newFldId();
328 vecTide
.hash
:= Hsh
.enterStr("tide");
329 vecTide
.dfScp
:= vecBlkId
;
330 vecTide
.recTyp
:= vecBase
.type
.boundRecTp();
331 vecTide
.type
:= Blt
.intTp
;
332 MkRecName(vecTide
.recTyp(Ty
.Record
));
337 PROCEDURE vecClsTyId(ord
: INTEGER) : Id
.TypId
;
338 VAR str
: ARRAY 8 OF CHAR;
342 IF vecTypes
[ord
] = NIL THEN
344 | Ty
.charN
: str
:= "VecChr";
345 | Ty
.intN
: str
:= "VecI32";
346 | Ty
.lIntN
: str
:= "VecI64";
347 | Ty
.sReaN
: str
:= "VecR32";
348 | Ty
.realN
: str
:= "VecR64";
349 | Ty
.anyPtr
: str
:= "VecRef";
351 Blt
.MkDummyClass(str
, vecModId(), Ty
.noAtt
, tId
);
352 rcT
:= tId
.type
.boundRecTp()(Ty
.Record
);
353 rcT
.baseTp
:= vecTide
.recTyp
;
354 vecTypes
[ord
] := tId
;
356 RETURN vecTypes
[ord
];
359 PROCEDURE vecRecTyp(ord
: INTEGER) : Ty
.Record
;
361 RETURN vecClsTyId(ord
).type
.boundRecTp()(Ty
.Record
);
364 PROCEDURE vecArrFlId(ord
: INTEGER) : Id
.FldId
;
367 IF vecElms
[ord
] = NIL THEN
368 fld
:= Id
.newFldId();
369 fld
.hash
:= Hsh
.enterStr("elms");
370 fld
.dfScp
:= vecModId();
371 fld
.recTyp
:= vecRecTyp(ord
);
372 fld
.type
:= Ty
.mkArrayOf(mapOrdRepT(ord
));
378 (* ------------------------------------------------------------ *)
380 PROCEDURE (jf
: JavaFile
)MkVecRec
*(eTp
: Sym
.Type
),NEW;
383 ord
:= mapVecElTp(eTp
);
384 jf
.MkNewRecord(vecRecTyp(ord
));
387 (* ------------------------------- *)
389 PROCEDURE (jf
: JavaFile
)MkVecArr
*(eTp
: Sym
.Type
),NEW;
393 ord
:= mapVecElTp(eTp
);
394 jf
.Alloc1d(mapOrdRepT(ord
));
395 jf
.PutGetF(Jvm
.opc_putfield
, vecRecTyp(ord
), vecArrFlId(ord
));
398 (* ------------------------------------------------------------ *)
400 PROCEDURE (jf
: JavaFile
)GetVecArr
*(eTp
: Sym
.Type
),NEW;
404 ord
:= mapVecElTp(eTp
);
405 fId
:= vecArrFlId(ord
);
406 jf
.PutGetF(Jvm
.opc_getfield
, fId
.recTyp(Ty
.Record
), fId
);
409 (* ------------------------------- *)
411 PROCEDURE (jf
: JavaFile
)GetVecLen
*(),NEW;
413 jf
.PutGetF(Jvm
.opc_getfield
, vecTide
.recTyp(Ty
.Record
), vecTide
);
416 (* ------------------------------- *)
418 PROCEDURE (jf
: JavaFile
)PutVecLen
*(),NEW;
420 jf
.PutGetF(Jvm
.opc_putfield
, vecTide
.recTyp(Ty
.Record
), vecTide
);
423 (* ------------------------------- *)
425 PROCEDURE (jf
: JavaFile
)InvokeExpand
*(eTp
: Sym
.Type
),NEW;
430 ord
:= mapVecElTp(eTp
);
431 IF vecExpnd
[ord
] = NIL THEN
432 mth
:= Id
.newMthId();
433 mth
.hash
:= Blt
.xpndBk
;
434 mth
.dfScp
:= vecModId();
435 typ
:= Ty
.newPrcTp();
437 typ
.receiver
:= vecClsTyId(ord
).type
;
438 mth
.bndType
:= typ
.receiver
.boundRecTp();
440 NumberParams(mth
, typ
);
442 vecExpnd
[ord
] := mth
;
444 mth
:= vecExpnd
[ord
];
445 typ
:= mth
.type(Ty
.Procedure
);
447 jf
.CallIT(Jvm
.opc_invokevirtual
, mth
, typ
);
450 (* ------------------------------- *)
452 PROCEDURE (jf
: JavaFile
)PutVecElement
*(eTp
: Sym
.Type
),NEW;
454 jf
.PutElement(mapOrdRepT(mapVecElTp(eTp
)));
457 (* ------------------------------- *)
459 PROCEDURE (jf
: JavaFile
)GetVecElement
*(eTp
: Sym
.Type
),NEW;
460 VAR rTp
: Sym
.Type
; (* representation type *)
462 rTp
:= mapOrdRepT(mapVecElTp(eTp
));
464 * If rTp and eTp are not equal, then must restore erased type
468 IF rTp
= Blt
.anyPtr
THEN
469 jf
.CodeT(Jvm
.opc_checkcast
, eTp
);
471 jf
.ConvertDn(rTp
, eTp
);
476 (* ============================================================ *)
477 (* Some static utilities *)
478 (* ============================================================ *)
480 PROCEDURE jvmSize
*(t
: Sym
.Type
) : INTEGER;
482 IF t
.isLongType() THEN RETURN 2 ELSE RETURN 1 END;
485 (* ------------------------------------------------------------ *)
487 PROCEDURE newAnonLit() : L
.CharOpen
;
490 RETURN cat2(procLitPrefix
, L
.intToCharOpen(ptvIx
));
493 (* ------------------------------------------------------------ *)
495 PROCEDURE needsBox
*(i
: Id
.ParId
) : BOOLEAN;
496 (* A parameter needs to be boxed if it has non-reference *)
497 (* representation in the JVM, and is OUT or VAR mode. *)
499 RETURN ((i
.parMod
= Sym
.var
) OR (i
.parMod
= Sym
.out
)) &
500 i
.type
.isScalarType();
503 (* ============================================================ *)
505 PROCEDURE cat2
*(i
,j
: L
.CharOpen
) : L
.CharOpen
;
507 L
.ResetCharOpenSeq(nmArray
);
508 L
.AppendCharOpen(nmArray
, i
);
509 L
.AppendCharOpen(nmArray
, j
);
510 RETURN L
.arrayCat(nmArray
);
513 PROCEDURE cat3
*(i
,j
,k
: L
.CharOpen
) : L
.CharOpen
;
515 L
.ResetCharOpenSeq(nmArray
);
516 L
.AppendCharOpen(nmArray
, i
);
517 L
.AppendCharOpen(nmArray
, j
);
518 L
.AppendCharOpen(nmArray
, k
);
519 RETURN L
.arrayCat(nmArray
);
522 (* ------------------------------------------------------------ *)
524 PROCEDURE MkBlkName
*(mod
: Id
.BlkId
);
525 VAR mNm
: L
.CharOpen
;
526 (* -------------------------------------------------- *)
527 PROCEDURE dotToSlash(arr
: L
.CharOpen
) : L
.CharOpen
;
530 FOR ix
:= 0 TO LEN(arr
)-1 DO
531 IF arr
[ix
] = "." THEN arr
[ix
] := "/" END;
535 (* -------------------------------------------------- *)
537 IF mod
.xName
# NIL THEN RETURN END;
538 mNm
:= Sym
.getName
.ChPtr(mod
);
539 IF mod
.scopeNm
# NIL THEN
540 mod
.scopeNm
:= dotToSlash(mod
.scopeNm
);
542 mod
.scopeNm
:= cat3(prfx
, slsh
, mNm
); (* "CP/<modname>" *)
544 IF ~Cst
.doCode (* Only doing Jasmin output *)
545 OR Cst
.doJsmn (* Forcing assembly via Jasmin *)
546 OR (mod
.scopeNm
[0] = 0X
) (* Explicitly forcing no package! *) THEN
548 ELSE (* default case *)
549 mod
.xName
:= cat3(mod
.scopeNm
, slsh
, mNm
);
553 (* ------------------------------------------------------------ *)
555 PROCEDURE scopeName(scp
: Sym
.Scope
) : L
.CharOpen
;
557 WITH scp
: Id
.BlkId
DO
558 IF scp
.xName
= NIL THEN MkBlkName(scp
) END;
559 IF Cst
.doCode
& ~Cst
.doJsmn
THEN
560 RETURN Sym
.getName
.ChPtr(scp
);
565 IF scp
.prcNm
= NIL THEN MkProcName(scp
) END;
570 (* ------------------------------------------------------------ *)
572 PROCEDURE qualScopeName(scp
: Sym
.Scope
) : L
.CharOpen
;
574 WITH scp
: Id
.BlkId
DO
575 IF scp
.xName
= NIL THEN MkBlkName(scp
) END;
578 IF scp
.prcNm
= NIL THEN MkProcName(scp
) END;
583 (* ------------------------------------------------------------ *)
584 PROCEDURE newMthId
*(IN name
: ARRAY OF CHAR; dfScp
: Id
.BlkId
; bndTp
: Sym
.Type
) : Id
.MthId
;
587 rslt
:= Id
.newMthId();
588 rslt
.SetKind(Id
.conMth
);
589 rslt
.hash
:= Hsh
.enterStr(name
);
591 rslt
.bndType
:= bndTp
;
592 rslt
.rcvFrm
:= Id
.newParId();
593 rslt
.rcvFrm
.type
:= bndTp
;
594 IF bndTp
IS Ty
.Record
THEN rslt
.rcvFrm
.parMod
:= Sym
.var
END;
598 (* ------------------------------------------------------------ *)
599 (* Generate all naming strings for this record type, and put *)
600 (* a corresponding emitter record on the work list. *)
601 (* ------------------------------------------------------------ *)
602 PROCEDURE MkRecName
*(typ
: Ty
.Record
);
603 VAR mNm
: L
.CharOpen
;
608 (* ###################################### *)
609 IF typ
.xName
# NIL THEN RETURN END;
610 (* ###################################### *)
611 IF typ
.bindTp
# NIL THEN (* Synthetically named rec'd *)
612 tId
:= typ
.bindTp
.idnt
;
613 ELSE (* Normal, named record type *)
614 IF typ
.idnt
= NIL THEN (* Anonymous record type *)
615 typ
.idnt
:= Id
.newAnonId(typ
.serial
);
619 IF tId
.dfScp
= NIL THEN tId
.dfScp
:= Cst
.thisMod
END;
620 rNm
:= Sym
.getName
.ChPtr(tId
);
621 mNm
:= scopeName(tId
.dfScp
);
622 qNm
:= qualScopeName(tId
.dfScp
);
625 * rNm holds the simple record name
626 * mNm holds the qualifying module name
627 * qNm holds the qualifying scope name
628 * If extrnNm = NIL, the default mangling is used.
630 * xName to hold the fully qualified name
631 * extrnNm to hold the simple name
632 * scopeNm to hold the "L<qualid>;" name
634 IF typ
.extrnNm
# NIL THEN
637 typ
.extrnNm
:= cat3(mNm
, lowL
, rNm
);
640 typ
.xName
:= cat3(qNm
, slsh
, typ
.extrnNm
);
642 typ
.xName
:= typ
.extrnNm
;
644 typ
.scopeNm
:= cat3(lCap
, typ
.xName
, semi
);
646 * It is at this point that we link records into the
647 * class-emission worklist.
649 IF tId
.dfScp
.kind
# Id
.impId
THEN
650 JavaBase
.worklist
.AddNewRecEmitter(typ
);
654 (* ============================================================ *)
655 (* Some Procedure Variable utilities *)
656 (* ============================================================ *)
658 PROCEDURE getProcWrapperInvoke
*(typ
: Ty
.Record
) : Id
.MthId
;
661 (* We could get the method descriptor more cheaply by
662 * indexing into the symbol table, but this would be
663 * very fragile against future code changes.
665 idnt
:= typ
.symTb
.lookup(invokeHash
);
666 RETURN idnt(Id
.MthId
);
667 END getProcWrapperInvoke
;
669 PROCEDURE getProcVarInvoke
*(typ
: Ty
.Procedure
) : Id
.MthId
;
671 IF (typ
= NIL) OR (typ
.hostClass
= NIL) THEN RETURN NIL;
672 ELSE RETURN getProcWrapperInvoke(typ
.hostClass
);
674 END getProcVarInvoke
;
676 (* ------------------------------------------------------------ *)
679 * Copy the formals from the template procedure type descriptor
680 * to the type descriptor for the method 'scp'. Change the
681 * dfScp of the params (and receiver) to be local to scp.
682 * Also, in the case of methods imported without parameter
683 * names, generate synthetic names for the formals.
685 PROCEDURE RescopeFormals(template
: Ty
.Procedure
; scp
: Id
.MthId
);
686 VAR param
: Id
.ParId
;
689 newTyp
: Ty
.Procedure
;
691 newTyp
:= scp
.type(Ty
.Procedure
);
692 newTyp
.retType
:= template
.retType
;
693 FOR index
:= 0 TO template
.formals
.tide
-1 DO
694 param
:= Id
.cloneParInScope(template
.formals
.a
[index
], scp
);
695 IF param
.hash
= 0 THEN
696 synthH
:= Hsh
.enterStr("p" + L
.intToCharOpen(index
)^
);
697 template
.formals
.a
[index
].hash
:= synthH
;
698 param
.hash
:= synthH
;
700 IF ~Sym
.refused(param
, scp
) THEN
701 Id
.AppendParam(newTyp
.formals
, param
);
702 Sym
.AppendIdnt(scp
.locals
, param
);
707 (* ------------------------------------------------------------ *)
708 (* Generate all naming strings for this procedure type, and *)
709 (* put a corresponding emitter record on the work list. *)
710 (* ------------------------------------------------------------ *)
711 PROCEDURE MkProcTypeName
*(typ
: Ty
.Procedure
);
712 VAR tIdent
: Sym
.Idnt
;
714 (*invoke : Id.MthId;*)
715 rNm
, mNm
, qNm
: L
.CharOpen
;
717 (* ###################################### *)
718 IF typ
.xName
# NIL THEN RETURN END;
719 (* ###################################### *)
720 IF typ
.idnt
= NIL THEN (* Anonymous procedure type *)
721 typ
.idnt
:= Id
.newAnonId(typ
.serial
);
722 typ
.idnt
.type
:= typ
;
725 IF tIdent
.dfScp
= NIL THEN tIdent
.dfScp
:= Cst
.thisMod
END;
727 rNm
:= Sym
.getName
.ChPtr(tIdent
);
728 mNm
:= scopeName(tIdent
.dfScp
);
729 qNm
:= qualScopeName(tIdent
.dfScp
);
732 * rNm holds the simple record name
733 * mNm holds the qualifying module name
734 * qNm holds the qualifying scope name
736 * xName to hold the fully qualified name
738 hostTp
.extrnNm
:= cat3(mNm
, lowL
, rNm
);
739 hostTp
.xName
:= cat3(qNm
, slsh
, hostTp
.extrnNm
);
740 hostTp
.scopeNm
:= cat3(lCap
, hostTp
.xName
, semi
);
741 typ
.hostClass
:= hostTp
;
742 Blt
.MkDummyMethodAndInsert("Invoke", Ty
.newPrcTp(), hostTp
, Cst
.thisMod
, Sym
.pubMode
, Sym
.var
, Id
.isAbs
);
743 RescopeFormals(typ
, getProcVarInvoke(typ
));
744 typ
.xName
:= hostTp
.xName
;
746 * It is at this point that we link records into the
747 * class-emission worklist.
749 IF tIdent
.dfScp
.kind
# Id
.impId
THEN
750 JavaBase
.worklist
.AddNewProcTypeEmitter(typ
);
754 (* ------------------------------------------------------------ *)
755 (* Generate the body statement sequence for the proc-type *)
756 (* wrapper class to invoke the encapsulated procedure literal. *)
757 (* ------------------------------------------------------------ *)
758 PROCEDURE procLitBodyStatement(targetId
: Sym
.Idnt
; thisMth
: Id
.MthId
) : Sym
.Stmt
;
759 VAR text
: L
.CharOpenSeq
;
760 mthTp
: Ty
.Procedure
;
763 (* ###################################### *)
764 PROCEDURE textName(trgt
: Sym
.Idnt
) : L
.CharOpen
;
765 VAR simple
: L
.CharOpen
;
767 simple
:= trgt
.name();
768 IF trgt
.dfScp
= Cst
.thisMod
THEN
771 RETURN BOX(trgt
.dfScp
.name()^
+ '
.'
+ simple^
);
774 (* ###################################### *)
776 mthTp
:= thisMth
.type(Ty
.Procedure
);
777 IF mthTp
.retType
# NIL THEN L
.AppendCharOpen(text
, BOX("RETURN ")) END;
778 L
.AppendCharOpen(text
, textName(targetId
));
779 L
.AppendCharOpen(text
, lPar
);
780 FOR index
:= 0 TO mthTp
.formals
.tide
- 1 DO
781 IF index
# 0 THEN L
.AppendCharOpen(text
, comma
) END;
782 param
:= mthTp
.formals
.a
[index
];
783 L
.AppendCharOpen(text
, param
.name());
785 L
.AppendCharOpen(text
, rPar
);
786 L
.AppendCharOpen(text
, BOX("END"));
787 RETURN Psr
.parseTextAsStatement(text
.a
, thisMth
);
788 END procLitBodyStatement
;
790 (* ------------------------------------------------------------ *)
791 (* Every value of procedure type is represented by a singleton *)
792 (* class derived from the abstract host type of the proc-type. *)
793 (* ------------------------------------------------------------ *)
794 PROCEDURE newProcLitWrapperClass(exp
: Sym
.Expr
; typ
: Ty
.Procedure
) : Ty
.Record
;
795 VAR singleton
: Id
.TypId
;
796 hostClass
: Ty
.Record
;
797 newInvoke
: Id
.MthId
;
799 ASSERT(exp
IS Xp
.IdLeaf
);
800 Blt
.MkDummyClass(newAnonLit(), Cst
.thisMod
, Ty
.noAtt
, singleton
);
801 hostClass
:= singleton
.type
.boundRecTp()(Ty
.Record
);
802 Blt
.MkDummyMethodAndInsert("Invoke", Ty
.newPrcTp(), hostClass
, Cst
.thisMod
, Sym
.pubMode
, Sym
.var
, {});
803 MkRecName(hostClass
); (* Add this class to the emission work-list *)
804 newInvoke
:= getProcWrapperInvoke(hostClass
);
805 RescopeFormals(typ
, newInvoke
);
806 newInvoke
.body
:= procLitBodyStatement(exp(Xp
.IdLeaf
).ident
, newInvoke
);
808 END newProcLitWrapperClass
;
810 (* ------------------------------------------------------------ *)
811 (* ------------------------------------------------------------ *)
813 PROCEDURE MkVecName
*(typ
: Ty
.Vector
);
817 ord
:= mapVecElTp(typ
.elemTp
);
818 rTp
:= vecRecTyp(ord
);
819 IF rTp
.xName
= NIL THEN MkRecName(rTp
) END;
820 typ
.xName
:= rTp
.scopeNm
;
823 (* ------------------------------------------------------------ *)
825 PROCEDURE MkProcName
*(proc
: Id
.Procs
);
826 VAR pNm
: L
.CharOpen
;
830 (* -------------------------------------------------- *)
831 PROCEDURE clsNmFromRec(typ
: Sym
.Type
) : L
.CharOpen
;
833 IF Cst
.doCode
& ~Cst
.doJsmn
THEN
834 RETURN typ(Ty
.Record
).xName
;
836 RETURN typ(Ty
.Record
).extrnNm
;
839 (* -------------------------------------------------- *)
840 PROCEDURE className(p
: Id
.Procs
) : L
.CharOpen
;
842 WITH p
: Id
.PrcId
DO RETURN p
.clsNm
;
843 | p
: Id
.MthId
DO RETURN clsNmFromRec(p
.bndType
);
846 (* -------------------------------------------------- *)
847 PROCEDURE GetClassName(pr
: Id
.PrcId
; bl
: Id
.BlkId
);
850 nm
:= Sym
.getName
.ChPtr(pr
);
851 IF pr
.bndType
= NIL THEN (* normal case *)
852 pr
.clsNm
:= bl
.xName
;
853 IF pr
.prcNm
= NIL THEN pr
.prcNm
:= nm
END;
854 ELSE (* static method *)
855 IF pr
.bndType
.xName
= NIL THEN MkRecName(pr
.bndType(Ty
.Record
)) END;
856 pr
.clsNm
:= clsNmFromRec(pr
.bndType
);
857 IF pr
.prcNm
= NIL THEN
859 ELSIF pr
.prcNm^
= initStr
THEN
860 pr
.SetKind(Id
.ctorP
);
864 (* -------------------------------------------------- *)
865 PROCEDURE MkPrcNm(prc
: Id
.PrcId
);
871 IF prc
.scopeNm
# NIL THEN RETURN;
872 ELSIF prc
.kind
= Id
.fwdPrc
THEN
873 res
:= prc
.resolve(Id
.PrcId
); MkPrcNm(res
);
874 prc
.prcNm
:= res
.prcNm
;
875 prc
.clsNm
:= res
.clsNm
;
876 prc
.scopeNm
:= res
.scopeNm
;
877 ELSIF prc
.kind
= Id
.conPrc
THEN
879 WITH scp
: Id
.BlkId
DO
880 IF scp
.xName
= NIL THEN MkBlkName(scp
) END;
881 IF Sym
.isFn
IN scp
.xAttr
THEN
882 GetClassName(prc
, scp
);
884 prc
.clsNm
:= scp
.xName
;
885 IF prc
.prcNm
= NIL THEN prc
.prcNm
:= Sym
.getName
.ChPtr(prc
) END;
889 prc
.clsNm
:= className(scp
);
890 prc
.prcNm
:= cat3(Sym
.getName
.ChPtr(prc
), dlar
, scp
.prcNm
);
892 prc
.scopeNm
:= scp
.scopeNm
;
893 ELSE (* prc.kind = Id.ctorP *)
894 blk
:= prc
.dfScp(Id
.BlkId
);
895 rTp
:= prc
.type
.returnType().boundRecTp()(Ty
.Record
);
896 IF blk
.xName
= NIL THEN MkBlkName(blk
) END;
897 IF rTp
.xName
= NIL THEN MkRecName(rTp
) END;
898 prc
.clsNm
:= clsNmFromRec(rTp
);
899 prc
.prcNm
:= L
.strToCharOpen(initStr
);
900 prc
.scopeNm
:= blk
.scopeNm
;
903 (* -------------------------------------------------- *)
904 PROCEDURE MkMthNm(mth
: Id
.MthId
);
909 IF mth
.scopeNm
# NIL THEN RETURN;
910 ELSIF mth
.kind
= Id
.fwdMth
THEN
911 res
:= mth
.resolve(Id
.MthId
); MkMthNm(res
);
912 mth
.prcNm
:= res
.prcNm
; mth
.scopeNm
:= res
.scopeNm
;
914 scp
:= mth
.dfScp(Id
.BlkId
);
916 IF typ
.xName
= NIL THEN MkRecName(typ(Ty
.Record
)) END;
917 IF scp
.xName
= NIL THEN MkBlkName(scp
) END;
919 mth
.scopeNm
:= scp
.scopeNm
;
920 IF mth
.prcNm
= NIL THEN mth
.prcNm
:= Sym
.getName
.ChPtr(mth
) END;
923 (* -------------------------------------------------- *)
924 BEGIN (* MkProcName *)
925 WITH proc
: Id
.MthId
DO MkMthNm(proc
);
926 | proc
: Id
.PrcId
DO MkPrcNm(proc
);
930 (* ------------------------------------------------------------ *)
932 PROCEDURE MkAliasName
*(typ
: Ty
.Opaque
);
933 VAR mNm
: L
.CharOpen
;
938 * This was almost certainly broken,
939 * at least for foreign explicit names
941 IF typ
.xName
# NIL THEN RETURN END;
942 rNm
:= Sym
.getName
.ChPtr(typ
.idnt
);
945 * mNm := scopeName(typ.idnt.dfScp);
946 * sNm := cat3(mNm, lowL, rNm);
947 * typ.xName := cat3(qualScopeName(typ.idnt.dfScp), slsh, sNm);
951 typ
.xName
:= cat3(qualScopeName(typ
.idnt
.dfScp
), slsh
, rNm
);
953 typ
.scopeNm
:= cat3(lCap
, typ
.xName
, semi
);
956 (* ------------------------------------------------------------ *)
958 PROCEDURE MkVarName
*(var
: Id
.VarId
);
961 IF var
.varNm
# NIL THEN RETURN END;
962 mod
:= var
.dfScp(Id
.BlkId
);
963 var
.varNm
:= Sym
.getName
.ChPtr(var
);
964 IF var
.recTyp
= NIL THEN (* normal case *)
965 var
.clsNm
:= mod
.xName
;
966 ELSE (* static field *)
967 IF var
.recTyp
.xName
= NIL THEN MkRecName(var
.recTyp(Ty
.Record
)) END;
968 var
.clsNm
:= var
.recTyp(Ty
.Record
).extrnNm
;
972 (* ------------------------------------------------------------ *)
974 PROCEDURE NumberParams(pIdn
: Id
.Procs
; pTyp
: Ty
.Procedure
);
975 VAR parId
: Id
.ParId
;
979 (* ----------------------------------------- *)
980 PROCEDURE AppendTypeName(VAR lst
: L
.CharOpenSeq
; typ
: Sym
.Type
);
982 WITH typ
: Ty
.Base
DO
983 L
.AppendCharOpen(lst
, typ
.xName
);
985 IF typ
.xName
= NIL THEN MkVecName(typ
) END;
986 L
.AppendCharOpen(lst
, typ
.xName
);
988 L
.AppendCharOpen(lst
, brac
);
989 AppendTypeName(lst
, typ
.elemTp
);
991 IF typ
.xName
= NIL THEN MkRecName(typ
) END;
992 L
.AppendCharOpen(lst
, typ
.scopeNm
);
994 AppendTypeName(lst
, Blt
.intTp
);
995 | typ
: Ty
.Pointer
DO
996 AppendTypeName(lst
, typ
.boundTp
);
998 IF typ
.xName
= NIL THEN MkAliasName(typ
) END;
999 L
.AppendCharOpen(lst
, typ
.scopeNm
);
1000 | typ
: Ty
.Procedure
DO
1001 IF typ
.xName
= NIL THEN MkProcTypeName(typ
) END;
1002 L
.AppendCharOpen(lst
, typ
.hostClass
.scopeNm
);
1005 (* ----------------------------------------- *)
1008 * The parameter numbering scheme tries to use the return
1009 * value for the first OUT or VAR parameter. The variable
1010 * 'hasRt' notes whether this possiblity has been used up. If
1011 * this is a value returning function hasRt is true at entry.
1013 count
:= pIdn
.rtsFram
;
1014 retTp
:= pTyp
.retType
;
1015 IF pIdn
.kind
= Id
.ctorP
THEN
1017 ELSIF retTp
# NIL THEN (* and not a constructor... *)
1018 pTyp
.retN
:= jvmSize(pTyp
.retType
);
1020 L
.ResetCharOpenSeq(fmArray
);
1021 L
.AppendCharOpen(fmArray
, lPar
);
1022 IF pIdn
.lxDepth
> 0 THEN
1023 L
.AppendCharOpen(fmArray
, xhrMk
); INC(count
);
1025 FOR index
:= 0 TO pTyp
.formals
.tide
-1 DO
1026 parId
:= pTyp
.formals
.a
[index
];
1027 IF needsBox(parId
) THEN
1028 IF parId
.parMod
= Sym
.var
THEN (* pass value as well *)
1029 parId
.varOrd
:= count
;
1030 INC(count
, jvmSize(parId
.type
));
1031 AppendTypeName(fmArray
, parId
.type
);
1035 * Return slot is not already used, use it now.
1037 parId
.boxOrd
:= retMarker
;
1038 pTyp
.retN
:= jvmSize(parId
.type
);
1039 retTp
:= parId
.type
;
1042 * Return slot is already used, use a boxed variable.
1044 parId
.boxOrd
:= count
;
1046 L
.AppendCharOpen(fmArray
, brac
);
1047 AppendTypeName(fmArray
, parId
.type
);
1049 ELSE (* could be two slots ... *)
1050 parId
.varOrd
:= count
;
1051 INC(count
, jvmSize(parId
.type
));
1052 AppendTypeName(fmArray
, parId
.type
);
1055 L
.AppendCharOpen(fmArray
, rPar
);
1056 IF (retTp
= NIL) OR (pIdn
.kind
= Id
.ctorP
) THEN
1057 L
.AppendCharOpen(fmArray
, void
);
1058 ELSIF (pIdn
IS Id
.MthId
) & (Id
.covar
IN pIdn(Id
.MthId
).mthAtt
) THEN
1060 * This is a method with a covariant return type. We must
1061 * erase the declared type, substituting the non-covariant
1062 * upper-bound. Calls will cast the result to the real type.
1064 AppendTypeName(fmArray
, pIdn
.retTypBound());
1066 AppendTypeName(fmArray
, retTp
);
1068 pTyp
.xName
:= L
.arrayCat(fmArray
);
1070 * We must now set the argsize and retsize.
1071 * The current info.lNum (before the locals
1072 * have been added) is the argsize.
1075 pIdn
.rtsFram
:= count
;
1078 (* ------------------------------------------------------------ *)
1079 (* Proxies are the local variables corresponding to boxed *)
1080 (* arguments that are not also passed by value i.e. OUT mode. *)
1081 (* ------------------------------------------------------------ *)
1082 PROCEDURE NumberProxies(pIdn
: Id
.Procs
; IN pars
: Id
.ParSeq
);
1083 VAR parId
: Id
.ParId
;
1086 (* ------------------ *
1087 * Allocate an activation record slot for the XHR,
1088 * if this is needed. The XHR reference will be local
1089 * number pIdn.type.argN.
1090 * ------------------ *)
1091 IF Id
.hasXHR
IN pIdn
.pAttr
THEN MkXHR(pIdn
); INC(pIdn
.rtsFram
) END;
1092 FOR index
:= 0 TO pars
.tide
-1 DO
1093 parId
:= pars
.a
[index
];
1094 IF parId
.parMod
# Sym
.var
THEN
1095 IF needsBox(parId
) THEN
1096 parId
.varOrd
:= pIdn
.rtsFram
;
1097 INC(pIdn
.rtsFram
, jvmSize(parId
.type
));
1103 (* ------------------------------------------------------------ *)
1105 PROCEDURE NumberLocals(pIdn
: Id
.Procs
; IN locs
: Sym
.IdSeq
);
1106 VAR ident
: Sym
.Idnt
;
1110 count
:= pIdn
.rtsFram
;
1111 FOR index
:= 0 TO locs
.tide
-1 DO
1112 ident
:= locs
.a
[index
];
1113 WITH ident
: Id
.ParId
DO (* skip *)
1114 | ident
: Id
.LocId
DO
1115 ident
.varOrd
:= count
;
1116 INC(count
, jvmSize(ident
.type
));
1119 pIdn
.rtsFram
:= count
;
1122 (* ------------------------------------------------------------ *)
1124 PROCEDURE MkCallAttr
*(pIdn
: Sym
.Idnt
; pTyp
: Ty
.Procedure
);
1126 WITH pIdn
: Id
.MthId
DO
1127 IF ~
needsBox(pIdn
.rcvFrm
) THEN
1128 pIdn
.rtsFram
:= 1; (* count one for "this" *)
1130 pIdn
.rtsFram
:= 2; (* this plus the retbox *)
1133 NumberParams(pIdn
, pTyp
);
1134 | pIdn
: Id
.PrcId
DO
1137 NumberParams(pIdn
, pTyp
);
1141 (* ------------------------------------------------------------ *)
1143 PROCEDURE RenumberLocals
*(prcId
: Id
.Procs
);
1144 VAR parId
: Id
.ParId
;
1145 frmTp
: Ty
.Procedure
;
1150 * (i) The receiver (if any) must be #0
1151 * (ii) Params are #1 .. #N, or #0 .. for statics
1152 * (iii) Locals are #(N+1) ...
1153 * (iv) doubles and longs take two slots.
1155 * This procedure computes the number of local slots. It
1156 * renumbers the varOrd fields, and initializes rtsFram.
1157 * The procedure also computes the formal name for the JVM.
1160 frmTp
:= prcId
.type(Ty
.Procedure
);
1161 funcT
:= (frmTp
.retType
# NIL);
1162 WITH prcId
: Id
.MthId
DO
1163 parId
:= prcId
.rcvFrm
;
1164 parId
.varOrd
:= 0; prcId
.rtsFram
:= 1; (* count one for "this" *)
1165 ASSERT(~
needsBox(parId
));
1167 * Receivers are never boxed in Component Pascal
1169 * IF needsBox(parId) THEN
1170 * parId.boxOrd := 1; prcId.rtsFram := 2; (* count one for retbox *)
1173 ELSE (* skip static procedures *)
1176 * Assert: params do not appear in the local array.
1177 * Count params (and boxes if needed).
1179 NumberParams(prcId
, frmTp
);
1180 IF prcId
.body
# NIL THEN
1181 NumberProxies(prcId
, frmTp
.formals
);
1182 NumberLocals(prcId
, prcId
.locals
);
1186 (* ------------------------------------------------------------ *)
1187 (* ------------------------------------------------------------ *)
1189 PROCEDURE (jf
: JavaFile
)MakeAndPushProcLitValue
*(exp
: Sym
.Expr
; typ
: Ty
.Procedure
),NEW;
1190 VAR singleton
: Id
.TypId
;
1191 hostClass
: Ty
.Record
;
1193 MkProcTypeName(typ
);
1194 hostClass
:= newProcLitWrapperClass(exp
, typ
);
1195 hostClass
.baseTp
:= typ
.hostClass
;
1196 jf
.MkNewRecord(hostClass
);
1197 END MakeAndPushProcLitValue
;
1199 (* ------------------------------------------------------------ *)
1201 PROCEDURE (jf
: JavaFile
)LoadLocal
*(ord
: INTEGER; typ
: Sym
.Type
),NEW;
1204 IF (typ
# NIL) & (typ
IS Ty
.Base
) THEN
1205 code
:= typeLoad
[typ(Ty
.Base
).tpOrd
];
1207 code
:= Jvm
.opc_aload
;
1211 | Jvm
.opc_iload
: code
:= Jvm
.opc_iload_0
+ ord
;
1212 | Jvm
.opc_lload
: code
:= Jvm
.opc_lload_0
+ ord
;
1213 | Jvm
.opc_fload
: code
:= Jvm
.opc_fload_0
+ ord
;
1214 | Jvm
.opc_dload
: code
:= Jvm
.opc_dload_0
+ ord
;
1215 | Jvm
.opc_aload
: code
:= Jvm
.opc_aload_0
+ ord
;
1219 jf
.CodeI(code
, ord
);
1223 (* ---------------------------------------------------- *)
1225 PROCEDURE (jf
: JavaFile
)GetLocal
*(var
: Id
.LocId
),NEW;
1227 IF Id
.uplevA
IN var
.locAtt
THEN jf
.GetUplevel(var
);
1228 ELSE jf
.LoadLocal(var
.varOrd
, var
.type
);
1232 (* ---------------------------------------------------- *)
1234 PROCEDURE typeToChOpen(typ
: Sym
.Type
) : L
.CharOpen
;
1235 (* --------------------------------------------- *)
1236 PROCEDURE slashToDot(a
: L
.CharOpen
) : L
.CharOpen
;
1237 VAR nw
: L
.CharOpen
; ix
: INTEGER; ch
: CHAR;
1240 FOR ix
:= 0 TO LEN(a
)-1 DO
1241 ch
:= a
[ix
]; IF ch
= "/" THEN nw
[ix
] := "." ELSE nw
[ix
] := ch
END;
1245 (* --------------------------------------------- *)
1246 PROCEDURE typeTag(typ
: Sym
.Type
) : L
.CharOpen
;
1248 WITH typ
: Ty
.Base
DO
1251 RETURN cat2(brac
, typeTag(typ
.elemTp
));
1252 | typ
: Ty
.Record
DO
1253 IF typ
.xName
= NIL THEN MkRecName(typ
) END;
1254 RETURN slashToDot(typ
.scopeNm
);
1256 RETURN Blt
.intTp
.xName
;
1257 | typ
: Ty
.Pointer
DO
1258 RETURN typeTag(typ
.boundTp
);
1259 | typ
: Ty
.Opaque
DO
1260 IF typ
.xName
= NIL THEN MkAliasName(typ
) END;
1261 RETURN slashToDot(typ
.scopeNm
);
1264 (* --------------------------------------------- *)
1266 WITH typ
: Ty
.Base
DO
1267 RETURN typeTag(typ
);
1269 RETURN cat2(brac
, typeTag(typ
.elemTp
));
1270 | typ
: Ty
.Record
DO
1271 IF typ
.xName
= NIL THEN MkRecName(typ
) END;
1272 RETURN slashToDot(typ
.xName
);
1273 | typ
: Ty
.Pointer
DO
1274 RETURN typeToChOpen(typ
.boundTp
);
1275 | typ
: Ty
.Opaque
DO
1276 IF typ
.xName
= NIL THEN MkAliasName(typ
) END;
1277 RETURN slashToDot(typ
.xName
);
1281 (* ---------------------------------------------------- *)
1283 PROCEDURE (jf
: JavaFile
)LoadType
*(id
: Sym
.Idnt
),NEW;
1286 ASSERT(id
IS Id
.TypId
);
1288 WITH tp
: Ty
.Base
DO
1289 jf
.PushInt(tp
.tpOrd
);
1290 jf
.CallRTS(LoadTp1
, 1, 1);
1293 * First we get the string-name of the
1294 * type, and then we push the string.
1296 jf
.PushStr(typeToChOpen(id
.type
));
1298 * Then we call getClassByName
1300 jf
.CallRTS(LoadTp2
, 1, 1);
1304 (* ---------------------------------------------------- *)
1306 PROCEDURE (jf
: JavaFile
)GetVar
*(id
: Sym
.Idnt
),NEW;
1310 var
:= id(Id
.AbVar
);
1311 IF var
.kind
= Id
.conId
THEN
1312 jf
.GetLocal(var(Id
.LocId
));
1315 WITH scp
: Id
.BlkId
DO
1316 jf
.PutGetS(Jvm
.opc_getstatic
, scp
, var(Id
.VarId
));
1317 ELSE (* must be local *)
1318 jf
.GetLocal(var(Id
.LocId
));
1323 (* ------------------------------------------------------------ *)
1325 PROCEDURE (jf
: JavaFile
)StoreLocal
*(ord
: INTEGER; typ
: Sym
.Type
),NEW;
1328 IF (typ
# NIL) & (typ
IS Ty
.Base
) THEN
1329 code
:= typeStore
[typ(Ty
.Base
).tpOrd
];
1331 code
:= Jvm
.opc_astore
;
1335 | Jvm
.opc_istore
: code
:= Jvm
.opc_istore_0
+ ord
;
1336 | Jvm
.opc_lstore
: code
:= Jvm
.opc_lstore_0
+ ord
;
1337 | Jvm
.opc_fstore
: code
:= Jvm
.opc_fstore_0
+ ord
;
1338 | Jvm
.opc_dstore
: code
:= Jvm
.opc_dstore_0
+ ord
;
1339 | Jvm
.opc_astore
: code
:= Jvm
.opc_astore_0
+ ord
;
1343 jf
.CodeI(code
, ord
);
1347 (* ---------------------------------------------------- *)
1349 PROCEDURE (jf
: JavaFile
)PutLocal
*(var
: Id
.LocId
),NEW;
1351 IF Id
.uplevA
IN var
.locAtt
THEN jf
.PutUplevel(var
);
1352 ELSE jf
.StoreLocal(var
.varOrd
, var
.type
);
1356 (* ---------------------------------------------------- *)
1358 PROCEDURE (jf
: JavaFile
)PutVar
*(id
: Sym
.Idnt
),NEW;
1362 var
:= id(Id
.AbVar
);
1364 WITH scp
: Id
.BlkId
DO
1365 jf
.PutGetS(Jvm
.opc_putstatic
, scp
, var(Id
.VarId
));
1366 ELSE (* could be in an XHR *)
1367 jf
.PutLocal(var(Id
.LocId
));
1371 (* ------------------------------------------------------------ *)
1373 PROCEDURE (jf
: JavaFile
)PutElement
*(typ
: Sym
.Type
),NEW;
1376 IF (typ
# NIL) & (typ
IS Ty
.Base
) THEN
1377 code
:= typePutE
[typ(Ty
.Base
).tpOrd
];
1379 code
:= Jvm
.opc_aastore
;
1384 (* ------------------------------------------------------------ *)
1386 PROCEDURE (jf
: JavaFile
)GetElement
*(typ
: Sym
.Type
),NEW;
1389 IF (typ
# NIL) & (typ
IS Ty
.Base
) THEN
1390 code
:= typeGetE
[typ(Ty
.Base
).tpOrd
];
1392 code
:= Jvm
.opc_aaload
;
1397 (* ------------------------------------------------------------ *)
1399 PROCEDURE (jf
: JavaFile
)PushInt
*(num
: INTEGER),NEW;
1403 IF (num
>= MIN(BYTE)) & (num
<= MAX(BYTE)) THEN
1405 |
-1 : jf
.Code(Jvm
.opc_iconst_m1
);
1406 |
0 : jf
.Code(Jvm
.opc_iconst_0
);
1407 |
1 : jf
.Code(Jvm
.opc_iconst_1
);
1408 |
2 : jf
.Code(Jvm
.opc_iconst_2
);
1409 |
3 : jf
.Code(Jvm
.opc_iconst_3
);
1410 |
4 : jf
.Code(Jvm
.opc_iconst_4
);
1411 |
5 : jf
.Code(Jvm
.opc_iconst_5
);
1413 jf
.CodeI(Jvm
.opc_bipush
, num
);
1420 (* ------------------------------------------------------------ *)
1422 PROCEDURE (jf
: JavaFile
)PushLong
*(num
: LONGINT),NEW;
1425 jf
.Code(Jvm
.opc_lconst_0
);
1427 jf
.Code(Jvm
.opc_lconst_1
);
1428 ELSIF (num
>= MIN(INTEGER)) & (num
<= MAX(INTEGER)) THEN
1429 jf
.PushInt(SHORT(num
));
1430 jf
.Code(Jvm
.opc_i2l
);
1432 jf
.CodeL(Jvm
.opc_ldc2_w
, num
);
1436 (* ------------------------------------------------------------ *)
1438 PROCEDURE (jf
: JavaFile
)PushReal
*(num
: REAL),NEW;
1441 jf
.Code(Jvm
.opc_dconst_0
);
1442 ELSIF num
= 1.0 THEN
1443 jf
.Code(Jvm
.opc_dconst_1
);
1445 jf
.CodeR(Jvm
.opc_ldc2_w
, num
, FALSE
);
1449 (* ------------------------------------------------------------ *)
1451 PROCEDURE (jf
: JavaFile
)PushSReal
*(num
: REAL),NEW;
1456 jf
.Code(Jvm
.opc_fconst_0
);
1457 ELSIF num
= 1.0 THEN
1458 jf
.Code(Jvm
.opc_fconst_1
);
1459 ELSIF num
= 2.0 THEN
1460 jf
.Code(Jvm
.opc_fconst_2
);
1462 jf
.CodeR(Jvm
.opc_ldc
, num
, TRUE
);
1466 (* ------------------------------------------------------------ *)
1468 PROCEDURE (jf
: JavaFile
)PushStaticLink
*(tgt
: Id
.Procs
),NEW;
1469 VAR lxDel
: INTEGER;
1474 lxDel
:= tgt
.lxDepth
- clr
.lxDepth
;
1475 pTp
:= clr
.type(Ty
.Procedure
);
1478 |
0 : jf
.Code(Jvm
.opc_aload_0
);
1479 |
1 : IF Id
.hasXHR
IN clr
.pAttr
THEN
1480 jf
.LoadLocal(pTp
.argN
, NIL);
1481 ELSIF clr
.lxDepth
= 0 THEN
1482 jf
.Code(Jvm
.opc_aconst_null
);
1484 jf
.Code(Jvm
.opc_aload_0
);
1487 jf
.Code(Jvm
.opc_aload_0
);
1489 clr
:= clr
.dfScp(Id
.Procs
);
1490 IF Id
.hasXHR
IN clr
.pAttr
THEN
1491 jf
.PutGetF(Jvm
.opc_getfield
,
1492 Cst
.rtsXHR
.boundRecTp()(Ty
.Record
), Cst
.xhrId
);
1494 UNTIL clr
.lxDepth
= tgt
.lxDepth
;
1498 (* ------------------------------------------------------------ *)
1500 PROCEDURE (jf
: JavaFile
)GetXHR(var
: Id
.LocId
),NEW;
1501 VAR scp
: Id
.Procs
; (* the scope holding the datum *)
1502 clr
: Id
.Procs
; (* the scope making the call *)
1506 scp
:= var
.dfScp(Id
.Procs
);
1508 pTp
:= clr
.type(Ty
.Procedure
);
1510 * Check if this is an own local
1513 jf
.LoadLocal(pTp
.argN
, NIL);
1515 del
:= xhrCount(scp
, clr
);
1517 * First, load the static link
1519 jf
.Code(Jvm
.opc_aload_0
);
1521 * Next, load the XHR pointer.
1524 jf
.PutGetF(Jvm
.opc_getfield
,
1525 Cst
.rtsXHR
.boundRecTp()(Ty
.Record
), Cst
.xhrId
);
1529 * Finally, cast to concrete type
1531 jf
.CodeT(Jvm
.opc_checkcast
, scp
.xhrType
);
1535 (* ------------------------------------------------------------ *)
1537 PROCEDURE (jf
: JavaFile
)PutGetX
*(cde
: INTEGER; var
: Id
.LocId
),NEW;
1538 VAR pTyp
: Sym
.Type
;
1540 pTyp
:= var
.dfScp(Id
.Procs
).xhrType
;
1541 jf
.PutGetF(cde
, pTyp
.boundRecTp()(Ty
.Record
), var
);
1544 (* ------------------------------------------------------------ *)
1546 PROCEDURE (jf
: JavaFile
)XhrHandle
*(var
: Id
.LocId
),NEW;
1551 (* ------------------------------------------------------------ *)
1553 PROCEDURE (jf
: JavaFile
)GetUplevel
*(var
: Id
.LocId
),NEW;
1556 jf
.PutGetX(Jvm
.opc_getfield
, var
);
1559 (* ------------------------------------------------------------ *)
1561 PROCEDURE (jf
: JavaFile
)PutUplevel
*(var
: Id
.LocId
),NEW;
1563 jf
.PutGetX(Jvm
.opc_putfield
, var
);
1566 (* ------------------------------------------------------------ *)
1568 PROCEDURE (jf
: JavaFile
)ConvertUp
*(inT
, outT
: Sym
.Type
),NEW;
1569 (* Conversion "up" is always safe at runtime. Many are nop. *)
1570 VAR inB
, outB
, code
: INTEGER;
1572 inB
:= inT(Ty
.Base
).tpOrd
;
1573 outB
:= outT(Ty
.Base
).tpOrd
;
1574 IF inB
= outB
THEN RETURN END; (* PREMATURE RETURN! *)
1577 IF inB
= Ty
.sReaN
THEN code
:= Jvm
.opc_f2d
;
1578 ELSIF inB
= Ty
.lIntN
THEN code
:= Jvm
.opc_l2d
;
1579 ELSE code
:= Jvm
.opc_i2d
;
1582 IF inB
= Ty
.lIntN
THEN code
:= Jvm
.opc_l2f
;
1583 ELSE code
:= Jvm
.opc_i2f
;
1586 code
:= Jvm
.opc_i2l
;
1587 ELSE RETURN; (* PREMATURE RETURN! *)
1592 (* ------------------------------------------------------------ *)
1594 PROCEDURE (jf
: JavaFile
)ConvertDn
*(inT
, outT
: Sym
.Type
),NEW;
1595 (* Conversion "down" often needs a runtime check. *)
1596 VAR inB
, outB
, code
: INTEGER;
1598 inB
:= inT(Ty
.Base
).tpOrd
;
1599 outB
:= outT(Ty
.Base
).tpOrd
;
1600 IF inB
= outB
THEN RETURN END; (* PREMATURE RETURN! *)
1602 | Ty
.realN
: RETURN; (* PREMATURE RETURN! *)
1604 code
:= Jvm
.opc_d2f
;
1606 IF inB
= Ty
.realN
THEN code
:= Jvm
.opc_d2l
;
1607 ELSIF inB
= Ty
.sReaN
THEN code
:= Jvm
.opc_f2l
;
1608 ELSE RETURN; (* PREMATURE RETURN! *)
1611 IF inB
= Ty
.realN
THEN code
:= Jvm
.opc_d2i
;
1612 ELSIF inB
= Ty
.sReaN
THEN code
:= Jvm
.opc_f2i
;
1613 ELSIF inB
= Ty
.lIntN
THEN
1614 (* jf.RangeCheck(...); STILL TO DO *)
1615 code
:= Jvm
.opc_l2i
;
1616 ELSE RETURN; (* PREMATURE RETURN! *)
1619 jf
.ConvertDn(inT
, Blt
.intTp
);
1620 (* jf.RangeCheck(...); STILL TO DO *)
1621 code
:= Jvm
.opc_i2s
;
1623 jf
.ConvertDn(inT
, Blt
.intTp
);
1624 (* jf.RangeCheck(...); STILL TO DO *)
1626 code
:= Jvm
.opc_iand
;
1628 jf
.ConvertDn(inT
, Blt
.intTp
);
1629 (* jf.RangeCheck(...); STILL TO DO *)
1630 code
:= Jvm
.opc_i2b
;
1632 jf
.ConvertDn(inT
, Blt
.intTp
); RETURN; (* PREMATURE RETURN! *)
1634 jf
.ConvertDn(inT
, Blt
.intTp
);
1635 (* jf.RangeCheck(...); STILL TO DO *)
1636 code
:= Jvm
.opc_i2c
;
1638 jf
.ConvertDn(inT
, Blt
.intTp
);
1639 (* jf.RangeCheck(...); STILL TO DO *)
1641 code
:= Jvm
.opc_iand
;
1646 (* ------------------------------------------------------------ *)
1648 PROCEDURE (jf
: JavaFile
)EmitOneRange
*
1649 (var
: INTEGER; (* local variable index *)
1650 loC
: INTEGER; (* low-value of range *)
1651 hiC
: INTEGER; (* high-value of range *)
1652 min
: INTEGER; (* minimun selector val *)
1653 max
: INTEGER; (* maximum selector val *)
1654 def
: Label
; (* default code label *)
1655 target
: Label
),NEW;
1656 (* ---------------------------------------------------------- *
1657 * The selector value is known to be in the range min .. max *
1658 * and we wish to send values between loC and hiC to the *
1659 * target code label. All otherwise go to def. *
1660 * A range is "compact" if it is hard against min/max limits *
1661 * ---------------------------------------------------------- *)
1664 * Deal with several special cases...
1666 IF (min
= loC
) & (max
= hiC
) THEN (* fully compact: just GOTO *)
1667 jf
.CodeLb(Jvm
.opc_goto
, target
);
1669 jf
.LoadLocal(var
, Blt
.intTp
);
1670 IF loC
= hiC
THEN (* a singleton *)
1672 jf
.CodeLb(Jvm
.opc_if_icmpeq
, target
);
1673 ELSIF min
= loC
THEN (* compact at low end only *)
1675 jf
.CodeLb(Jvm
.opc_if_icmple
, target
);
1676 ELSIF max
= hiC
THEN (* compact at high end only *)
1678 jf
.CodeLb(Jvm
.opc_if_icmpge
, target
);
1679 ELSE (* Shucks! The general case *)
1681 jf
.CodeLb(Jvm
.opc_if_icmplt
, def
);
1682 jf
.LoadLocal(var
, Blt
.intTp
);
1684 jf
.CodeLb(Jvm
.opc_if_icmple
, target
);
1686 jf
.CodeLb(Jvm
.opc_goto
, def
);
1690 (* ------------------------------------------------------------ *)
1692 PROCEDURE (jf
: JavaFile
)Return
*(ret
: Sym
.Type
),NEW;
1695 jf
.Code(Jvm
.opc_return
);
1696 ELSIF ret
IS Ty
.Base
THEN
1697 jf
.Code(typeRetn
[ret(Ty
.Base
).tpOrd
]);
1699 jf
.Code(Jvm
.opc_areturn
);
1703 (* ------------------------------------------------------------ *)
1705 PROCEDURE (jf
: JavaFile
)FixPar(par
: Id
.ParId
),NEW;
1708 * Load up the actual into boxVar[0];
1710 jf
.LoadLocal(par
.boxOrd
, NIL);
1711 jf
.Code(Jvm
.opc_iconst_0
);
1713 * The param might be an XHR field, so
1714 * jf.LoadLocal(par.varOrd, par.type) breaks.
1717 jf
.PutElement(par
.type
);
1720 (* ------------------------------------------------------------ *)
1722 PROCEDURE (jf
: JavaFile
)FixOutPars
*(pId
: Id
.Procs
; OUT ret
: Sym
.Type
),NEW;
1723 VAR frm
: Ty
.Procedure
;
1729 * Receivers are never boxed in Component Pascal.
1731 * WITH pId : Id.MthId DO
1732 * par := pId.rcvFrm;
1733 * IF par.boxOrd # 0 THEN jf.FixPar(par) END;
1734 * ELSE (* nothing *)
1737 frm
:= pId
.type(Ty
.Procedure
);
1738 FOR idx
:= 0 TO frm
.formals
.tide
-1 DO
1739 par
:= frm
.formals
.a
[idx
];
1740 IF par
.boxOrd
= retMarker
THEN
1743 * The param might be an XHR field, so
1744 * jf.LoadLocal(par.varOrd, ret) breaks.
1747 ELSIF needsBox(par
) THEN
1752 * If ret is still NIL, then either there is an explicit
1753 * return type, or there was no OUT or VAR parameters here.
1756 IF (ret
= NIL) & (pId
.kind
# Id
.ctorP
) THEN ret
:= frm
.retType
END;
1759 (* ------------------------------------------------------------ *)
1761 PROCEDURE (jf
: JavaFile
)PushJunkAndReturn
*(),NEW;
1762 VAR frm
: Ty
.Procedure
;
1768 * This procedure pushes a dummy return value
1769 * if that is necessary, and calls return.
1772 IF jf
.theP
= NIL THEN RETURN END; (* PREMATURE EXIT FOR MOD BODY *)
1773 frm
:= jf
.theP
.type(Ty
.Procedure
);
1775 * First, we must find the (jvm) return type.
1776 * It would have been nice to store this in out.info!
1778 FOR idx
:= 0 TO frm
.formals
.tide
-1 DO
1779 par
:= frm
.formals
.a
[idx
];
1780 IF par
.boxOrd
= retMarker
THEN ret
:= par
.type
END;
1782 IF ret
= NIL THEN ret
:= frm
.retType
END;
1784 * Now push a "zero" if necessary, then return.
1785 * If this is a void function in the JVM, then we
1786 * may safely leave things to the fall through return.
1789 WITH ret
: Ty
.Base
DO
1791 | Ty
.boolN
.. Ty
.intN
: jf
.Code(Jvm
.opc_iconst_0
);
1792 | Ty
.lIntN
: jf
.Code(Jvm
.opc_lconst_0
);
1793 | Ty
.sReaN
: jf
.Code(Jvm
.opc_fconst_0
);
1794 | Ty
.realN
: jf
.Code(Jvm
.opc_dconst_0
);
1795 ELSE jf
.Code(Jvm
.opc_aconst_null
);
1798 jf
.Code(Jvm
.opc_aconst_null
);
1802 END PushJunkAndReturn
;
1804 (* ------------------------------------------------------------ *)
1806 PROCEDURE (jf
: JavaFile
)Init1dArray
*(elTp
: Sym
.Type
; leng
: INTEGER),NEW;
1807 CONST inlineLimit
= 4;
1813 * Precondition: elTp is either a record or fixed array.
1814 * At entry stack is (top) arrayRef, unchanged at exit.
1815 * (len == 0) ==> take length from runtime descriptor.
1817 IF (leng
< 4) & (leng
# 0) & (elTp
.kind
= Ty
.recTp
) THEN
1819 * Do a compile-time loop ...
1821 FOR indx
:= 0 TO leng
-1 DO
1822 jf
.Code(Jvm
.opc_dup
);
1824 jf
.MkNewRecord(elTp(Ty
.Record
));
1825 jf
.Code(Jvm
.opc_aastore
);
1828 (* ------------------------------------------------------ *
1829 * Do a runtime loop ...
1831 * push-len> ; (top) len, ref,...
1833 * iconst_1 ; (top) 1, len, ref,...
1834 * isub ; (top) len*, ref,...
1835 * dup2 ; (top) len*, ref, len*, ref,...
1836 * <newElem> ; (top) new, len*, ref, len*, ref,...
1837 * aastore ; (top) len*, ref,...
1838 * dup ; (top) len*, len*, ref,...
1839 * ifne loop ; (top) len*, ref,...
1840 * pop ; (top) ref, ...
1841 * ------------------------------------------------------ *)
1842 IF leng
= 0 THEN (* find the length from the descriptor *)
1843 jf
.Code(Jvm
.opc_dup
);
1844 jf
.Code(Jvm
.opc_arraylength
);
1848 labl
:= jf
.newLabel();
1849 jf
.DefLabC(labl
, "1-d init loop");
1850 jf
.Code(Jvm
.opc_iconst_1
);
1851 jf
.Code(Jvm
.opc_isub
);
1852 jf
.Code(Jvm
.opc_dup2
);
1853 IF elTp
.kind
= Ty
.recTp
THEN
1854 jf
.MkNewRecord(elTp(Ty
.Record
));
1856 arrT
:= elTp(Ty
.Array
);
1857 jf
.MkNewFixedArray(arrT
.elemTp
, arrT
.length
);
1859 jf
.Code(Jvm
.opc_aastore
);
1860 jf
.Code(Jvm
.opc_dup
);
1861 jf
.CodeLb(Jvm
.opc_ifne
, labl
);
1862 jf
.CodeC(Jvm
.opc_pop
, " ; end 1-d loop");
1866 (* ============================================================ *)
1868 PROCEDURE (jf
: JavaFile
)InitNdArray
*(desc
: Sym
.Type
; elTp
: Sym
.Type
),NEW;
1871 (* ------------------------------------------------------ *
1872 * Initialize multi-dimensional array, using
1873 * the runtime array descriptors to generate lengths.
1874 * Here, desc is the outer element type; elTp
1877 * At entry stack is (top) arrayRef, unchanged at exit.
1879 * dup ; (top) ref,ref...
1880 * arraylength ; (top) len,ref...
1882 * iconst_1 ; (top) 1,len,ref...
1883 * isub ; (top) len',ref...
1884 * dup2 ; (top) hi,ref,hi,ref...
1886 * <eleminit> ; (top) rec,ref[i],hi,ref...
1887 * aastore ; (top) hi,ref...
1889 * aaload ; (top) ref[i],hi,ref...
1890 * <recurse> ; (top) ref[i],hi,ref...
1891 * pop ; (top) hi,ref...
1893 * dup ; (top) hi,hi,ref...
1894 * ifne loop ; (top) hi,ref...
1895 * pop ; (top) ref...
1896 * ------------------------------------------------------ *)
1897 labl
:= jf
.newLabel();
1898 jf
.Code(Jvm
.opc_dup
);
1899 jf
.Code(Jvm
.opc_arraylength
);
1900 jf
.DefLabC(labl
, "Element init loop");
1901 jf
.Code(Jvm
.opc_iconst_1
);
1902 jf
.Code(Jvm
.opc_isub
);
1903 jf
.Code(Jvm
.opc_dup2
);
1906 * This is the innermost loop!
1908 WITH elTp
: Ty
.Array
DO
1910 * Must be switching from open to fixed arrays...
1912 jf
.MkNewFixedArray(elTp
.elemTp
, elTp
.length
);
1913 | elTp
: Ty
.Record
DO
1915 * Element type is some record type.
1917 jf
.MkNewRecord(elTp
);
1919 jf
.Code(Jvm
.opc_aastore
);
1922 * There are more dimensions to go ... so recurse down.
1924 jf
.Code(Jvm
.opc_aaload
);
1925 jf
.InitNdArray(desc(Ty
.Array
).elemTp
, elTp
);
1926 jf
.Code(Jvm
.opc_pop
);
1928 jf
.Code(Jvm
.opc_dup
);
1929 jf
.CodeLb(Jvm
.opc_ifne
, labl
);
1930 jf
.CodeC(Jvm
.opc_pop
, " ; end loop");
1933 (* ============================================================ *)
1935 PROCEDURE (jf
: JavaFile
)ValArrCopy
*(typ
: Ty
.Array
),NEW;
1936 VAR local
: INTEGER;
1942 * Stack at entry is (top) srcRef, dstRef...
1944 label
:= jf
.newLabel();
1945 local
:= jf
.newLocal();
1946 IF typ
.length
= 0 THEN (* open array, get length from source desc *)
1947 jf
.Code(Jvm
.opc_dup
);
1948 jf
.Code(Jvm
.opc_arraylength
);
1950 jf
.PushInt(typ
.length
);
1952 jf
.StoreLocal(local
, Blt
.intTp
);
1954 * <get length> ; (top) n,rr,lr...
1955 * store(n) ; (top) rr,lr...
1957 * dup2 ; (top) rr,lr,rr,lr...
1958 * iinc n -1 ; (top) rr,lr...
1959 * load(n) ; (top) n,rr,lr,rr,lr...
1960 * dup_x1 ; (top) n,rr,n,lr,rr,lr...
1961 * <doassign> ; (top) rr,lr
1962 * load(n) ; (top) n,rr,lr...
1963 * ifne lab ; (top) rr,lr...
1967 jf
.Code(Jvm
.opc_dup2
);
1968 jf
.CodeInc(local
, -1);
1969 jf
.LoadLocal(local
, Blt
.intTp
);
1970 jf
.Code(Jvm
.opc_dup_x1
);
1972 * Assign the element
1974 elTyp
:= typ
.elemTp
;
1975 jf
.GetElement(elTyp
); (* (top) r[n],n,lr,rr,lr... *)
1976 IF (elTyp
.kind
= Ty
.arrTp
) OR
1977 (elTyp
.kind
= Ty
.recTp
) THEN
1978 sTemp
:= jf
.newLocal(); (* must recurse in copy code *)
1979 jf
.StoreLocal(sTemp
, elTyp
); (* (top) n,lr,rr,lr... *)
1980 jf
.GetElement(elTyp
); (* (top) l{n],rr,lr... *)
1981 jf
.LoadLocal(sTemp
, elTyp
); (* (top) r[n],l[n],rr,lr... *)
1982 jf
.ReleaseLocal(sTemp
);
1983 WITH elTyp
: Ty
.Record
DO
1984 jf
.ValRecCopy(elTyp
);
1985 | elTyp
: Ty
.Array
DO
1986 jf
.ValArrCopy(elTyp
);
1989 jf
.PutElement(elTyp
);
1992 * stack is (top) rr,lr...
1994 jf
.LoadLocal(local
, Blt
.intTp
);
1995 jf
.CodeLb(Jvm
.opc_ifne
, label
);
1996 jf
.Code(Jvm
.opc_pop2
);
1997 jf
.ReleaseLocal(local
);
2000 (* ============================================================ *)
2002 PROCEDURE (jf
: JavaFile
)InitVars
*(scp
: Sym
.Scope
),NEW;
2003 VAR index
: INTEGER;
2010 * Create the explicit activation record, if needed.
2012 WITH scp
: Id
.Procs
DO
2013 IF Id
.hasXHR
IN scp
.pAttr
THEN
2014 xhrNo
:= scp
.type(Ty
.Procedure
).argN
;
2015 jf
.Comment("create XHR record");
2016 jf
.MkNewRecord(scp
.xhrType
.boundRecTp()(Ty
.Record
));
2017 IF scp
.lxDepth
> 0 THEN
2018 jf
.Code(Jvm
.opc_dup
);
2019 jf
.Code(Jvm
.opc_aload_0
);
2020 jf
.PutGetF(Jvm
.opc_putfield
,
2021 Cst
.rtsXHR
.boundRecTp()(Ty
.Record
), Cst
.xhrId
);
2023 jf
.StoreLocal(xhrNo
, NIL);
2028 * Initialize local fields, if needed
2030 FOR index
:= 0 TO scp
.locals
.tide
-1 DO
2031 ident
:= scp
.locals
.a
[index
];
2032 scalr
:= ident
.type
.isScalarType();
2033 WITH ident
: Id
.ParId
DO
2035 * If any args are uplevel addressed, they must
2036 * be copied to the correct field of the XHR.
2037 * The test "varOrd < xhrNo" excludes out params.
2039 IF (Id
.uplevA
IN ident
.locAtt
) & (ident
.varOrd
< xhrNo
) THEN
2040 jf
.LoadLocal(xhrNo
, NIL);
2041 jf
.LoadLocal(ident
.varOrd
, ident
.type
);
2042 jf
.PutGetX(Jvm
.opc_putfield
, ident
);
2044 | ident
: Id
.LocId
DO
2046 IF Id
.uplevA
IN ident
.locAtt
THEN jf
.LoadLocal(xhrNo
, NIL) END;
2050 | ident
: Id
.VarId
DO
2053 jf
.PutGetS(Jvm
.opc_putstatic
, scp(Id
.BlkId
), ident
);
2059 (* ============================================================ *)
2064 InitVecDescriptors();
2067 (* ============================================================ *)
2068 (* ============================================================ *)
2071 invokeHash
:= Hsh
.enterStr("Invoke");
2073 L
.InitCharOpenSeq(fmArray
, 8);
2074 L
.InitCharOpenSeq(nmArray
, 8);
2076 typeRetn
[ Ty
.boolN
] := Jvm
.opc_ireturn
;
2077 typeRetn
[ Ty
.sChrN
] := Jvm
.opc_ireturn
;
2078 typeRetn
[ Ty
.charN
] := Jvm
.opc_ireturn
;
2079 typeRetn
[ Ty
.byteN
] := Jvm
.opc_ireturn
;
2080 typeRetn
[ Ty
.sIntN
] := Jvm
.opc_ireturn
;
2081 typeRetn
[ Ty
.intN
] := Jvm
.opc_ireturn
;
2082 typeRetn
[ Ty
.lIntN
] := Jvm
.opc_lreturn
;
2083 typeRetn
[ Ty
.sReaN
] := Jvm
.opc_freturn
;
2084 typeRetn
[ Ty
.realN
] := Jvm
.opc_dreturn
;
2085 typeRetn
[ Ty
.setN
] := Jvm
.opc_ireturn
;
2086 typeRetn
[Ty
.anyPtr
] := Jvm
.opc_areturn
;
2087 typeRetn
[ Ty
.uBytN
] := Jvm
.opc_ireturn
;
2089 typeLoad
[ Ty
.boolN
] := Jvm
.opc_iload
;
2090 typeLoad
[ Ty
.sChrN
] := Jvm
.opc_iload
;
2091 typeLoad
[ Ty
.charN
] := Jvm
.opc_iload
;
2092 typeLoad
[ Ty
.byteN
] := Jvm
.opc_iload
;
2093 typeLoad
[ Ty
.sIntN
] := Jvm
.opc_iload
;
2094 typeLoad
[ Ty
.intN
] := Jvm
.opc_iload
;
2095 typeLoad
[ Ty
.lIntN
] := Jvm
.opc_lload
;
2096 typeLoad
[ Ty
.sReaN
] := Jvm
.opc_fload
;
2097 typeLoad
[ Ty
.realN
] := Jvm
.opc_dload
;
2098 typeLoad
[ Ty
.setN
] := Jvm
.opc_iload
;
2099 typeLoad
[Ty
.anyPtr
] := Jvm
.opc_aload
;
2100 typeLoad
[Ty
.anyRec
] := Jvm
.opc_aload
;
2101 typeLoad
[ Ty
.uBytN
] := Jvm
.opc_iload
;
2103 typeStore
[ Ty
.boolN
] := Jvm
.opc_istore
;
2104 typeStore
[ Ty
.sChrN
] := Jvm
.opc_istore
;
2105 typeStore
[ Ty
.charN
] := Jvm
.opc_istore
;
2106 typeStore
[ Ty
.byteN
] := Jvm
.opc_istore
;
2107 typeStore
[ Ty
.sIntN
] := Jvm
.opc_istore
;
2108 typeStore
[ Ty
.intN
] := Jvm
.opc_istore
;
2109 typeStore
[ Ty
.lIntN
] := Jvm
.opc_lstore
;
2110 typeStore
[ Ty
.sReaN
] := Jvm
.opc_fstore
;
2111 typeStore
[ Ty
.realN
] := Jvm
.opc_dstore
;
2112 typeStore
[ Ty
.setN
] := Jvm
.opc_istore
;
2113 typeStore
[Ty
.anyPtr
] := Jvm
.opc_astore
;
2114 typeStore
[Ty
.anyRec
] := Jvm
.opc_astore
;
2115 typeStore
[ Ty
.uBytN
] := Jvm
.opc_istore
;
2117 typePutE
[ Ty
.boolN
] := Jvm
.opc_bastore
;
2118 typePutE
[ Ty
.sChrN
] := Jvm
.opc_castore
;
2119 typePutE
[ Ty
.charN
] := Jvm
.opc_castore
;
2120 typePutE
[ Ty
.byteN
] := Jvm
.opc_bastore
;
2121 typePutE
[ Ty
.sIntN
] := Jvm
.opc_sastore
;
2122 typePutE
[ Ty
.intN
] := Jvm
.opc_iastore
;
2123 typePutE
[ Ty
.lIntN
] := Jvm
.opc_lastore
;
2124 typePutE
[ Ty
.sReaN
] := Jvm
.opc_fastore
;
2125 typePutE
[ Ty
.realN
] := Jvm
.opc_dastore
;
2126 typePutE
[ Ty
.setN
] := Jvm
.opc_iastore
;
2127 typePutE
[Ty
.anyPtr
] := Jvm
.opc_aastore
;
2128 typePutE
[Ty
.anyRec
] := Jvm
.opc_aastore
;
2129 typePutE
[ Ty
.uBytN
] := Jvm
.opc_bastore
;
2131 typeGetE
[ Ty
.boolN
] := Jvm
.opc_baload
;
2132 typeGetE
[ Ty
.sChrN
] := Jvm
.opc_caload
;
2133 typeGetE
[ Ty
.charN
] := Jvm
.opc_caload
;
2134 typeGetE
[ Ty
.byteN
] := Jvm
.opc_baload
;
2135 typeGetE
[ Ty
.sIntN
] := Jvm
.opc_saload
;
2136 typeGetE
[ Ty
.intN
] := Jvm
.opc_iaload
;
2137 typeGetE
[ Ty
.lIntN
] := Jvm
.opc_laload
;
2138 typeGetE
[ Ty
.sReaN
] := Jvm
.opc_faload
;
2139 typeGetE
[ Ty
.realN
] := Jvm
.opc_daload
;
2140 typeGetE
[ Ty
.setN
] := Jvm
.opc_iaload
;
2141 typeGetE
[Ty
.anyPtr
] := Jvm
.opc_aaload
;
2142 typeGetE
[Ty
.anyRec
] := Jvm
.opc_aaload
;
2143 typeGetE
[ Ty
.uBytN
] := Jvm
.opc_baload
;
2145 semi
:= L
.strToCharOpen(";");
2146 comma
:= L
.strToCharOpen(",");
2147 colon
:= L
.strToCharOpen(":");
2148 lPar
:= L
.strToCharOpen("(");
2149 rPar
:= L
.strToCharOpen(")");
2150 brac
:= L
.strToCharOpen("[");
2151 lCap
:= L
.strToCharOpen("L");
2152 void
:= L
.strToCharOpen("V");
2153 rParV
:= L
.strToCharOpen(")V");
2154 lowL
:= L
.strToCharOpen("_");
2155 slsh
:= L
.strToCharOpen("/");
2156 dlar
:= L
.strToCharOpen("$");
2157 prfx
:= L
.strToCharOpen(classPrefix
);
2158 xhrDl
:= L
.strToCharOpen("XHR$");
2159 xhrMk
:= L
.strToCharOpen("LCP/CPJrts/XHR;");
2160 procLitPrefix
:= L
.strToCharOpen("Proc$Lit$");
2162 Blt
.setTp
.xName
:= L
.strToCharOpen("I");
2163 Blt
.intTp
.xName
:= L
.strToCharOpen("I");
2164 Blt
.boolTp
.xName
:= L
.strToCharOpen("Z");
2165 Blt
.byteTp
.xName
:= L
.strToCharOpen("B");
2166 Blt
.uBytTp
.xName
:= L
.strToCharOpen("B"); (* same as BYTE *)
2167 Blt
.charTp
.xName
:= L
.strToCharOpen("C");
2168 Blt
.sChrTp
.xName
:= L
.strToCharOpen("C");
2169 Blt
.sIntTp
.xName
:= L
.strToCharOpen("S");
2170 Blt
.lIntTp
.xName
:= L
.strToCharOpen("J");
2171 Blt
.realTp
.xName
:= L
.strToCharOpen("D");
2172 Blt
.sReaTp
.xName
:= L
.strToCharOpen("F");
2173 Blt
.anyRec
.xName
:= L
.strToCharOpen("Ljava/lang/Object;");
2174 Blt
.anyPtr
.xName
:= Blt
.anyRec
.xName
;
2176 (* ============================================================ *)
2177 (* ============================================================ *)