Explorar o código

feat: run 16-bit module dependencies under mcint

trans8to64: carry real DescDepCount and append dcnt*8 dep-name table at
the image tail (summed into the checksum); dcnt=0 output byte-identical
to the 5f922946 baseline.

Loader2: multi-window chain loader. LoadOne places each image + 8-aligned
zero-filled data window in the shared arena; Call loads deps into MTBL
slots 0..dcnt-1 and the main module at slot dcnt (first import = mod 0,
matching 16-bit Global.Module), then runs TOINIT dependency-first.
Nested dependencies still rejected.

Fixes CARDINAL underflow in the dep-init loop (FOR 0 TO dcnt-1 wrapped
to 2^32-1 iterations when dcnt=0).

Verified: Stack64/boot/example/readtest rc=0; mkdep synthetic two-module
extern_call (mod=0 -> dep slot 0) prints cross-module ok; real reference
libraries Extended/Array/Local (dep=STACK) all rc=0 under mcint.
Eric Streit hai 3 semanas
pai
achega
8f2c99e623
Modificáronse 8 ficheiros con 349 adicións e 13 borrados
  1. 93 11
      Loader2.mod
  2. BIN=BIN
      Loader2.o
  3. 27 0
      SESSION.MD5.trans8to64
  4. BIN=BIN
      mcint
  5. BIN=BIN
      mkdep
  6. 199 0
      mkdep.mod
  7. BIN=BIN
      trans8to64
  8. 30 2
      trans8to64.mod

+ 93 - 11
Loader2.mod

@@ -6,7 +6,7 @@ FROM FIO IMPORT OpenToRead, ReadNBytes, Close, IsNoError ;
 FROM Memory IMPORT ArenaBase, LoadImage, ReadByte, ReadWord, ReadSlot,
   FillBytes, ReadLong ;
 FROM Global IMPORT SetModuleBase, SetModuleProcs, SetModuleFlag,
-  SetCurrentModule ;
+  SetCurrentModule, GetModuleBase, GetModuleFlag ;
 FROM Local IMPORT Init, SetGP, SetIP ;
 FROM Instruction IMPORT ProcedureAddress ;
 FROM Interpreter IMPORT Run ;
@@ -25,12 +25,20 @@ CONST
   DescPad = 295 ;
   DescProcs = 296 ;
   DescVarSizes = 304 ;
+  MaxDeps = 32 ;
 
 VAR
   buf : ARRAY [0 .. 65535] OF CHAR ;
   f : FIO.File ;
 
-PROCEDURE Call (name: ARRAY OF CHAR) ;
+(* Load one translated .MCD image into module `slot`.  The image and its
+   zero-filled data window (plus globals) are placed at `next` and `next` is
+   advanced past them, so several modules share the arena without overlap
+   (multi-window arena).  The requested module lives at MTBL slot `dcnt`,
+   its dependencies at slots 0..dcnt-1 (the 16-bit source references the
+   first import as mod 0). *)
+PROCEDURE LoadOne (slot: CARDINAL; name: ARRAY OF CHAR; VAR next: LONGCARD ;
+                   allowDeps: BOOLEAN) ;
 VAR
   got : CARDINAL ;
   i : CARDINAL ;
@@ -50,12 +58,12 @@ BEGIN
   END ;
 
   imgLen := VAL (LONGCARD, got) - HeaderSize ;
-  desc := ArenaBase () ;
+  desc := next ;
   LoadImage (buf, HeaderSize, desc, got - HeaderSize) ;
 
   dcnt := ReadByte (desc + VAL (LONGCARD, DescDepCount)) ;
-  IF dcnt # 0 THEN
-    Fatal ("loader: dependencies not supported yet") ;
+  IF (dcnt # 0) AND NOT allowDeps THEN
+    Fatal ("loader: nested dependencies not supported yet") ;
   END ;
 
   chk := ReadLong (desc + VAL (LONGCARD, DescChecksum)) ;
@@ -89,16 +97,90 @@ BEGIN
     vnext := vnext + sz ;
   END ;
 
-  SetModuleBase (0, dataWin) ;
-  SetModuleProcs (0, procsAbs) ;
-  SetModuleFlag (0, fl) ;
-  SetCurrentModule (0) ;
+  SetModuleBase (slot, dataWin) ;
+  SetModuleProcs (slot, procsAbs) ;
+  SetModuleFlag (slot, fl) ;
+
+  next := vnext ;
+END LoadOne ;
+
+PROCEDURE Call (name: ARRAY OF CHAR) ;
+VAR
+  got : CARDINAL ;
+  imgLen, next : LONGCARD ;
+  dcnt : CARDINAL ;
+  j, k : CARDINAL ;
+  mainDataWin : LONGCARD ;
+  fl : CARDINAL ;
+  depName : ARRAY [0 .. MaxDeps - 1] OF ARRAY [0 .. 15] OF CHAR ;
+  fname : ARRAY [0 .. 255] OF CHAR ;
+BEGIN
+  f := OpenToRead (name) ;
+  IF NOT IsNoError (f) THEN
+    Fatal ("loader: cannot open module file") ;
+  END ;
+  got := ReadNBytes (f, HIGH (buf) + 1, ADR (buf)) ;
+  Close (f) ;
+  IF got <= 64 THEN
+    Fatal ("loader: file too short") ;
+  END ;
+
+  imgLen := VAL (LONGCARD, got) - HeaderSize ;
+  dcnt := ORD (buf [HeaderSize + DescDepCount]) ;
+  IF dcnt > MaxDeps THEN
+    Fatal ("loader: too many dependencies") ;
+  END ;
+
+  (* dependency names are the last dcnt*8 bytes of the image (file tail) *)
+  FOR j := 1 TO dcnt DO
+    FOR k := 0 TO 7 DO
+      depName [j - 1] [k] :=
+        buf [got - dcnt * 8 + (j - 1) * 8 + k] ;
+    END ;
+    depName [j - 1] [8] := 0C ;
+  END ;
+
+  next := ArenaBase () ;
 
+  (* dependencies first (slots 0..dcnt-1), then the requested module
+     (slot dcnt).  In the 16-bit source, extern references use mod 0 for
+     the first import, so MTBL slot 0 must be the first dependency. *)
+  FOR j := 1 TO dcnt DO
+    k := 0 ;
+    WHILE (k < 16) AND (depName [j - 1] [k] # 0C) DO
+      fname [k] := depName [j - 1] [k] ;
+      INC (k) ;
+    END ;
+    fname [k] := '.' ;
+    fname [k + 1] := 'M' ;
+    fname [k + 2] := 'C' ;
+    fname [k + 3] := 'D' ;
+    fname [k + 4] := 0C ;
+    LoadOne (j - 1, fname, next, FALSE) ;
+  END ;
+  LoadOne (dcnt, name, next, TRUE) ;
+
+  mainDataWin := GetModuleBase (dcnt) ;
+  fl := GetModuleFlag (dcnt) ;
+  SetCurrentModule (dcnt) ;
   Init () ;
-  SetGP (dataWin) ;
+  SetGP (mainDataWin) ;
 
+  (* initializers run dependency-first, the requested module last *)
+  FOR j := 1 TO dcnt DO
+    IF (GetModuleFlag (j - 1) DIV 4) MOD 2 # 0 THEN
+      Init () ;
+      SetGP (GetModuleBase (j - 1)) ;
+      SetCurrentModule (j - 1) ;
+      SetIP (ProcedureAddress (j - 1, 0)) ;
+      Run () ;
+    END ;
+  END ;
   IF (fl DIV 4) MOD 2 # 0 THEN  (* TOINIT : run the module initializer *)
-    SetIP (ProcedureAddress (0, 0)) ;
+    Init () ;
+    SetGP (mainDataWin) ;
+    SetCurrentModule (dcnt) ;
+    SetIP (ProcedureAddress (dcnt, 0)) ;
     Run () ;
   END ;
 END Call ;

BIN=BIN
Loader2.o


+ 27 - 0
SESSION.MD5.trans8to64

@@ -0,0 +1,27 @@
+trans8to64.mod baseline md5 = 36170a8bd630d93b90fc4c9b3c03cbbc (uncommitted; translator
+emit-locked, dep-chain milestone done)
+Any step that rewrites this file without first raising the lock paper is a session bug.
+
+== DEP-CHAIN MILESTONE CLOSED ==
+What changed (trans8to64.mod): reads ndeps=H16(6), deps16=H16(4); validates
+16+deps16+ndeps*12<=got and ndeps<=32; writes real DescDepCount (image byte 294);
+appends dcnt*8 dep-name table (NUL-padded, 8 bytes each) at the image tail, summed
+into the checksum. dcnt=0 output is byte-identical to the 5f922946 baseline.
+
+What changed (Loader2.mod): multi-window chain loader.
+  - LoadOne(slot, name, next, allowDeps): loads one image into MTBL slot `slot`;
+    per-slot dataWin = desc+imgLen (8-aligned) + zero-filled globals; advances `next`.
+  - Call: deps (slots 0..dcnt-1) loaded first, main at slot dcnt; dep names come
+    from the image tail (buf[got-dcnt*8 + ...]); dep TOINIT then main TOINIT run.
+  - Slot convention = the 16-bit semantics: extern mod 0 == first import
+    (verified at runtime by mkdep synthetic test: DEP extern_call mod=0 -> STAK slot 0,
+    "cross-module ok", rc=0).
+  - NOT allowed yet: nested dependencies (dep modules must have dcnt=0).
+  - Known trap fixed: `FOR j := 0 TO dcnt - 1` wrapped to 2^32-1 iterations when
+    dcnt=0 (CARDINAL underflow); now `FOR j := 1 TO dcnt` / j-1 indexing.
+
+Regression battery (all rc=0): Stack64 (dcnt=0, byte-identical image), boot.mc4,
+example.MCD, readtest (stdin), mkdep DEP cross-module call, and the real reference
+libraries Extended/Array/Local (dcnt=1, dep=STACK) under mcint.
+
+Old baseline (5f922946) kept for rollback.

BIN=BIN
mcint


BIN=BIN
mkdep


+ 199 - 0
mkdep.mod

@@ -0,0 +1,199 @@
+MODULE mkdep ;
+
+(* Synthetic two-module MC64 test for the Loader2 dep-chain :
+   - STAK.MCD : dependency-free sidecar.  proc0 = empty TOINIT,
+     proc1 = writes a host string (proves an extern call reached
+     the dependency's code via MTBL slot 0 + cross-module call/leave).
+   - DEP.MCD  : main module, dcnt=1, dep name "STAK".  TOINIT
+     extern-calls STAK.proc1, then end_program.
+   Run : mkdep ; then  mcint DEP.MCD   from the dir holding STAK.MCD.
+   Expect one line from the STAK proc, exit 0. *)
+
+FROM FileIO IMPORT WriteFile ;
+FROM Console IMPORT Fatal ;
+FROM SYSTEM IMPORT ADR ;
+
+CONST
+  HeaderSize = 64 ;
+  DescName = 264 ;
+  DescChecksum = 288 ;
+  DescFlags = 292 ;
+  DescVarCount = 293 ;
+  DescDepCount = 294 ;
+  DescProcs = 296 ;
+  ProcTable = 304 ;
+  CodeOff = 312 ;
+  BufSize = 2048 ;
+
+TYPE
+  Typ = (tStak, tDep) ;
+
+VAR
+  buf : ARRAY [0 .. BufSize - 1] OF CHAR ;
+  pcimg : CARDINAL ;
+  i, p0, p1, sum, pt : CARDINAL ;
+  which : Typ ;
+
+PROCEDURE Op (o : CARDINAL) ;
+BEGIN
+  buf [HeaderSize + pcimg] := CHR (o MOD 256) ;
+  INC (pcimg) ;
+END Op ;
+
+PROCEDURE OpB (o, b : CARDINAL) ;
+BEGIN
+  Op (o) ;
+  buf [HeaderSize + pcimg] := CHR (b MOD 256) ;
+  INC (pcimg) ;
+END OpB ;
+
+PROCEDURE Put32 (off, v : CARDINAL) ;
+BEGIN
+  buf [off] := CHR (v MOD 256) ;
+  buf [off + 1] := CHR ((v DIV 256) MOD 256) ;
+  buf [off + 2] := CHR ((v DIV 65536) MOD 256) ;
+  buf [off + 3] := CHR (v DIV 16777216) ;
+END Put32 ;
+
+PROCEDURE Put64 (off : CARDINAL ; v : LONGCARD) ;
+VAR j : CARDINAL ;
+BEGIN
+  FOR j := 0 TO 7 DO
+    buf [off + j] := CHR (VAL (CARDINAL, v MOD 256)) ;
+    v := v DIV 256 ;
+  END ;
+END Put64 ;
+
+PROCEDURE ImmB (b : CARDINAL) ;
+BEGIN
+  OpB (8DH, b) ;
+END ImmB ;
+
+PROCEDURE EStr (s : ARRAY OF CHAR) ;
+VAR len, k : CARDINAL ;
+BEGIN
+  Op (8CH) ;
+  len := LENGTH (s) + 1 ;
+  buf [HeaderSize + pcimg] := CHR (len) ;
+  INC (pcimg) ;
+  FOR k := 0 TO LENGTH (s) - 1 DO
+    buf [HeaderSize + pcimg + k] := s [k] ;
+  END ;
+  INC (pcimg, LENGTH (s)) ;
+  buf [HeaderSize + pcimg] := 0C ;
+  INC (pcimg) ;
+END EStr ;
+
+PROCEDURE PrintStr ;
+BEGIN
+  ImmB (1) ;
+  Op (0C3H) ;
+END PrintStr ;
+
+PROCEDURE Stak ;  (* build STAK.MCD *)
+VAR st, s1 : CARDINAL ;
+BEGIN
+  which := tStak ;
+  FOR i := 0 TO BufSize - 1 DO
+    buf [i] := 0C ;
+  END ;
+  buf [0] := 'M' ;
+  buf [1] := 'C' ;
+  buf [2] := '6' ;
+  buf [3] := '4' ;
+  buf [HeaderSize + DescName] := 'S' ;
+  buf [HeaderSize + DescName + 1] := 'T' ;
+  buf [HeaderSize + DescName + 2] := 'A' ;
+  buf [HeaderSize + DescName + 3] := 'K' ;
+  buf [HeaderSize + DescFlags] := CHR (4) ;
+  buf [HeaderSize + DescVarCount] := CHR (0) ;
+  buf [HeaderSize + DescDepCount] := CHR (0) ;
+
+  pcimg := CodeOff ;
+
+  (* proc0 : empty initializer *)
+  p0 := pcimg ;
+  Op (50H) ;
+
+  (* proc1 : write "cross-module ok" via SYSTEM service 1 *)
+  s1 := pcimg ;
+  OpB (0D4H, 250) ;
+  EStr ("cross-module ok") ;
+  PrintStr ;
+  OpB (85H, 0) ;
+
+  pt := pcimg ;
+  Put64 (HeaderSize + DescProcs, VAL (LONGCARD, pt)) ;
+  Put64 (HeaderSize + pt, VAL (LONGCARD, p0) - VAL (LONGCARD, pt)) ;
+  Put64 (HeaderSize + pt + 8,
+         VAL (LONGCARD, s1) - VAL (LONGCARD, pt + 8)) ;
+  INC (pcimg, 16) ;
+
+  sum := 0 ;
+  FOR i := HeaderSize TO HeaderSize + pcimg - 1 DO
+    IF NOT ((i >= 352) AND (i <= 355)) THEN
+      sum := sum + ORD (buf [i]) ;
+    END ;
+  END ;
+  Put32 (HeaderSize + DescChecksum, sum) ;
+
+  IF NOT WriteFile ("STAK.MCD", buf, HeaderSize + pcimg) THEN
+    Fatal ("mkdep: cannot write STAK.MCD") ;
+  END ;
+END Stak ;
+
+PROCEDURE Dep ;  (* build DEP.MCD *)
+VAR st0, dep : CARDINAL ;
+BEGIN
+  which := tDep ;
+  FOR i := 0 TO BufSize - 1 DO
+    buf [i] := 0C ;
+  END ;
+  buf [0] := 'M' ;
+  buf [1] := 'C' ;
+  buf [2] := '6' ;
+  buf [3] := '4' ;
+  buf [HeaderSize + DescName] := 'D' ;
+  buf [HeaderSize + DescName + 1] := 'E' ;
+  buf [HeaderSize + DescName + 2] := 'P' ;
+  buf [HeaderSize + DescFlags] := CHR (4) ;
+  buf [HeaderSize + DescVarCount] := CHR (0) ;
+  buf [HeaderSize + DescDepCount] := CHR (1) ;
+
+  pcimg := CodeOff ;
+
+  (* proc0 : TOINIT -> extern call STAK.proc1, then end_program *)
+  st0 := pcimg ;
+  OpB (0EFH, 0) ; Op (1) ;   (* extern_call mod=0, proc=1 *)
+  Op (50H) ;
+
+  pt := pcimg ;
+  Put64 (HeaderSize + DescProcs, VAL (LONGCARD, pt)) ;
+  Put64 (HeaderSize + pt, VAL (LONGCARD, st0) - VAL (LONGCARD, pt)) ;
+  INC (pcimg, 8) ;
+
+  (* dependency name table at the image tail : "STAK" *)
+  dep := pcimg ;
+  buf [HeaderSize + dep] := 'S' ;
+  buf [HeaderSize + dep + 1] := 'T' ;
+  buf [HeaderSize + dep + 2] := 'A' ;
+  buf [HeaderSize + dep + 3] := 'K' ;
+  INC (pcimg, 8) ;
+
+  sum := 0 ;
+  FOR i := HeaderSize TO HeaderSize + pcimg - 1 DO
+    IF NOT ((i >= 352) AND (i <= 355)) THEN
+      sum := sum + ORD (buf [i]) ;
+    END ;
+  END ;
+  Put32 (HeaderSize + DescChecksum, sum) ;
+
+  IF NOT WriteFile ("DEP.MCD", buf, HeaderSize + pcimg) THEN
+    Fatal ("mkdep: cannot write DEP.MCD") ;
+  END ;
+END Dep ;
+
+BEGIN
+  Stak ;
+  Dep ;
+END mkdep.

BIN=BIN
trans8to64


+ 30 - 2
trans8to64.mod

@@ -22,8 +22,13 @@ MODULE trans8to64 ;
             scan i while cell<0 ; codeEnd = procsAddr-2*k0
       dependencies : nbDeps * 12 bytes (dropped by mc64)
 
+   16-bit dependencies : nbDependencies u16 (header +6) ; records of 12 bytes
+   (name[8], version u16, location u16) sit at blob offset +4 (header +4),
+   at the tail of the blob.  The 64-bit image carries dcnt (DescDepCount)
+   and an 8-byte name per dependency, appended at the image tail.
+
    64-bit output : 64-byte "MC64" header + descriptor + translated code +
-   rebuilt proc table (cells relative to cell start).
+   rebuilt proc table (cells relative to cell start) + dcnt*8 dep-name table.
 
    Operand translation (locked against mc64/Interpreter.mod) ::
       8E word imm  2B -> 8B  zero-extended (CARDINAL/word semantics)
@@ -74,6 +79,8 @@ VAR
   map : ARRAY [0 .. MaxBuf] OF LONGCARD ;
   got : CARDINAL ;
   ms, cs : CARDINAL ;
+  ndeps, deps16 : CARDINAL ;
+  k2 : CARDINAL ;
   desc, procs16 : CARDINAL ;
   k0 : CARDINAL ;
   codeEnd : CARDINAL ;
@@ -352,6 +359,14 @@ BEGIN
   IF 16 + cs > got THEN
     Fatal ("trans8to64: header/blob size mismatch") ;
   END ;
+  ndeps := H16 (6) ;
+  deps16 := cs ;
+  IF ndeps > 32 THEN
+    Fatal ("trans8to64: too many dependencies") ;
+  END ;
+  IF 16 + deps16 + ndeps * 12 > got THEN
+    Fatal ("trans8to64: dependency table out of range") ;
+  END ;
   IF ms + 84 > cs THEN
     Fatal ("trans8to64: descriptor out of range") ;
   END ;
@@ -426,7 +441,7 @@ BEGIN
   Put64 (DescLoadAddr, VAL (LONGCARD, Get16 (desc + 74))) ;
   WB (DescFlags, flags8) ;
   WB (DescVarCount, vcnt) ;
-  WB (DescDepCount, 0) ;
+  WB (DescDepCount, ndeps) ;
   WB (DescPad, 0) ;
   IF vcnt > 0 THEN
     FOR j := 0 TO vcnt - 1 DO
@@ -455,6 +470,19 @@ BEGIN
   END ;
   imgLen := procTabImg + k0 * 8 ;
 
+  (* append the dependency name table at the image tail : 8 bytes each *)
+  IF ndeps > 0 THEN
+    IF imgLen + ndeps * 8 > MaxBuf THEN
+      Fatal ("trans8to64: output too large") ;
+    END ;
+    FOR j := 0 TO ndeps - 1 DO
+      FOR k2 := 0 TO 7 DO
+        WB (imgLen + k2, B (deps16 + j * 12 + k2)) ;
+      END ;
+      INC (imgLen, 8) ;
+    END ;
+  END ;
+
   (* file header : magic *)
   dst [0] := 'M' ;
   dst [1] := 'C' ;