|
|
@@ -16,6 +16,7 @@ CONST
|
|
|
MaxSym = 8192; (* whole-session: >4096 vars/consts/params *)
|
|
|
MaxName = 63;
|
|
|
MaxProc = 2048; (* whole-session: the compiler declares >1200 procs *)
|
|
|
+ MaxImp = 512; (* per-unit imports *)
|
|
|
MaxPar = 32;
|
|
|
HashSize = 16384; (* power of two > MaxSym, MaxProc: open addressing *)
|
|
|
|
|
|
@@ -41,6 +42,12 @@ VAR
|
|
|
lookups over thousands of entries), so FindSym/FindProc hash. *)
|
|
|
symHash : ARRAY [0 .. HashSize - 1] OF INTEGER;
|
|
|
procHash : ARRAY [0 .. HashSize - 1] OF INTEGER;
|
|
|
+ (* Per-unit imports (FROM M IMPORT P): the exact proc entry for a
|
|
|
+ name, so an unqualified call resolves to the imported proc even
|
|
|
+ when another module declares the same name. Reset each unit. *)
|
|
|
+ impProc : ARRAY [0 .. MaxImp - 1] OF INTEGER;
|
|
|
+ impName : ARRAY [0 .. MaxImp * 64 - 1] OF CHAR;
|
|
|
+ nImps : CARDINAL;
|
|
|
(* Scoping: each symbol records the procedure that owns it (-1 =
|
|
|
module level); FindSym searches the emitted procedure's chain
|
|
|
innermost-first so common names (s, i, k) do not collide across
|
|
|
@@ -354,11 +361,22 @@ PROCEDURE ProcVisible (i: INTEGER): BOOLEAN;
|
|
|
RETURN procParent[i] = -1
|
|
|
END ProcVisible;
|
|
|
|
|
|
+PROCEDURE ImpNameEq (i: CARDINAL; name: ARRAY OF CHAR): BOOLEAN;
|
|
|
+ BEGIN
|
|
|
+ RETURN SpanEq(impName, i * 64, name)
|
|
|
+ END ImpNameEq;
|
|
|
+
|
|
|
PROCEDURE FindProc (name: ARRAY OF CHAR): INTEGER;
|
|
|
(* Scope-aware: a nested procedure (e.g. one of two `Sep`s) must resolve
|
|
|
- to the one in the emitted procedure's chain, not the last duplicate. *)
|
|
|
+ to the one in the emitted procedure's chain, not the last duplicate.
|
|
|
+ The current unit's imports win over any same-named proc. *)
|
|
|
VAR i: INTEGER; owner: INTEGER;
|
|
|
BEGIN
|
|
|
+ i := 0;
|
|
|
+ WHILE i < VAL(INTEGER, nImps) DO
|
|
|
+ IF ImpNameEq(VAL(CARDINAL, i), name) THEN RETURN impProc[i] END;
|
|
|
+ INC(i)
|
|
|
+ END;
|
|
|
i := HashGet(procHash, procName, name);
|
|
|
IF (i >= 0) AND ProcVisible(i) THEN RETURN i END;
|
|
|
owner := emitProc;
|
|
|
@@ -395,6 +413,21 @@ PROCEDURE FindProcByUid (uid: CARDINAL): INTEGER;
|
|
|
RETURN -1
|
|
|
END FindProcByUid;
|
|
|
|
|
|
+PROCEDURE NoteImportedProc (name: ARRAY OF CHAR);
|
|
|
+(* FROM M IMPORT P (a procedure): remember the exact proc entry so an
|
|
|
+ unqualified call resolves to the imported proc, not a same-named
|
|
|
+ proc declared in another module. Reset at each unit. *)
|
|
|
+ VAR pi: INTEGER;
|
|
|
+ BEGIN
|
|
|
+ IF SymTab.SymKind(name) # SymTab.KindProc THEN RETURN END;
|
|
|
+ pi := FindProcByUid(SymTab.ProcUid(name));
|
|
|
+ IF pi < 0 THEN RETURN END;
|
|
|
+ IF nImps >= MaxImp THEN RETURN END;
|
|
|
+ impProc[nImps] := pi;
|
|
|
+ CopySpan(name, impName, 0, nImps * 64);
|
|
|
+ INC(nImps)
|
|
|
+ END NoteImportedProc;
|
|
|
+
|
|
|
PROCEDURE Resolve (nm: ARRAY OF CHAR; VAR k: INTEGER;
|
|
|
VAR t: SymTab.TypeIndex): BOOLEAN;
|
|
|
VAR kind: INTEGER; ti: SymTab.TypeIndex;
|
|
|
@@ -1135,7 +1168,11 @@ PROCEDURE LowerDesign (n: AST.Node; VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
|
END
|
|
|
ELSIF (k = SymTab.KindVar) OR (k = SymTab.KindParam) THEN
|
|
|
cls := SymTab.ClassOf(t);
|
|
|
- IF (cls = SymTab.ClInt) OR (cls = SymTab.ClBool)
|
|
|
+ IF AST.Op(n) = 1 THEN
|
|
|
+ (* a forward module-level reference: the grammar's FwdAddrOper
|
|
|
+ leaves an address (sfx=TRUE), not a loaded value *)
|
|
|
+ QbeGen.AddrOf(nm, q); sfx := TRUE
|
|
|
+ ELSIF (cls = SymTab.ClInt) OR (cls = SymTab.ClBool)
|
|
|
OR (cls = SymTab.ClChar) OR (cls = SymTab.ClUChar)
|
|
|
OR (cls = SymTab.ClEnum) OR (cls = SymTab.ClReal) THEN
|
|
|
QbeGen.LoadVar(nm, cls = SymTab.ClReal, q)
|
|
|
@@ -2616,6 +2653,7 @@ PROCEDURE BeginUnit;
|
|
|
(* Snapshot the pre-parse state so Lower can discard the grammar's
|
|
|
suppressed inline mutations for this unit. *)
|
|
|
BEGIN
|
|
|
+ nImps := 0;
|
|
|
QbeGen.SaveSession
|
|
|
END BeginUnit;
|
|
|
|