Просмотр исходного кода

fix: make Lower V3-legal and stop the fixpoint masking errors

V3 (unlike gm2) has no whole-module pass: a call to a procedure declared
later in the same module is reported as `invalid call` and codegen drops
the call. Lower.mod's mutually recursive walkers (CanExpr, CanDecls,
CanProc, IsBuiltin, LowerExpr, LowerStmt, LowerDecls) were called before
their declarations, so the compiler session reported 45 `invalid call`
errors in Lower.mod and emitted degraded code for the whole Lower module.
Declare them in Lower.def (definition-visible throughout the impl) since
gm2's link pass rejects FORWARD.

Also fix SymTab.FormalOk so two open-array formals are compatible when
their element types match: each `ARRAY OF T` declaration allocates a
fresh descriptor, so a DEFINITION/IMPLEMENTATION pair never shares the
type index and SameType rejected it (e.g. LowerSession's
`units: ARRAY OF AST.Node`).

Remove the debug ASTDUMP from M2.atg and gate M2make on "Parsed
correctly" instead of "Parsed": the ASTDUMP printed the string literal
'Parsed correctly', which satisfied the check while the compiler was
actually reporting "Incorrect source". The fixpoint had been passing
with a broken compiler session.

The compiler session now parses with zero errors; suite 204/204 and
fixpoint byte-identical (3,409,871 bytes).
Eric Streit 5 дней назад
Родитель
Сommit
a3ef897134

+ 14 - 1
compiler/src/Lower.def

@@ -11,13 +11,26 @@ DEFINITION MODULE Lower;
    the tables below while the scope is open, so the walk can resolve names
    the tables below while the scope is open, so the walk can resolve names
    after SymTab has popped their scopes. *)
    after SymTab has popped their scopes. *)
 
 
-IMPORT AST, SymTab;
+IMPORT AST, SymTab, QbeGen;
 
 
 PROCEDURE CanLower (unit: AST.Node): BOOLEAN;
 PROCEDURE CanLower (unit: AST.Node): BOOLEAN;
 PROCEDURE LowerUnit (unit: AST.Node);
 PROCEDURE LowerUnit (unit: AST.Node);
 PROCEDURE LowerSession (units: ARRAY OF AST.Node; n: CARDINAL;
 PROCEDURE LowerSession (units: ARRAY OF AST.Node; n: CARDINAL;
                         progName: ARRAY OF CHAR);
                         progName: ARRAY OF CHAR);
 
 
+(* The expression/statement/declaration walkers are mutually recursive.
+   gm2's link pass rejects FORWARD and V3 has no whole-module pass, so
+   they are declared here (definition-visible throughout the
+   implementation) instead of being forward-declared. *)
+PROCEDURE CanExpr (n: AST.Node): BOOLEAN;
+PROCEDURE CanDecls (seq: AST.Node): BOOLEAN;
+PROCEDURE CanProc (proc: AST.Node): BOOLEAN;
+PROCEDURE IsBuiltin (nm: ARRAY OF CHAR): BOOLEAN;
+PROCEDURE LowerExpr (n: AST.Node; VAR t: SymTab.TypeIndex;
+                     VAR q: QbeGen.QVal);
+PROCEDURE LowerStmt (seq: AST.Node);
+PROCEDURE LowerDecls (seq: AST.Node);
+
 PROCEDURE Reset;
 PROCEDURE Reset;
 PROCEDURE NoteVar (name: ARRAY OF CHAR; kind: INTEGER; t: SymTab.TypeIndex);
 PROCEDURE NoteVar (name: ARRAY OF CHAR; kind: INTEGER; t: SymTab.TypeIndex);
 PROCEDURE ScopeEnter;
 PROCEDURE ScopeEnter;

+ 3 - 2
compiler/src/Lower.mod

@@ -1,7 +1,8 @@
 IMPLEMENTATION MODULE Lower;
 IMPLEMENTATION MODULE Lower;
 (* Scalar/boolean/control-flow walk (L0-L2): see Lower.def and
 (* Scalar/boolean/control-flow walk (L0-L2): see Lower.def and
-   docs/plan-lower.md.  No FORWARD declarations: sequence iteration and
-   statement dispatch are merged into CanStmt / LowerStmt. *)
+   docs/plan-lower.md.  The mutually recursive walkers are declared in
+   Lower.def (gm2's link pass rejects FORWARD, V3 has no whole-module
+   pass, so a definition-visible declaration breaks the cycle). *)
 
 
 IMPORT AST, SymTab, QbeGen;
 IMPORT AST, SymTab, QbeGen;
 
 

+ 1 - 1
compiler/src/M2.atg

@@ -246,7 +246,7 @@ PRODUCTIONS
     = (. twoPhase := TRUE; astCur := AST.NoNode; astStmt := AST.NoNode; astDecl := AST.NoNode; astImp := AST.NoNode; astImpTail := AST.NoNode;
     = (. twoPhase := TRUE; astCur := AST.NoNode; astStmt := AST.NoNode; astDecl := AST.NoNode; astImp := AST.NoNode; astImpTail := AST.NoNode;
                                            astImp := AST.NoNode;
                                            astImp := AST.NoNode;
                                            astImpTail := AST.NoNode; .)
                                            astImpTail := AST.NoNode; .)
-      Unit "." (. FileIO.WriteString(FileIO.StdOut, "ASTDUMP:"); FileIO.WriteLn(FileIO.StdOut); AST.Dump(astUnit, 0); .) .
+      Unit "." .
   (* Units: program modules compile fully; DEFINITION and
   (* Units: program modules compile fully; DEFINITION and
      IMPLEMENTATION modules parse + check now but lower in step 4
      IMPLEMENTATION modules parse + check now but lower in step 4
      (each ends with one 230); same for nested local modules. *)
      (each ends with one 230); same for nested local modules. *)

+ 2 - 2
compiler/src/M2.lst

@@ -264,7 +264,7 @@ Listing:
   246      = (. twoPhase := TRUE; astCur := AST.NoNode; astStmt := AST.NoNode; astDecl := AST.NoNode; astImp := AST.NoNode; astImpTail := AST.NoNode;
   246      = (. twoPhase := TRUE; astCur := AST.NoNode; astStmt := AST.NoNode; astDecl := AST.NoNode; astImp := AST.NoNode; astImpTail := AST.NoNode;
   247                                             astImp := AST.NoNode;
   247                                             astImp := AST.NoNode;
   248                                             astImpTail := AST.NoNode; .)
   248                                             astImpTail := AST.NoNode; .)
-  249        Unit "." (. FileIO.WriteString(FileIO.StdOut, "ASTDUMP:"); FileIO.WriteLn(FileIO.StdOut); AST.Dump(astUnit, 0); .) .
+  249        Unit "." .
   250    (* Units: program modules compile fully; DEFINITION and
   250    (* Units: program modules compile fully; DEFINITION and
   251       IMPLEMENTATION modules parse + check now but lower in step 4
   251       IMPLEMENTATION modules parse + check now but lower in step 4
   252       (each ends with one 230); same for nested local modules. *)
   252       (each ends with one 230); same for nested local modules. *)
@@ -3857,7 +3857,7 @@ Statistics:
   nr of non-terminals:    85 (limit   210)
   nr of non-terminals:    85 (limit   210)
   nr of pragmas:           0 (limit   396)
   nr of pragmas:           0 (limit   396)
   nr of symbolnodes:     189 (limit   500)
   nr of symbolnodes:     189 (limit   500)
-  nr of graphnodes:     1111 (limit  1500)
+  nr of graphnodes:     1110 (limit  1500)
   nr of conditionsets:    11 (limit   100)
   nr of conditionsets:    11 (limit   100)
   nr of charactersets:    16 (limit   250)
   nr of charactersets:    16 (limit   250)
 
 

+ 7 - 0
compiler/src/SymTab.mod

@@ -376,6 +376,13 @@ PROCEDURE FormalOk (a, b: TypeIndex): BOOLEAN;
     END;
     END;
     IF SameType(a, b) THEN RETURN TRUE END;
     IF SameType(a, b) THEN RETURN TRUE END;
     IF IsIntFamily(a) AND IsIntFamily(b) THEN RETURN TRUE END;
     IF IsIntFamily(a) AND IsIntFamily(b) THEN RETURN TRUE END;
+    (* Open-array formals are structurally compatible when their element
+       types match: each `ARRAY OF T` declaration allocates a fresh
+       descriptor, so a DEFINITION/IMPLEMENTATION pair never shares the
+       type index and SameType would otherwise reject it. *)
+    IF IsOpenArray(a) AND IsOpenArray(b) THEN
+      RETURN SameType(ArrayElem(a), ArrayElem(b))
+    END;
     RETURN StrCompat(a, b)
     RETURN StrCompat(a, b)
   END FormalOk;
   END FormalOk;
 
 

+ 1 - 1
tools/m2make/M2make.mod

@@ -797,7 +797,7 @@ BEGIN
     IF Len(tmpP) > 0 THEN AppendTok(cmd, tmpP) END;
     IF Len(tmpP) > 0 THEN AppendTok(cmd, tmpP) END;
     INC(k)
     INC(k)
   END;
   END;
-  AppendSeg(cmd, " 2>&1 | tee m2make.log | grep -q Parsed");
+  AppendSeg(cmd, " 2>&1 | tee m2make.log | grep -q 'Parsed correctly'");
   AppendSeg(cmd, " && qbe -o gen_ssa/");
   AppendSeg(cmd, " && qbe -o gen_ssa/");
   AppendSeg(cmd, progName);
   AppendSeg(cmd, progName);
   AppendSeg(cmd, ".s gen_ssa/");
   AppendSeg(cmd, ".s gen_ssa/");

+ 1 - 1
tools/m2make/build_m2.sh

@@ -36,7 +36,7 @@ else
       "../$SYS/SysShim.def" "../$SYS/SysShim.mod" \
       "../$SYS/SysShim.def" "../$SYS/SysShim.mod" \
       "../$SYS/FileIO.def" "../$SYS/FileIO.mod" \
       "../$SYS/FileIO.def" "../$SYS/FileIO.mod" \
       M2makeOS.def M2makeOS.mod M2make.mod \
       M2makeOS.def M2makeOS.mod M2make.mod \
-      2>&1 | tee m2.log | grep -q Parsed || exit 1
+      2>&1 | tee m2.log | grep -q "Parsed correctly" || exit 1
   echo "=== Assembling and linking ==="
   echo "=== Assembling and linking ==="
   qbe -o gen_ssa/M2make.s gen_ssa/M2make.ssa || exit 1
   qbe -o gen_ssa/M2make.s gen_ssa/M2make.ssa || exit 1
   cc gen_ssa/M2make.s "../$SYS/shim.c" m2make_os.c \
   cc gen_ssa/M2make.s "../$SYS/shim.c" m2make_os.c \