1 (* ============================================================ *)
2 (* MsilUtil is the module which writes ILASM file structures *)
3 (* Copyright (c) John Gough 1999, 2000. *)
4 (* ============================================================ *)
8 IMPORT
9 GPCPcopyright,
10 RTS,
11 ASCII,
12 Console,
13 GPText,
14 GPBinFiles,
15 GPTextFiles,
27 (* ============================================================ *)
29 CONST
30 (* various ILASM-specific runtime name strings *)
43 CONST
47 (* ============================================================ *)
48 (* ============================================================ *)
51 (* Fields inherited from MsilFile *
52 * srcS* : Lv.CharOpen; (* source file name *)
55 *)
61 (* ============================================================ *)
67 (* ============================================================ *)
71 (* ============================================================ *)
95 (* ============================================================ *)
96 (* Utility Coercion Method *)
97 (* ============================================================ *)
103 BEGIN
112 (* ============================================================ *)
113 (* Constructor Method *)
114 (* ============================================================ *)
118 BEGIN
125 (* ============================================================ *)
128 BEGIN
132 (* ============================================================ *)
133 (* Some static utilities *)
134 (* ============================================================ *)
143 (* ============================================================ *)
146 BEGIN
151 (* ============================================================ *)
155 BEGIN
162 (* ============================================================ *)
163 (* Signature handling for this version *)
164 (* ============================================================ *)
173 (* ----------------------------------------- *)
177 BEGIN
178 (*
179 * We append type names, which must be lexically
180 * equivalent to the names used in the declaration
181 * in MethodDecl.
182 *)
197 (*
198 * This is a pointer to a value class, which has a
199 * runtime representation as a boxed-class reference.
200 *)
204 ELSE
219 (* ----------------------------------------- *)
220 BEGIN
245 (*
246 * The current info.lNum (before the locals
247 * have been added) is the argsize.
248 *)
253 (* ============================================================ *)
254 (* Private Methods *)
255 (* ============================================================ *)
258 BEGIN
262 (* ============================================================ *)
265 BEGIN
269 (* ============================================================ *)
273 BEGIN
277 (* ============================================================ *)
281 BEGIN
285 (* ============================================================ *)
288 BEGIN
292 (* ============================================================ *)
296 BEGIN
301 (* ============================================================ *)
304 BEGIN
310 (* ============================================================ *)
313 (* TAB, then string *)
314 BEGIN
318 (* ============================================================ *)
321 (* BLANK, then string *)
322 BEGIN
326 (* ============================================================ *)
329 (* TAB, then int *)
330 BEGIN
334 (* ============================================================ *)
337 (* TAB, then long *)
338 BEGIN
342 (* ============================================================ *)
345 (* ------------------------ *)
350 BEGIN
352 FOR idx := 0 TO LEN(str) - 2 DO
353 chr := str[idx];
354 CASE chr OF
361 ELSE
368 ELSE
370 END
374 END EmitQuotedString;
375 (* ------------------------ *)
376 PROCEDURE EmitByteArray(os : IlasmFile; IN str : ARRAY OF CHAR);
377 VAR idx : INTEGER;
378 ord : INTEGER;
379 BEGIN
381 FOR idx := 0 TO LEN(str) - 2 DO
382 ord := ORD(str[idx]);
383 os.WriteHexByte(ord MOD 256);
384 os.WriteHexByte(ord DIV 256);
385 END;
387 END EmitByteArray;
388 (* ------------------------ *)
389 PROCEDURE NotASCIIZ(IN str : ARRAY OF CHAR) : BOOLEAN;
390 VAR idx : INTEGER;
391 ord : INTEGER;
392 BEGIN
393 FOR idx := 0 TO LEN(str) - 2 DO
394 ord := ORD(str[idx]);
395 IF (ord = 0) OR (ord > 0FFH) THEN RETURN TRUE END;
396 END;
397 RETURN FALSE;
398 END NotASCIIZ;
399 (* ------------------------ *)
400 BEGIN
401 IF NotASCIIZ(str) THEN
402 EmitByteArray(os, str);
403 ELSE
404 EmitQuotedString(os, str);
405 END;
406 END QuoteStr;
408 (* ============================================================ *)
410 PROCEDURE (os : IlasmFile)Prefix(code : INTEGER),NEW;
411 BEGIN
412 os.CatChar(ASCII.HT); os.CatStr(Asm.op[code]);
413 END Prefix;
415 (* ============================================================ *)
417 PROCEDURE (os : IlasmFile)IAdjust*(delta : INTEGER),NEW;
418 BEGIN
419 os.Adjust(delta);
420 IF Cs.verbose THEN
422 os.CatInt(os.proc.dNum);
424 os.CatInt(os.proc.dMax);
425 END;
426 os.CatEOL();
427 END IAdjust;
429 (* ============================================================ *)
431 PROCEDURE (os : IlasmFile)Suffix(code : INTEGER),NEW;
432 BEGIN
433 os.Adjust(Asm.dl[code]);
434 IF Cs.verbose THEN
436 os.CatInt(os.proc.dNum);
438 os.CatInt(os.proc.dMax);
439 END;
440 os.CatEOL();
441 END Suffix;
443 (* ============================================================ *)
445 PROCEDURE (os : IlasmFile)Access*(acc : SET),NEW;
446 VAR att : INTEGER;
447 BEGIN
449 FOR att := 0 TO Asm.maxAttIndex DO
450 IF att IN acc THEN
451 os.CatStr(Asm.access[att]);
452 os.CatChar(' ');
453 END;
454 END;
455 END Access;
457 (* ============================================================ *)
459 PROCEDURE (os : IlasmFile)RefLab*(l : Mu.Label),NEW;
460 BEGIN
461 os.CatChar(ASCII.HT);
464 os.CatInt(l(ILabel).labl);
465 END RefLab;
467 (* ------------------------------------ *)
469 PROCEDURE (os : IlasmFile)LstLab*(l : Mu.Label);
470 BEGIN
472 os.CatEOL();
474 os.CatInt(l(ILabel).labl);
475 END LstLab;
477 (* ============================================================ *)
479 PROCEDURE (os : IlasmFile)SwitchHead*(n : INTEGER);
480 (* n is table length, ignored here *)
481 BEGIN
482 os.Prefix(Asm.opc_switch);
484 os.CatInt(n);
485 END SwitchHead;
487 (* ------------------------------------ *)
489 PROCEDURE (os : IlasmFile)SwitchTail*();
490 BEGIN
492 os.IAdjust(-1);
493 END SwitchTail;
495 (* ============================================================ *)
497 PROCEDURE (os : IlasmFile)Idnt(idD : Sy.Idnt),NEW;
498 BEGIN
500 os.CatStr(Sy.getName.ChPtr(idD));
502 END Idnt;
504 (* ------------------------------------ *)
506 PROCEDURE (os : IlasmFile)SQuote(str : Lv.CharOpen),NEW;
507 BEGIN
509 os.CatStr(str);
511 END SQuote;
513 (* ------------------------------------ *)
515 PROCEDURE (os : IlasmFile)TsQuote(str : Lv.CharOpen),NEW;
516 BEGIN
517 os.CatChar(ASCII.HT); os.SQuote(str);
518 END TsQuote;
520 (* ------------------------------------ *)
522 PROCEDURE (os : IlasmFile)Tidnt(idD : Sy.Idnt),NEW;
523 BEGIN
524 os.CatChar(ASCII.HT); os.Idnt(idD);
525 END Tidnt;
527 (* ------------------------------------ *)
529 PROCEDURE (os : IlasmFile)Bidnt(idD : Sy.Idnt),NEW;
530 BEGIN
532 END Bidnt;
534 (* ------------------------------------ *)
536 PROCEDURE (os : IlasmFile)PIdnt(idD : Id.Procs),NEW;
537 (* Write out procedure identifier name *)
538 VAR fullNm : Lv.CharOpen;
539 BEGIN
540 IF idD.scopeNm = NIL THEN Mu.MkProcName(idD, os) END;
542 WITH idD : Id.PrcId DO
543 IF idD.bndType = NIL THEN
544 fullNm := Mu.cat2(idD.scopeNm, idD.clsNm);
545 ELSE (* beware of special cases for object and string! *)
546 fullNm := idD.bndType(Ty.Record).scopeNm;
547 END;
548 | idD : Id.MthId DO
549 IF Id.boxRcv IN idD.mthAtt THEN
550 fullNm := Mu.cat3(idD.scopeNm, boxedObj, idD.bndType.xName);
551 ELSE (* beware of special cases for object and string! *)
552 fullNm := idD.bndType(Ty.Record).scopeNm;
553 END;
554 END;
555 os.CatStr(fullNm);
556 os.CatStr(cln2);
557 os.SQuote(idD.prcNm);
558 END PIdnt;
560 (* ============================================================ *)
562 PROCEDURE (os : IlasmFile)TypeTag(typ : Sy.Type),NEW;
563 BEGIN
564 IF typ.xName = NIL THEN Mu.MkTypeName(typ,os) END;
565 WITH typ : Ty.Base DO
566 os.CatStr(typ.xName);
567 | typ : Ty.Vector DO
568 os.CatStr(clss);
569 os.CatStr(typ.xName);
570 | typ : Ty.Array DO
571 os.TypeTag(typ.elemTp);
572 os.CatStr(brks);
573 | typ : Ty.Record DO
574 IF ~(Sy.clsTp IN typ.xAttr) THEN os.CatStr(vals) END;
575 IF ~(Sy.spshl IN typ.xAttr) THEN os.CatStr(clss) END;
576 os.CatStr(typ.scopeNm);
577 | typ : Ty.Procedure DO (* and also Event! *)
578 os.CatStr(clss);
579 os.CatStr(typ.tName);
580 | typ : Ty.Pointer DO
581 IF Mu.isValRecord(typ.boundTp) THEN
582 (*
583 * This is a pointer to a value class, which has a
584 * runtime representation as a boxed-class reference.
585 *)
586 os.CatStr(clss);
587 os.CatStr(typ.xName);
588 ELSE
589 os.TypeTag(typ.boundTp);
590 END;
591 | typ : Ty.Opaque DO
592 os.CatStr(clss);
593 os.CatStr(typ.xName);
594 | typ : Ty.Enum DO
595 os.CatStr(vals);
596 os.CatStr(clss);
597 os.CatStr(typ.xName);
598 END;
599 END TypeTag;
601 (* ============================================================ *)
603 PROCEDURE (os : IlasmFile)Translate(IN str : ARRAY OF CHAR),NEW;
604 VAR ix : INTEGER;
605 ch : CHAR;
606 BEGIN
607 ix := 0; ch := str[0];
608 WHILE ch # 0X DO
609 IF ch = '$' THEN
610 INC(ix); ch := str[ix];
615 END;
616 ELSE
617 os.CatChar(ch);
618 END;
619 INC(ix); ch := str[ix];
620 END;
621 END Translate;
623 PROCEDURE (os : IlasmFile)TTranslate(IN str : ARRAY OF CHAR),NEW;
624 BEGIN
625 os.CatChar(ASCII.HT);
626 os.Translate(str);
627 END TTranslate;
629 (* ============================================================ *)
631 PROCEDURE (os : IlasmFile)TtypeTag(typ : Sy.Type),NEW;
632 BEGIN
633 os.CatChar(ASCII.HT);
634 os.TypeTag(typ);
635 END TtypeTag;
637 (* ------------------------------------ *)
639 PROCEDURE (os : IlasmFile)TtypeNam(typ : Sy.Type),NEW;
640 BEGIN
641 os.Tstring(Mu.typeName(typ, os));
642 END TtypeNam;
644 (* ------------------------------------ *)
646 PROCEDURE (os : IlasmFile)TypeName(typ : Sy.Type),NEW;
647 BEGIN
648 os.CatStr(Mu.typeName(typ, os));
649 END TypeName;
651 (* ============================================================ *)
653 PROCEDURE (os : IlasmFile)RetType(typ : Ty.Procedure; pId : Id.Procs),NEW;
654 BEGIN
655 IF typ.retType = NIL THEN
656 os.CatStr(vStr);
657 ELSIF (pId # NIL) & (pId IS Id.MthId) &
658 (Id.covar IN pId(Id.MthId).mthAtt) THEN
659 (*
660 * This is a method with a covariant return type. We must
661 * erase the declared type, substituting the non-covariant
662 * upper-bound. Calls will cast the result to the real type.
663 *)
664 os.TypeTag(pId.retTypBound());
665 ELSE
666 os.TypeTag(typ.retType);
667 END;
668 END RetType;
670 (* ============================================================ *)
671 (* Exported Methods *)
672 (* ============================================================ *)
674 PROCEDURE (os : IlasmFile)Blank*();
675 BEGIN
676 os.CatEOL();
677 END Blank;
679 (* ============================================================ *)
681 PROCEDURE (os : IlasmFile)Separator(c : CHAR; i : INTEGER),NEW;
682 BEGIN
683 os.CatChar(c);
684 os.CatEOL();
685 WHILE i > 0 DO os.CatChar(ASCII.HT); DEC(i) END;
686 END Separator;
688 (* ============================================================ *)
690 PROCEDURE (os : IlasmFile)OpenBrace*(i : INTEGER);
691 BEGIN
694 os.CatEOL();
695 END OpenBrace;
697 (* ============================================================ *)
699 PROCEDURE (os : IlasmFile)CloseBrace*(i : INTEGER);
700 BEGIN
703 os.CatEOL();
704 END CloseBrace;
706 (* ============================================================ *)
708 PROCEDURE (os : IlasmFile)Directive*(dir : INTEGER),NEW;
709 BEGIN
710 os.CatStr(Asm.dirStr[dir]);
711 os.CatEOL();
712 END Directive;
714 (* -------------------------------------------- *)
716 PROCEDURE (os : IlasmFile)DirectiveS*(dir : INTEGER;
717 IN str : ARRAY OF CHAR),NEW;
718 BEGIN
719 os.CatStr(Asm.dirStr[dir]);
720 os.Bstring(str);
721 os.CatEOL();
722 END DirectiveS;
724 (* -------------------------------------------- *)
726 PROCEDURE (os : IlasmFile)DirectiveIS*(dir : INTEGER;
727 att : SET;
728 IN str : ARRAY OF CHAR),NEW;
729 BEGIN
730 os.CatStr(Asm.dirStr[dir]);
731 os.Access(att);
732 os.CatStr(str);
733 os.CatEOL();
734 END DirectiveIS;
736 (* -------------------------------------------- *)
738 PROCEDURE (os : IlasmFile)DirectiveISS*(dir : INTEGER;
739 att : SET;
740 IN s1 : ARRAY OF CHAR;
741 IN s2 : ARRAY OF CHAR),NEW;
742 BEGIN
743 os.CatStr(Asm.dirStr[dir]);
744 os.Access(att);
745 os.CatStr(s1);
746 os.CatStr(s2);
747 IF dir = Asm.dot_method THEN os.Bstring(managedStr) END;
748 os.CatEOL();
749 END DirectiveISS;
751 (* ============================================================ *)
753 PROCEDURE (os : IlasmFile)Finish*();
754 BEGIN
755 GPBinFiles.CloseFile(os.file);
756 END Finish;
758 (* ------------------------------------------------- *)
760 PROCEDURE (os : IlasmFile)MkBodyClass*(mod : Id.BlkId);
761 BEGIN
762 os.clsN := mod.clsNm;
763 os.DirectiveIS(Asm.dot_class, Asm.modAttr, os.clsN);
764 END MkBodyClass;
766 (* ------------------------------------------------- *)
768 PROCEDURE (os : IlasmFile)ClassHead*(attSet : SET;
769 thisRc : Ty.Record;
770 superT : Ty.Record);
771 BEGIN
772 os.clsN := thisRc.xName;
773 os.DirectiveIS(Asm.dot_class, attSet, os.clsN);
774 IF superT # NIL THEN
775 IF superT.xName = NIL THEN Mu.MkRecName(superT, os) END;
776 os.DirectiveS(Asm.dot_super, superT.scopeNm);
777 END;
778 END ClassHead;
780 (* ------------------------------------------------- *)
782 PROCEDURE (os : IlasmFile)StartNamespace*(name : Lv.CharOpen);
783 BEGIN
784 os.DirectiveS(Asm.dot_namespace, name);
785 END StartNamespace;
787 (* ------------------------------------------------- *)
789 PROCEDURE (os : IlasmFile)AsmDef*(IN pkNm : ARRAY OF CHAR);
790 BEGIN
792 END AsmDef;
794 (* ------------------------------------------------- *)
796 PROCEDURE (os : IlasmFile)RefRTS*();
797 BEGIN
799 IF Cs.netRel = Cs.netV2_0 THEN
801 END;
802 END RefRTS;
804 (* ============================================================ *)
806 PROCEDURE (os : IlasmFile)SignatureDecl(prcT : Ty.Procedure),NEW;
807 VAR indx : INTEGER;
808 parD : Id.ParId;
809 long : BOOLEAN;
810 nest : BOOLEAN;
811 frst : BOOLEAN;
812 BEGIN
813 frst := TRUE;
814 indx := prcT.formals.tide;
815 nest := (prcT.idnt IS Id.Procs) & (prcT.idnt(Id.Procs).lxDepth > 0);
816 long := (indx > 1) OR (nest & (indx > 0));
819 IF long THEN os.Separator(' ', 2) END;
820 IF nest THEN os.CatStr(xhrMk); frst := FALSE END;
821 FOR indx := 0 TO prcT.formals.tide-1 DO
822 parD := prcT.formals.a[indx];
823 IF long THEN
824 IF ~frst THEN os.Separator(',', 2) END;
825 IF parD.boxOrd = Sy.out THEN os.CatStr(ouMk) END;
826 os.TypeTag(parD.type);
827 IF (parD.boxOrd # Sy.val) OR
828 (Id.cpVarP IN parD.locAtt) THEN os.CatStr(rfMk) END;
829 os.Tidnt(parD);
830 ELSE
831 IF ~frst THEN os.CatStr(cmma) END;
832 IF parD.boxOrd = Sy.out THEN os.CatStr(ouMk) END;
833 os.TypeTag(parD.type);
834 IF (parD.boxOrd # Sy.val) OR
835 (Id.cpVarP IN parD.locAtt) THEN os.CatStr(rfMk) END;
836 os.Bidnt(parD);
837 END;
838 frst := FALSE;
839 END;
841 END SignatureDecl;
843 (* -------------------------------------------- *)
845 PROCEDURE (os : IlasmFile)MethodDecl*(attr : SET; proc : Id.Procs);
846 VAR prcT : Ty.Procedure;
847 BEGIN
848 prcT := proc.type(Ty.Procedure);
849 os.CatStr(Asm.dirStr[Asm.dot_method]);
850 os.Access(attr);
851 os.RetType(prcT, proc);
854 os.CatStr(proc.prcNm);
856 os.SignatureDecl(prcT);
857 os.Bstring(managedStr);
858 os.CatEOL();
859 IF Asm.att_abstract * attr # {} THEN
860 os.Tstring(brsz); os.CatEOL();
861 END;
862 END MethodDecl;
864 (* ------------------------------------------------------------ *)
866 PROCEDURE (os : IlasmFile)CheckNestedClass*(typ : Ty.Record;
867 scp : Sy.Scope;
868 str : Lv.CharOpen);
869 VAR i, len: INTEGER;
870 BEGIN
871 (*
872 * scan str with all occurences of
873 * '$' replaced by '/', except at index 0
874 *)
875 len := LEN(str);
876 FOR i := 1 TO len-1 DO
877 IF str[i] = '$' THEN str[i] := '/' END;
878 END; (* FOR *)
879 END CheckNestedClass;
881 (* ------------------------------------------------------------ *)
883 PROCEDURE (os : IlasmFile)ExternList*();
884 VAR idx : INTEGER;
885 blk : Id.BlkId;
886 (* ----------------------------------------- *)
887 PROCEDURE Assembly(fl : IlasmFile; bk : Id.BlkId);
888 VAR ix : INTEGER;
889 ch : CHAR;
890 BEGIN
891 IF Sy.isFn IN bk.xAttr THEN
892 IF bk.scopeNm[0] # '[' THEN
894 ix := 1;
895 ch := bk.scopeNm[ix];
896 WHILE (ch # 0X) & (ch # ']') DO
897 fl.CatChar(ch);
898 INC(ix);
899 ch := bk.scopeNm[ix];
900 END;
901 ELSE
902 fl.CatStr(bk.xName);
903 END;
904 END Assembly;
905 (* ----------------------------------------- *)
906 PROCEDURE WriteHex(fl : IlasmFile; int : INTEGER);
907 VAR ord : INTEGER;
908 BEGIN
909 IF int <= 9 THEN ord := ORD('0') + int ELSE ord := (ORD('A')-10)+int END;
910 fl.CatChar(CHR(ord));
911 END WriteHex;
912 (* ----------------------------------------- *)
913 PROCEDURE WriteHexByte(fl : IlasmFile; int : INTEGER);
914 BEGIN
915 WriteHex(fl, int DIV 16);
916 WriteHex(fl, int MOD 16);
917 fl.CatChar(' ');
918 END WriteHexByte;
919 (* ----------------------------------------- *)
920 PROCEDURE WriteBytes(fl : IlasmFile; int : INTEGER);
921 BEGIN
922 WriteHexByte(fl, int DIV 1000000H MOD 100H);
923 WriteHexByte(fl, int DIV 10000H MOD 100H);
924 WriteHexByte(fl, int DIV 100H MOD 100H);
925 WriteHexByte(fl, int MOD 100H);
926 END WriteBytes;
927 (* ----------------------------------------- *)
928 PROCEDURE WriteVersionName(os : IlasmFile; IN nam : ARRAY OF INTEGER);
929 BEGIN
932 IF (nam[4] # 0) OR (nam[5] # 0) THEN
934 (*
935 * IF Cs.netRel = Cs.beta2 THEN
937 * ELSE
939 * END;
940 *)
941 WriteBytes(os, nam[4]);
942 WriteBytes(os, nam[5]);
944 os.CatEOL();
945 END;
948 os.CatInt(nam[0]);
950 os.CatInt(nam[1]);
952 os.CatInt(nam[2]);
954 os.CatInt(nam[3]);
955 os.CatEOL();
957 END WriteVersionName;
958 (* ----------------------------------------- *)
959 BEGIN
960 (*
961 * It is empirically established that all the
962 * .assembly extern declarations must come at
963 * the beginning of the ILASM file, at once.
964 *)
965 FOR idx := 0 TO Cs.impSeq.tide-1 DO
966 blk := Cs.impSeq.a[idx](Id.BlkId);
967 IF ~(Sy.rtsMd IN blk.xAttr) & (Sy.need IN blk.xAttr) THEN
968 Mu.MkBlkName(blk);
969 os.CatStr(Asm.dirStr[Asm.dot_assembly]);
970 os.Access(Asm.att_extern);
971 Assembly(os, blk);
972 IF blk.verNm = NIL THEN
974 ELSE
975 WriteVersionName(os, blk.verNm);
976 END;
977 os.CatEOL();
978 END;
979 END;
980 END ExternList;
982 (* -------------------------------------------- *)
984 PROCEDURE (os : IlasmFile)Comment*(IN s : ARRAY OF CHAR);
985 BEGIN
987 os.CatStr(s);
988 os.CatEOL();
989 END Comment;
991 (* -------------------------------------------- *)
993 PROCEDURE (os : IlasmFile)CommentT*(IN s : ARRAY OF CHAR);
994 BEGIN
996 os.CatStr(s);
997 os.CatEOL();
998 END CommentT;
1000 (* ============================================================ *)
1002 PROCEDURE (os : IlasmFile)DefLab*(l : Mu.Label);
1003 BEGIN
1006 os.CatInt(l(ILabel).labl);
1008 os.CatEOL();
1009 END DefLab;
1011 (* -------------------------------------------- *)
1013 PROCEDURE (os : IlasmFile)DefLabC*(l : Mu.Label; IN c : ARRAY OF CHAR);
1014 BEGIN
1017 os.CatInt(l(ILabel).labl);
1019 os.CatChar(ASCII.HT);
1020 os.Comment(c);
1021 END DefLabC;
1023 (* ============================================================ *)
1025 PROCEDURE (os : IlasmFile)Code*(code : INTEGER);
1026 BEGIN
1027 os.Prefix(code);
1028 os.Suffix(code);
1029 END Code;
1031 (* -------------------------------------------- *)
1033 PROCEDURE (os : IlasmFile)CodeI*(code,int : INTEGER);
1034 BEGIN
1035 os.Prefix(code);
1036 os.Tint(int);
1037 os.Suffix(code);
1038 END CodeI;
1040 (* -------------------------------------------- *)
1042 PROCEDURE (os : IlasmFile)CodeT*(code : INTEGER; type : Sy.Type);
1043 BEGIN
1044 os.Prefix(code);
1045 os.TtypeTag(type);
1046 os.Suffix(code);
1047 END CodeT;
1049 (* -------------------------------------------- *)
1051 PROCEDURE (os : IlasmFile)CodeTn*(code : INTEGER; type : Sy.Type);
1052 BEGIN
1053 os.Prefix(code);
1054 os.TtypeNam(type);
1055 os.Suffix(code);
1056 END CodeTn;
1058 (* -------------------------------------------- *)
1060 PROCEDURE (os : IlasmFile)CodeL*(code : INTEGER; long : LONGINT);
1061 BEGIN
1062 os.Prefix(code);
1063 os.Tlong(long);
1064 os.Suffix(code);
1065 END CodeL;
1067 (* -------------------------------------------- *)
1069 PROCEDURE (os : IlasmFile)CodeR*(code : INTEGER; real : REAL);
1070 VAR nam : ARRAY 64 OF CHAR;
1071 BEGIN
1072 os.Prefix(code);
1073 RTS.RealToStrInvar(real, nam);
1074 os.Tstring(nam$);
1075 os.Suffix(code);
1076 END CodeR;
1078 (* -------------------------------------------- *)
1080 PROCEDURE (os : IlasmFile)CodeLb*(code : INTEGER; i2 : Mu.Label);
1081 BEGIN
1082 os.Prefix(code);
1083 os.RefLab(i2);
1084 os.Suffix(code);
1085 END CodeLb;
1087 (* -------------------------------------------- *)
1089 PROCEDURE (os : IlasmFile)CodeStr(code : INTEGER;
1090 IN str : ARRAY OF CHAR),NEW;
1091 BEGIN
1092 os.Prefix(code);
1093 os.TTranslate(str);
1094 os.Suffix(code);
1095 END CodeStr;
1097 PROCEDURE (os : IlasmFile)CodeS*(code : INTEGER; str : INTEGER);
1098 BEGIN
1099 os.CodeStr(code, rts[str]);
1100 END CodeS;
1102 (* -------------------------------------------- *)
1104 PROCEDURE (os : IlasmFile)StaticCall*(s : INTEGER; d : INTEGER);
1105 BEGIN
1106 os.Prefix(Asm.opc_call);
1107 os.TTranslate(rts[s]);
1108 os.IAdjust(d);
1109 END StaticCall;
1111 (* -------------------------------------------- *)
1113 PROCEDURE (os : IlasmFile)Try*();
1114 VAR retT : Sy.Type;
1115 BEGIN
1116 retT := os.proc.prId.type.returnType();
1117 os.Directive(Asm.dot_try);
1118 os.OpenBrace(4);
1119 os.proc.exLb := os.newLabel();
1120 IF retT # NIL THEN os.proc.rtLc := os.proc.newLocal(retT) END;
1121 END Try;
1123 (* -------------------------------------------- *)
1125 PROCEDURE (os : IlasmFile)Catch*(proc : Id.Procs);
1126 BEGIN
1127 os.CloseBrace(4);
1128 os.CatStr(catchStr);
1129 os.CatEOL();
1130 os.OpenBrace(4);
1131 os.Adjust(1); (* allow for incoming exception reference *)
1132 os.StoreLocal(proc.except.varOrd);
1133 END Catch;
1135 (* -------------------------------------------- *)
1137 PROCEDURE (os : IlasmFile)CloseCatch*();
1138 BEGIN
1139 os.CloseBrace(4);
1140 END CloseCatch;
1142 (* -------------------------------------------- *)
1144 PROCEDURE (os : IlasmFile)CopyCall*(typ : Ty.Record);
1145 BEGIN
1146 os.Prefix(Asm.opc_call);
1147 os.Tstring(initPrefix);
1148 os.Bstring(typ.scopeNm);
1150 os.TypeTag(typ);
1152 os.IAdjust(-2);
1153 END CopyCall;
1155 (* -------------------------------------------- *)
1157 PROCEDURE (os : IlasmFile)PushStr*(IN str : ARRAY OF CHAR);
1158 (* Use target quoting conventions for the literal string *)
1159 BEGIN
1160 os.Prefix(Asm.opc_ldstr);
1161 os.CatChar(ASCII.HT);
1162 os.QuoteStr(str);
1163 os.IAdjust(1);
1164 END PushStr;
1166 (* ============================================================ *)
1168 PROCEDURE (os : IlasmFile)CallIT*(code : INTEGER;
1169 proc : Id.Procs;
1170 type : Ty.Procedure);
1171 BEGIN
1172 os.Prefix(code);
1173 os.CatChar(ASCII.HT);
1174 (*
1175 * For static calls to procedures we want
1176 * call <ret-type> <idnt>(<signature>)
1177 * for static calls to final or super methods, we need
1178 * call instance <ret-type> <idnt>(<signature>)
1179 * for calls to type-bound methods that are not final
1180 * callvirt instance <ret-type> <idnt>(<signature>)
1181 *)
1183 os.RetType(type, proc);
1184 os.PIdnt(proc);
1185 os.CatStr(type.xName);
1186 os.IAdjust(type.retN - type.argN);
1187 END CallIT;
1189 (* ============================================================ *)
1191 PROCEDURE (os : IlasmFile)CallCT*(proc : Id.Procs;
1192 type : Ty.Procedure);
1193 BEGIN
1194 os.Prefix(Asm.opc_newobj);
1195 os.Tstring(initPrefix);
1196 os.PIdnt(proc);
1197 os.CatStr(type.xName);
1198 os.IAdjust(type.retN - type.argN);
1199 END CallCT;
1201 (* ============================================================ *)
1203 PROCEDURE (os : IlasmFile)CallDelegate*(typ : Ty.Procedure);
1204 BEGIN
1205 os.Prefix(Asm.opc_callvirt);
1207 os.RetType(typ, NIL);
1208 os.Bstring(typ.tName);
1210 os.CatStr(typ.xName);
1211 os.IAdjust(typ.retN - typ.argN);
1212 END CallDelegate;
1214 (* ============================================================ *)
1216 PROCEDURE (os : IlasmFile)PutGetS*(code : INTEGER;
1217 blk : Id.BlkId;
1218 fld : Id.VarId);
1219 VAR size : INTEGER;
1220 (* Emit putstatic and getstatic for static field *)
1221 BEGIN
1222 os.Prefix(code);
1223 os.TtypeTag(fld.type);
1224 os.CatChar(ASCII.HT);
1225 IF blk.xName = NIL THEN Mu.MkBlkName(blk) END;
1226 IF fld.varNm = NIL THEN Mu.MkVarName(fld, os) END;
1227 os.CatStr(blk.scopeNm);
1228 os.CatStr(fld.clsNm);
1229 os.CatStr(cln2);
1230 os.SQuote(fld.varNm);
1231 os.Suffix(code);
1232 END PutGetS;
1234 (* -------------------------------------------- *)
1236 PROCEDURE (os : IlasmFile)PutGetFld(code : INTEGER;
1237 fTyp : Sy.Type;
1238 rTyp : Sy.Type;
1239 name : Lv.CharOpen),NEW;
1240 BEGIN
1241 os.Prefix(code);
1242 os.TtypeTag(fTyp);
1243 os.TtypeNam(rTyp);
1244 os.CatStr(cln2);
1245 os.SQuote(name);
1246 os.Suffix(code);
1247 END PutGetFld;
1249 (* -------------------------------------------- *)
1251 PROCEDURE (os : IlasmFile)GetValObj*(code : INTEGER;
1252 ptrT : Ty.Pointer);
1253 BEGIN
1254 os.PutGetFld(code, ptrT.boundTp, ptrT, vFld);
1255 END GetValObj;
1257 (* -------------------------------------------- *)
1259 PROCEDURE (os : IlasmFile)PutGetXhr*(code : INTEGER;
1260 proc : Id.Procs;
1261 locD : Id.LocId);
1262 VAR name : Lv.CharOpen;
1263 BEGIN
1264 name := Sy.getName.ChPtr(locD);
1265 os.PutGetFld(code, locD.type, proc.xhrType, name);
1266 END PutGetXhr;
1268 (* -------------------------------------------- *)
1270 PROCEDURE (os : IlasmFile)PutGetF*(code : INTEGER;
1271 fld : Id.FldId);
1272 VAR recT : Ty.Record;
1273 (* Emit putfield and getfield for record field *)
1274 BEGIN
1275 recT := fld.recTyp(Ty.Record);
1276 os.Prefix(code);
1277 os.TtypeTag(fld.type);
1278 os.CatChar(ASCII.HT);
1279 IF fld.fldNm = NIL THEN fld.fldNm := Sy.getName.ChPtr(fld) END;
1280 (*
1281 * Note the difference here. JVM needs the
1282 * static type of the variable, VOS wants
1283 * the name of the record with the field.
1284 *)
1285 os.CatStr(recT.scopeNm);
1286 os.CatStr(cln2);
1287 os.SQuote(fld.fldNm);
1288 os.Suffix(code);
1289 END PutGetF;
1291 (* ============================================================ *)
1292 (* ============================================================ *)
1294 PROCEDURE (os : IlasmFile)MkNewRecord*(typ : Ty.Record);
1295 VAR name : Lv.CharOpen;
1296 BEGIN
1297 (*
1299 *)
1300 IF typ.xName = NIL THEN Mu.MkRecName(typ, os) END;
1301 IF Sy.clsTp IN typ.xAttr THEN
1302 name := typ.scopeNm;
1303 ELSE
1304 name := Mu.boxedName(typ, os);
1305 END;
1306 os.Prefix(Asm.opc_newobj);
1307 os.Tstring(initPrefix);
1308 os.Bstring(name);
1309 os.CatStr(cln2);
1310 os.CatStr(initSuffix);
1311 os.IAdjust(1);
1312 END MkNewRecord;
1314 (* ============================================================ *)
1315 (* ============================================================ *)
1317 PROCEDURE (os : IlasmFile)MkNewProcVal*(p : Sy.Idnt; t : Sy.Type);
1318 VAR name : Lv.CharOpen;
1319 proc : Id.Procs;
1320 type : Ty.Procedure;
1321 code : INTEGER;
1322 BEGIN
1323 proc := p(Id.Procs);
1324 type := t(Ty.Procedure);
1325 (*
1327 *)
1334 ELSE
1337 ELSE
1340 (*
1341 * If this will be a virtual method call, then we
1342 * must duplicate the receiver, since the call of
1343 * ldvirtftn uses up one copy.
1344 *)
1353 (*
1354 * We need "newobj instance void <name>::.ctor(...)"
1355 *)
1364 (* ============================================================ *)
1369 BEGIN
1370 (*
1371 * Get the procedure type, if any ...
1372 *)
1375 ELSE
1384 ELSE
1392 (*
1393 * Now we begin to initialize the supertype;
1394 *)
1399 (* ============================================================ *)
1405 BEGIN
1406 (*
1407 * Get the procedure type, if any ...
1408 *)
1412 ELSE
1426 ELSE
1429 ELSE
1435 (* ============================================================ *)
1438 BEGIN
1448 (* ============================================================ *)
1451 BEGIN
1455 (* FIX FOR BOXED CLASS COPY *)
1467 (* ============================================================ *)
1470 BEGIN
1476 (* ============================================================ *)
1482 BEGIN
1496 (* ============================================================ *)
1499 BEGIN
1504 ELSE
1513 (*
1514 * Save the command-line arguments to the RTS.
1515 *)
1520 (* ============================================================ *)
1523 BEGIN
1533 (* ============================================================ *)
1540 BEGIN
1550 (*
1551 * Emit the no-arg constructor
1552 *)
1559 (*
1560 * Copies of value classes are always done inline.
1561 *)
1564 (* ============================================================ *)
1567 BEGIN
1573 (* ------------------------------------------------------------ *)
1578 (* ------------------------------------------------------------ *)
1583 (* ------------------------------------------------------------ *)
1588 (* ============================================================ *)
1591 BEGIN
1601 (* ============================================================ *)
1605 BEGIN
1620 (* ============================================================ *)
1621 (* Start of Procedure Variable and Event Stuff *)
1622 (* ============================================================ *)
1626 (* ------------------------------------------------- *)
1628 BEGIN
1636 (* ------------------------------------------------- *)
1638 BEGIN
1661 (* ------------------------------------------------- *)
1663 BEGIN
1680 (* ------------------------------------------------- *)
1681 BEGIN
1684 (*
1685 * Emit the "add_*" method
1686 *)
1688 (*
1689 * Emit the "remove_*" method
1690 *)
1692 (*
1693 * Emit the .event declaration"
1694 *)
1706 (* ============================================================ *)
1710 BEGIN
1725 (* ============================================================ *)
1726 (* ============================================================ *)
1733 (* --------------------------------------------------------- *)
1737 BEGIN
1742 (* --------------------------------------------------------- *)
1747 BEGIN
1754 (* --------------------------------------------------------- *)
1755 BEGIN
1757 (*
1758 * <push handle> // ... already done
1759 * <push receiver (or nil)> // ... already done
1760 * <make new proc value> // ... still to do
1761 * call instance void A.B::add_fld(class tyName)
1762 *)
1768 (*
1769 * <push receiver (or nil)> // ... already done
1770 * <make new proc value> // ... still to do
1771 * call void A.B::add_fld(class tyName)
1772 *)
1780 (*
1781 * <save receiver>
1782 * ldloc 'local'
1783 * <restore receiver>
1784 * <make new proc value> // ... still to do
1785 * call class D D::Combine(class D, class D)
1786 *)
1797 (* ============================================================ *)
1798 (* ============================================================ *)
1802 BEGIN
1807 (*
1808 * From Beta-2, all delegates derive from MulticastDelegate
1809 *)
1829 (* ============================================================ *)
1830 (* End of Procedure Variable and Event Stuff *)
1831 (* ============================================================ *)
1834 BEGIN
1841 (* ============================================================ *)
1844 BEGIN
1853 (* ============================================================ *)
1856 BEGIN
1870 (* ============================================================ *)
1873 (** Declare the local of this method. *)
1878 BEGIN
1880 (* if dMax < 8, leave maxstack as default *)
1892 ELSE
1923 (* ============================================================ *)
1926 BEGIN
1927 (*
1928 * ldtoken <Type>
1929 * call class [mscorlib]System.Type
1930 * [mscorlib]System.Type::GetTypeFromHandle(
1931 * value class [mscorlib]System.RuntimeTypeHandle)
1932 *)
1942 (* ============================================================ *)
1943 (* ============================================================ *)
1944 BEGIN
1974 (* ============================================================ *)
1998 (* ============================================================ *)
1999 (* ============================================================ *)