1 (* ==================================================================== *)
3 (* State Module for the Gardens Point Component Pascal Compiler. *)
4 (* Copyright (c) John Gough 1999, 2000. *)
6 (* Note that since this module is likely to be imported by most other *)
7 (* modules, it is important to ensure that it does not import others, *)
8 (* to avoid import cycles. *)
10 (* ==================================================================== *)
28 CONST prefix
= "#gpcp: ";
35 (* ==================================================================== *)
36 (* State Variables of this compilation *)
37 (* ==================================================================== *)
40 ntvObj
* : Symbols
.Type
; (* native Object type *)
41 ntvStr
* : Symbols
.Type
; (* native String type *)
42 ntvExc
* : Symbols
.Type
; (* native Exceptions type *)
43 ntvTyp
* : Symbols
.Type
; (* native System.Type type *)
44 ntvEvt
* : Symbols
.Type
; (* native MulticastDelegate *)
45 rtsXHR
* : Symbols
.Type
; (* native XHR type descriptor *)
46 ntvVal
* : Symbols
.Type
; (* native ValueType type *)
48 objId
* : Symbols
.Idnt
;
49 strId
* : Symbols
.Idnt
;
50 excId
* : Symbols
.Idnt
;
51 clsId
* : Symbols
.Idnt
;
52 xhrId
* : IdDesc
.FldId
; (* descriptor of RTS.XHR.prev *)
53 rtsBlk
* : IdDesc
.BlkId
;
54 prgArg
* : IdDesc
.BlkId
;
55 argLst
* : IdDesc
.VarId
; (* descriptor of RTS.argList *)
57 srcBkt
* : INTEGER; (* hashtable bucket of "src" *)
58 corBkt
* : INTEGER; (* bucket of "mscorlib_System" *)
60 fltInf
* : IdDesc
.VarId
; (* descriptor of RTS.fltPosInf. *)
61 dblInf
* : IdDesc
.VarId
; (* descriptor of RTS.dblPosInf. *)
62 fltNInf
* : IdDesc
.VarId
; (* descriptor of RTS.fltNegInf. *)
63 dblNInf
* : IdDesc
.VarId
; (* descriptor of RTS.dblNegInf. *)
66 modNam
* : FileNames
.NameString
; (* name of the _MODULE_ *)
67 basNam
-, (* base name of source _FILE_ *)
68 srcNam
-, (* name of the source file *)
69 lstNam
- : FileNames
.NameString
; (* name of the listing file *)
71 target
- : ARRAY 6 OF CHAR;
72 emitter
- : ClassMaker
.ClassEmitter
;
74 cpSymX
-, (* User supplied CPSYM name *)
75 binDir
-, (* PE-file directory .NET only *)
76 symDir
- : FileNames
.NameString
; (* Symbol file directory *)
105 thisMod
- : IdDesc
.BlkId
; (* Desc. of compiling module. *)
106 sysMod
- : IdDesc
.BlkId
; (* Desc. of SYSTEM module. *)
107 sysLib
- : IdDesc
.BlkId
; (* mscorlib OR java.lang BlkId *)
109 impSeq
* : Symbols
.ScpSeq
;
123 VAR outNam
* : POINTER TO ARRAY OF CHAR;
126 expectedNet
: BOOLEAN; (* A .NET specific option was parsed *)
127 expectedJvm
: BOOLEAN; (* A JVM specific option was parsed *)
128 expectedLlvm
: BOOLEAN; (* An LLVM specific option was parsed *)
130 (* ==================================================================== *)
132 (* ==================================================================== *)
134 PROCEDURE SetSysLib
*(lib
: IdDesc
.BlkId
);
139 PROCEDURE SetEmitter
*(maker
: ClassMaker
.ClassEmitter
);
144 PROCEDURE ImportObjectFeatures
*();
146 emitter
.ObjectFeatures();
147 END ImportObjectFeatures
;
149 PROCEDURE SetQuiet
*();
151 CPascalErrors
.nowarn
:= TRUE
;
154 PROCEDURE RestoreQuiet
*();
156 CPascalErrors
.nowarn
:= ~warning
;
159 PROCEDURE targetIsNET
*() : BOOLEAN;
161 RETURN target
= "net";
164 PROCEDURE targetIsJVM
*() : BOOLEAN;
166 RETURN target
= "jvm";
169 PROCEDURE targetIsLLVM
*() : BOOLEAN;
171 RETURN target
= "llvm";
174 PROCEDURE Message
*(IN mss
: ARRAY OF CHAR);
176 Console
.WriteString(prefix
);
177 Console
.WriteString(mss
);
181 PROCEDURE PrintLn
*(IN mss
: ARRAY OF CHAR);
183 Console
.WriteString(mss
);
187 PROCEDURE ErrMesg
*(IN mss
: ARRAY OF CHAR);
189 Console
.WriteString(prefix
);
190 Error
.WriteString(mss
);
194 PROCEDURE Abort
*(IN mss
: ARRAY OF CHAR);
196 ErrMesg(mss
); ASSERT(FALSE
);
199 PROCEDURE isForeign
*() : BOOLEAN;
202 (Symbols
.rtsMd
IN thisMod
.xAttr
) OR
203 (Symbols
.frnMd
IN thisMod
.xAttr
);
206 PROCEDURE TimeMsg
*(IN mss
: ARRAY OF CHAR; tim
: LONGINT);
208 IF (tim
< 0) OR (tim
>= totalS
) THEN tim
:= 0 END;
209 Console
.WriteString(prefix
);
210 Console
.WriteString(mss
);
211 Console
.WriteInt(SHORT(tim
), 5);
212 Console
.WriteString(millis
);
216 (* ==================================================================== *)
220 PrintLn("gardens point component pascal: " + GPCPcopyright
.verStr
);
221 Message("Usage from the command line ...");
222 IF RTS
.defaultTarget
= "net" THEN
223 PrintLn(" $ gpcp [cp-options] file {file}");
224 PrintLn("# CP Options ...");
225 PrintLn(" /bindir=XXX ==> Place binary files in directory XXX");
226 PrintLn(" /copyright ==> Display copyright notice");
227 PrintLn(" /cpsym=XXX ==> Use environ. variable XXX instead of CPSYM");
228 PrintLn(" /debug ==> Generate debugging information (default)");
229 PrintLn(" /nodebug ==> Give up debugging for maximum speed");
230 PrintLn(" /dostats ==> Give a statistical summary");
231 PrintLn(" /extras ==> Enable experimental compiler features");
232 PrintLn(" /help ==> Write out this usage message");
233 PrintLn(" /hsize=NNN ==> Set hashtable size >= NNN (0 .. 65000)");
234 PrintLn(" /ilasm ==> Force compilation via ILASM");
235 PrintLn(" /list ==> (default) Create *.lst file if errors");
236 PrintLn(" /list+ ==> Unconditionally create *.lst file");
237 PrintLn(" /list- ==> Don't create error *.lst file");
238 PrintLn(" /noasm ==> Don't create asm (or object) files");
239 PrintLn(" /nocode ==> Don't create any object files");
240 PrintLn(" /nocheck ==> Don't perform arithmetic overflow checks");
241 PrintLn(" /nosym ==> Don't create *.sym (or asm or object) files");
242 PrintLn(" /perwapi ==> Force compilation via PERWAPI");
243 PrintLn(" /quiet ==> Compile silently if possible");
244 PrintLn(" /strict ==> Disallow non-standard constructs");
245 PrintLn(" /special ==> Compile dummy symbol file");
246 PrintLn(" /symdir=XXX ==> Place symbol files in directory XXX");
247 PrintLn(" /target=XXX ==> Emit (jvm|net|llvm) assembly");
248 PrintLn(" /unsafe ==> Allow unsafe code generation");
249 PrintLn(" /vX.X ==> (v1.0 | v1.1 | v2.0) CLR target version");
250 PrintLn(" /verbose ==> Emit verbose diagnostics");
251 PrintLn(" /version ==> Write out version number");
252 PrintLn(" /vserror ==> Print error messages in Visual Studio format");
253 PrintLn(" /warn- ==> Don't emit warnings");
254 PrintLn(" /nowarn ==> Don't emit warnings");
255 PrintLn(" /whidbey ==> Target code for Whidbey Beta release");
256 PrintLn(" /xmlerror ==> Print error messages in XML format");
257 PrintLn(' Unix
-style options
: "-option" are recognized also'
);
259 IF RTS
.defaultTarget
= "jvm" THEN
260 PrintLn(" $ cprun gpcp [cp-options] file {file}, OR");
261 PrintLn(" $ java [java-options] CP.gpcp.gpcp [cp-options] file {file}");
262 ELSIF RTS
.defaultTarget
= "llvm" THEN
263 PrintLn(" $ gpcp [cp-options] file {file}");
265 PrintLn("# CP Options ...");
266 PrintLn(" -clsdir=XXX ==> Set class tree root in directory XXX");
267 PrintLn(" -copyright ==> Display copyright notice");
268 PrintLn(" -cpsym=XXX ==> Use environ. variable XXX instead of CPSYM");
269 PrintLn(" -dostats ==> Give a statistical summary");
270 PrintLn(" -extras ==> Enable experimental compiler features");
271 PrintLn(" -help ==> Write out this usage message");
272 PrintLn(" -hsize=NNN ==> Set hashtable size >= NNN (0 .. 65000)");
273 PrintLn(" -jasmin ==> Ceate asm files and run Jasmin");
274 PrintLn(" -list ==> (default) Create *.lst file if errors");
275 PrintLn(" -list+ ==> Unconditionally create *.lst file");
276 PrintLn(" -list- ==> Don't create error *.lst file");
277 PrintLn(" -nocode ==> Don't create any object files");
278 PrintLn(" -noasm ==> Don't create asm (or object) files");
279 PrintLn(" -nosym ==> Don't create *.sym (or asm or object) files");
280 PrintLn(" -quiet ==> Compile silently if possible");
281 PrintLn(" -special ==> Compile dummy symbol file");
282 PrintLn(" -strict ==> Disallow non-standard constructs");
283 PrintLn(" -symdir=XXX ==> Place symbol files in directory XXX");
284 PrintLn(" -target=XXX ==> Emit (jvm|net|llvm) assembly");
285 PrintLn(" -verbose ==> Emit verbose diagnostics");
286 PrintLn(" -version ==> Write out version number");
287 PrintLn(" -warn- ==> Don't emit warnings");
288 PrintLn(" -nowarn ==> Don't emit warnings");
289 PrintLn(" -xmlerror ==> Print error messages in XML format");
290 IF RTS
.defaultTarget
= "jvm" THEN
291 PrintLn("# Java Options ...");
292 PrintLn(" -D<name>=<value> pass <value> to JRE as system property <name>");
293 PrintLn(" -DCPSYM=$CPSYM pass value of CPSYM environment variable to JRE");
296 Message("This program comes with NO WARRANTY");
297 Message("Read source/GPCPcopyright for license details");
300 (* ==================================================================== *)
302 (* ==================================================================== *)
304 PROCEDURE ParseOption
*(IN opt
: ARRAY OF CHAR);
305 CONST MaxTargetLength
= 4;
306 VAR copy
: ARRAY 16 OF CHAR;
307 trgt
: ARRAY MaxTargetLength
+ 1 OF CHAR;
309 (* ----------------------------------------- *)
310 PROCEDURE Unknown(IN str
: ARRAY OF CHAR);
312 Message('Unknown option
"' + str + '"'
);
315 (* ----------------------------------------- *)
317 BEGIN Message('hsize must be integer in range
0 .. 65000'
) END BadSize
;
318 (* ----------------------------------------- *)
319 PROCEDURE ParseSize(IN opt
: ARRAY OF CHAR);
326 WHILE opt
[ix
] # 0X
DO
328 IF (ch
>= '
0'
) & (ch
<= '
9'
) THEN
329 nm
:= nm
* 10 + ORD(ch
) - ORD('
0'
);
330 IF nm
> 65521 THEN BadSize
; hashSize
:= nm
; RETURN END;
332 BadSize
; doHelp
:= TRUE
; hashSize
:= nm
; RETURN;
338 (* ----------------------------------------- *)
339 PROCEDURE GetSuffix(preLen
: INTEGER;
340 IN opt
: ARRAY OF CHAR;
341 OUT dir
: ARRAY OF CHAR);
347 WHILE (chr
# 0X
) & (idx
< LEN(opt
)) DO
348 dir
[idx
- preLen
] := chr
;
349 INC(idx
); chr
:= opt
[idx
];
352 (* ----------------------------------------- *)
353 PROCEDURE RaiseSuffix(preLen
: INTEGER;
355 IN opt
: ARRAY OF CHAR;
356 OUT dir
: ARRAY OF CHAR);
362 chr
:= opt
[idx
+ preLen
];
363 dir
[idx
] := CAP(chr
);
365 UNTIL (chr
= 0X
) OR (idx
>= outLen
) OR ((idx
+ preLen
) > LEN(opt
));
369 (* ----------------------------------------- *)
370 PROCEDURE StartsWith(str
: ARRAY OF CHAR; IN pat
: ARRAY OF CHAR) : BOOLEAN;
372 str
[LEN(pat$
)] := 0X
;
375 (* ----------------------------------------- *)
378 WHILE (indx
< 16) & (indx
< LEN(opt
)) DO
379 copy
[indx
-1] := opt
[indx
]; INC(indx
);
385 IF StartsWith(copy
, "bindir=") THEN
386 GetSuffix(LEN("/bindir="), opt
, binDir
);
389 Message("bin directory set to <" + binDir
+">");
395 IF copy
= "copyright" THEN
397 ELSIF StartsWith(copy
, "clsdir=") THEN
398 GetSuffix(LEN("/clsdir="), opt
, binDir
);
401 Message("output class tree rooted at <" + binDir
+">");
403 ELSIF StartsWith(copy
, "cpsym=") THEN
404 GetSuffix(LEN("/cpsym="), opt
, cpSymX
);
406 Message("using %" + cpSymX
+"% as symbol file path");
412 IF copy
= "dostats" THEN
414 ELSIF copy
= "debug" THEN
420 |
"e" : IF copy
= "extras" THEN extras
:= TRUE
ELSE Unknown(opt
) END;
423 IF copy
= "help" THEN
425 ELSIF copy
= "hsize=" THEN
431 IF copy
= "ilasm" THEN
438 IF copy
= "jasmin" THEN
446 IF copy
= "list-" THEN
447 listLevel
:= CPascalS
.listNever
;
448 ELSIF copy
= "list+" THEN
449 listLevel
:= CPascalS
.listAlways
;
450 ELSIF copy
= "list" THEN
451 listLevel
:= CPascalS
.listErrOnly
;
452 ELSIF copy
= "legacy" THEN
458 IF copy
= "nosym" THEN
462 ELSIF copy
= "noasm" THEN
465 ELSIF copy
= "nocode" THEN
467 ELSIF copy
= "nowarn" THEN
469 CPascalErrors
.nowarn
:= TRUE
;
470 ELSIF copy
= "nocheck" THEN
473 ELSIF copy
= "nodebug" THEN
480 IF copy
= "perwapi" THEN
481 forcePerwapi
:= TRUE
;
487 IF copy
= "quiet" THEN
494 IF copy
= "special" THEN
498 ELSIF copy
= "strict" THEN
500 ELSIF StartsWith(copy
, "symdir=") THEN
501 GetSuffix(LEN("/symdir="), opt
, symDir
);
503 Message("sym directory set to <" + symDir
+">");
509 IF StartsWith(copy
, "target=") THEN
510 RaiseSuffix(LEN("/target="), MaxTargetLength
, opt
, trgt
);
512 IF RTS
.defaultTarget
= "jvm" THEN
513 Message("JVM is default target for this build");
516 ELSIF (trgt
= "NET") OR (trgt
= "CLR") THEN
517 IF RTS
.defaultTarget
= "net" THEN
518 Message("NET is default target for this build");
521 ELSIF trgt
= "LLVM" THEN
524 Message('Unknown target
, using
"target=' +
525 RTS.defaultTarget + '"'
);
531 IF copy
= "unsafe" THEN
538 IF copy
= "version" THEN
540 ELSIF copy
= "verbose" THEN
545 CPascalErrors
.prompt
:= TRUE
;
546 ELSIF copy
= "vserror" THEN
547 CPascalErrors
.forVisualStudio
:= TRUE
;
549 ELSIF copy
= "v1.0" THEN
552 ELSIF copy
= "v1.1" THEN
555 ELSIF copy
= "v2.0" THEN
562 IF copy
= "warn-" THEN
564 CPascalErrors
.nowarn
:= TRUE
;
565 ELSIF copy
= "whidbey" THEN
572 IF copy
= "xmlerror" THEN
573 CPascalErrors
.xmlErrors
:= TRUE
;
580 IF doVersion
& ~doneVersion
THEN
581 Message(target
+ GPCPcopyright
.verStr
);
584 IF doHelp
& ~doneHelp
THEN Usage
; doneHelp
:= TRUE
END;
587 (* ==================================================================== *)
589 PROCEDURE CheckOptionsOK
*;
591 IF target
= "net" THEN
592 IF expectedJvm
THEN Message
593 ("WARNING - a JVM-specific option was specified for .NET target");
594 expectedJvm
:= FALSE
;
596 IF expectedLlvm
THEN Message
597 ("WARNING - an LLVM-specific option was specified for .NET target");
598 expectedLlvm
:= FALSE
;
600 ELSIF target
= "jvm" THEN
601 IF expectedNet
THEN Message
602 ("WARNING - a .NET-specific option was specified for JVM target");
603 expectedNet
:= FALSE
;
605 IF expectedLlvm
THEN Message
606 ("WARNING - an LLVM-specific option was specified for JVM target");
607 expectedLlvm
:= FALSE
;
609 ELSIF target
= "llvm" THEN
610 IF expectedJvm
THEN Message
611 ("WARNING - a JVM-specific option was specified for LLVM target");
612 expectedJvm
:= FALSE
;
614 IF expectedNet
THEN Message
615 ("WARNING - a .NET-specific option was specified for LLVM target");
616 expectedNet
:= FALSE
;
620 * If debug is set, for this version, ILASM is used unless /perwapi is explicit
621 * If debug is clar, for this versin, PERWAPI is used unless /ilasm is explicit
623 IF forceIlasm
THEN doIlasm
:= TRUE
;
624 ELSIF forcePerwapi
THEN doIlasm
:= FALSE
;
625 ELSE doIlasm
:= debug
;
629 (* ==================================================================== *)
631 PROCEDURE CreateThisMod
*();
634 thisMod
.SetKind(IdDesc
.modId
);
635 thisMod
.ovfChk
:= ovfCheck
;
638 PROCEDURE InitCompState
*(IN nam
: ARRAY OF CHAR);
640 IF verbose
THEN Message("opened local file <" + nam
+ ">") END;
641 GPText
.Assign(nam
, srcNam
);
642 CPascalErrors
.SetSrcNam(nam
);
643 FileNames
.StripExt(nam
, basNam
);
644 FileNames
.AppendExt(basNam
, "lst", lstNam
);
647 xhrId
:= IdDesc
.newFldId();
648 xhrId
.hash
:= NameHash
.enterStr("prev");
649 srcBkt
:= NameHash
.enterStr("src");
650 corBkt
:= NameHash
.enterStr("mscorlib_System");
653 sysMod
.SetKind(IdDesc
.impId
);
656 (* ==================================================================== *)
659 VAR str1
: ARRAY 8 OF CHAR;
660 str2
: ARRAY 8 OF CHAR;
662 Message(target
+ GPCPcopyright
.verStr
);
663 GPText
.IntToStr(CPascalS
.line
, str1
);
664 Message(str1
+ " source lines");
665 GPText
.IntToStr(impMax
, str1
);
666 Message("import recursion depth " + str1
);
667 GPText
.IntToStr(NameHash
.size
, str2
);
668 GPText
.IntToStr(NameHash
.entries
, str1
);
669 Message(str1
+ " entries in hashtable of size " + str2
);
670 TimeMsg("import time ", import2
- import1
);
671 TimeMsg("source time ", parseS
- totalS
);
672 TimeMsg("parse time ", parseE
- parseS
- import2
+ import1
);
673 TimeMsg("analysis time ", attrib
- parseE
);
674 TimeMsg("symWrite time ", symEnd
- attrib
);
675 TimeMsg("asmWrite time ", asmEnd
- symEnd
);
676 TimeMsg("assemble time ", totalE
- asmEnd
);
677 TimeMsg("total time ", totalE
- totalS
);
680 (* ==================================================================== *)
682 PROCEDURE InitOptions
*;
687 doHelp
:= FALSE
; doneHelp
:= FALSE
;
688 doVersion
:= FALSE
; doneVersion
:= FALSE
;
691 netRel
:= netV2_0
; (* probably should be from RTS? *)
699 forcePerwapi
:= FALSE
;
706 listLevel
:= CPascalS
.listErrOnly
;
707 hashSize
:= 5000; (* gets default hash size *)
708 expectedNet
:= FALSE
;
709 expectedJvm
:= FALSE
;
710 expectedLlvm
:= FALSE
;
714 (* ==================================================================== *)
716 GPText
.Assign(RTS
.defaultTarget
, target
);
718 (* ==================================================================== *)