| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355 |
- DEFINITION MODULE MGen;
- (* MC64 image emitter for the M2c scalar subset (see M2c.atg).
- Buffers a single-module MC64 image and writes "<Module>.MC4"
- (current directory) at EndModule. The image satisfies the
- reference loader (Loader2): magic "MC64", descriptor with name,
- TOINIT flag, global sizes (one 8-byte slot per variable), two
- procedures (0 = user code, 1 = decimal print helper), relative
- procedure-table cells, and the checksum rule.
- Lowered: scalar globals (INTEGER/CARDINAL/CHAR/BOOLEAN/enums as
- 32-bit ops on slots, REAL as binary64), CONST initializers that
- are plain literals (emitted as startup stores), full scalar
- expressions on the stack machine, IF/CASE/WHILE/REPEAT/LOOP+EXIT/
- FOR via E0/E1 jumps with fixups. Everything else is reported by
- the parser (error 230); this module only needs structurally
- valid placeholders for those cases.
- Test convention (no I/O in the language): if the source declares
- VAR ExitCode : INTEGER; (int family, VAR kind)
- the epilogue prints its value as decimal + CRLF through the
- embedded print procedure; otherwise the program just ends.
- Step 3 adds procedures: user procedures take table entries 1..N
- (0 = module body), run with ENTER frames, and are called via
- ED (global), EC (directly nested) or EE (display walk). *)
- TYPE
- LitStr = ARRAY [0 .. 63] OF CHAR;
- (* Literal text: "42", "-5", "0FFH", "3.14", "'a'", "TRUE". ""
- means "not a plain literal". *)
- PROCEDURE OpenModule (name: ARRAY OF CHAR);
- (* Resets all state; reserves slots 0..3 for the print helper. *)
- PROCEDURE SetModName (name: ARRAY OF CHAR);
- (* Sets the output image name (multi-file sessions: the program
- unit calls this; EndModule writes <name>.MC4). *)
- PROCEDURE DeclVar (name: ARRAY OF CHAR);
- (* Assigns the next global slot to name (any type; one slot). *)
- PROCEDURE DeclVarSized (name: ARRAY OF CHAR; slots: CARDINAL);
- (* Assigns slots global slots to name (composites); 0 = empty record. *)
- PROCEDURE DeclConst (name: ARRAY OF CHAR; lit: LitStr; t: INTEGER);
- (* Assigns a slot and buffers a startup initializer from the literal
- text (t is a SymTab.TypeIndex). Empty lit buffers a 0. *)
- PROCEDURE DeclConstInt (name: ARRAY OF CHAR; v: INTEGER);
- (* Assigns a slot with an INTEGER startup value (enum literals). *)
- PROCEDURE BeginBody;
- (* Flushes buffered CONST initializers as startup stores. *)
- PROCEDURE EndModule;
- (* Emits the epilogue, the print procedure, the procedure table,
- the descriptor, the checksum, and writes the .MC4 file. *)
- PROCEDURE LoadVar (name: ARRAY OF CHAR);
- (* Pushes the global (placeholder push-0 if unknown). *)
- PROCEDURE StoreVar (name: ARRAY OF CHAR);
- (* Pops into the global (dropped if unknown). *)
- PROCEDURE PushVar (name: ARRAY OF CHAR);
- (* Pushes a variable's value, frame-aware: globals via the global
- table, same-frame locals/params direct, outer frames via the
- display, VAR params indirect. Placeholder push-0 if unknown. *)
- PROCEDURE LoadTemp (t: INTEGER);
- PROCEDURE StoreTemp (t: INTEGER);
- (* Direct slot access for compiler temporaries. *)
- PROCEDURE TempGlobal (): INTEGER;
- (* Allocates a fresh hidden global slot, returns its index. *)
- PROCEDURE PushInt (v: INTEGER);
- (* Small encodings for 0..15; negatives via 0,mag,sub. *)
- PROCEDURE PushBits (b: LONGCARD);
- (* 8E + 8 bytes: CARDINAL values and REAL bit patterns. *)
- PROCEDURE ParseInt (s: ARRAY OF CHAR; VAR v: INTEGER): BOOLEAN;
- (* Decimal, H-suffixed hex, optional leading '-'. *)
- PROCEDURE ParseCard (s: ARRAY OF CHAR; VAR v: CARDINAL): BOOLEAN;
- (* Decimal or H-suffixed hex (for literals past MAXINT). *)
- PROCEDURE ParseReal (s: ARRAY OF CHAR; VAR b: LONGCARD): BOOLEAN;
- (* Decimal with optional fraction/exponent/sign to IEEE bits. *)
- PROCEDURE CharOrd (s: ARRAY OF CHAR): INTEGER;
- (* ORD of a 1-character literal such as 'a'. *)
- PROCEDURE NegFold (a: ARRAY OF CHAR; VAR q: LitStr);
- (* Folds a unary minus into literal text ("5" -> "-5"). *)
- PROCEDURE IsLit (s: ARRAY OF CHAR): BOOLEAN;
- (* TRUE for non-empty literal text. *)
- (* ---- stack operators (one opcode each, see mc64-spec.md §11) ---- *)
- PROCEDURE Add;
- PROCEDURE Sub;
- PROCEDURE MulU;
- PROCEDURE DivU;
- PROCEDURE ModU;
- PROCEDURE MulI;
- PROCEDURE DivI;
- PROCEDURE ModI (t: INTEGER);
- (* Signed a MOD b with truncation semantics via temp slot t:
- a - (a DIV b) * b. Caller passes TempGlobal(). *)
- PROCEDURE RealAdd;
- PROCEDURE RealSub;
- PROCEDURE RealMul;
- PROCEDURE RealDiv;
- PROCEDURE And;
- PROCEDURE Or;
- PROCEDURE Not;
- PROCEDURE Power2;
- (* Push (1 << pop) for set element masks. *)
- PROCEDURE FieldMask;
- (* (1<<hi)-(1<<lo) for set ranges. *)
- PROCEDURE BitIn;
- (* Push (pop in bitset(pop)). *)
- PROCEDURE Eq;
- PROCEDURE Neq;
- PROCEDURE ULt;
- PROCEDURE ULe;
- PROCEDURE UGt;
- PROCEDURE UGe;
- PROCEDURE ILt;
- PROCEDURE ILe;
- PROCEDURE IGt;
- PROCEDURE IGe;
- PROCEDURE RealEq;
- PROCEDURE RealNe;
- PROCEDURE RealLt;
- PROCEDURE RealLe;
- PROCEDURE RealGt;
- PROCEDURE RealGe;
- PROCEDURE NegInt;
- PROCEDURE NegReal;
- PROCEDURE IntToReal;
- (* BD int_to_long + BE long_to_real. *)
- PROCEDURE Dup;
- PROCEDURE Drop;
- PROCEDURE Swap;
- (* 21H exchange top two words. *)
- (* ---- frames, addresses, indirect access (see §5-§6) ---- *)
- PROCEDURE LoadLocal (sl: INTEGER);
- PROCEDURE StoreLocal (sl: INTEGER);
- (* 2C/3C direct frame access (locals negative, params >= 3).
- Same-frame VAR-param slots hold addresses: read them with
- LoadLocal, then LoadIndir0. *)
- PROCEDURE LoadIndir0;
- PROCEDURE StoreIndir0;
- (* 60H/70H slot-0 indirect (through VAR-param addresses). *)
- PROCEDURE FrameAddr (sl: INTEGER; np: CARDINAL);
- (* Pushes (display-frame(np) + slot*8) as a byte address. *)
- PROCEDURE LoadIndir;
- PROCEDURE StoreIndir;
- (* 41H/51H through a computed address. *)
- PROCEDURE LocalAddr (sl: INTEGER);
- (* 80H address of a same-frame slot. *)
- PROCEDURE GlobalAddr (name: ARRAY OF CHAR);
- (* 81H address of a global (push-0 if unknown). *)
- PROCEDURE PushAddr (name: ARRAY OF CHAR);
- (* Pushes a VAR-actual address: slot addresses for plain variables,
- slot contents for VAR params; display-aware. Push-0 if unknown. *)
- PROCEDURE StoreSetup (name: ARRAY OF CHAR);
- (* Emits an early store address (VAR-param or outer-frame targets)
- before the value expression; nothing for direct targets. *)
- PROCEDURE StoreFinish (name: ARRAY OF CHAR);
- (* Emits the store for a storable variable (global, param, local,
- VAR-param, outer frame). *)
- (* ---- composites: arrays, records, pointers, sets, strings ---- *)
- PROCEDURE IdxScale (lo: INTEGER; elemBytes: CARDINAL);
- (* [base idx] -> base+(idx-lo)*elemBytes (unchecked, 32-bit). *)
- PROCEDURE FieldAdd (offSlots: CARDINAL);
- (* [base] -> base+offSlots*8 (no-op when 0). *)
- PROCEDURE CopyBlock;
- (* 30H copy_block: pops size, src, dst (push dst, src, size). *)
- PROCEDURE LoadByte;
- (* [addr] -> [byte at addr] (0DH with index 0). *)
- PROCEDURE StoreByte;
- (* [addr value] -> [] (1DH with index 0). *)
- PROCEDURE PushBytes (n: CARDINAL);
- (* Pushes n as byte count (for ALLOCATE/copy sizes). *)
- PROCEDURE AllocOp;
- (* 40H 05H ALLOCATE: pops size, p-addr; *p := heap block. *)
- PROCEDURE DeallocOp;
- (* 40H 06H DEALLOCATE: pops size, p-addr; free + *p := NIL. *)
- PROCEDURE BitXor;
- (* E9H bitset symmetric difference (for SET - via AND/NOT). *)
- PROCEDURE EmitString (s: ARRAY OF CHAR);
- (* 8CH inline NUL-terminated string: pushes its code address.
- s includes quotes (e.g. "'abc'"); longer than 255 rejected. *)
- PROCEDURE StrLenOf (s: ARRAY OF CHAR): CARDINAL;
- (* Length without quotes (bytes excluding NUL). *)
- PROCEDURE StrComp;
- (* C4H string compare (see spec 12.1). *)
- (* ---- WITH statement (record scope) ---- *)
- PROCEDURE WithEnter (typ: INTEGER);
- (* Pops record address, stores to fresh temp, pushes WITH level.
- typ is a SymTab.TypeIndex (record type). *)
- PROCEDURE WithExit;
- (* Pops one WITH level. *)
- PROCEDURE WithDepth (): CARDINAL;
- (* Current WITH nesting (0 outside). *)
- PROCEDURE WithAddr (name: ARRAY OF CHAR);
- (* Pushes field address for visible WITH field (or push-0 if absent). *)
- PROCEDURE PrintNum (): CARDINAL;
- (* Number of the embedded decimal-print helper (maxNum+1). *)
- PROCEDURE CallPrint;
- (* Calls the print helper (expects value on stack), drops result. *)
- PROCEDURE SysCall;
- (* C3H SYSTEM host call (pops id+param; see spec 9.3). *)
- (* ---- procedures (see §5.2) ---- *)
- PROCEDURE ProcEntry (num: INTEGER; nLoc: CARDINAL);
- (* Records the procedure address and emits ENTER for nLoc locals. *)
- PROCEDURE CallProc (num: INTEGER);
- (* ED: call a global procedure (OFP = NIL). *)
- PROCEDURE CallNested (num: INTEGER);
- (* EC: call a directly nested procedure (OFP = FP). *)
- PROCEDURE CallDisplay (num: INTEGER; np: CARDINAL);
- (* 11H np display walk, then EE call with that frame. *)
- PROCEDURE Leave (nPar: CARDINAL; func: BOOLEAN);
- (* 84H (proper) or 85H (function) procedure leave. *)
- PROCEDURE ModInitBegin (): INTEGER;
- (* Opens a module init body as a parameterless proper procedure,
- recorded for the startup calls in BeginBody. The number comes
- from SymTab's shared proc pool. -1 when full. *)
- PROCEDURE ModInitEnd (num: INTEGER);
- (* Closes a module init body (no-op for num < 0). *)
- (* ---- actual parameters (nested-call-safe frame stack) ---- *)
- PROCEDURE ActBegin (pn: ARRAY OF CHAR);
- (* Opens an actual-parameter frame for a call to pn. *)
- PROCEDURE ActValue (t: INTEGER; v: BOOLEAN;
- vn: ARRAY OF CHAR): INTEGER;
- (* Checks one actual against its formal (0 = ok): VAR formals need
- a plain variable of identical type (address pushed), value
- formals need assignment compatibility (INTEGER widens to REAL).
- Always consumes the value (temp store). 1 means error 233. *)
- PROCEDURE ActIsVarNext (): BOOLEAN;
- (* TRUE if the current formal (actSt.n) is a VAR parameter
- (known callee, in range). Used to keep addresses (not values)
- for VAR a[i] actuals. *)
- PROCEDURE StashAddr;
- (* Duplicates the address on top of stack into a per-actual temp of
- the current call frame (VAR actuals with tails). *)
- PROCEDURE ClrStash;
- (* Invalidates the stashed address of the current actual (a
- value-combining operator followed). *)
- PROCEDURE NoteSfx (b: BOOLEAN);
- (* Records tails-present for the current actual (top frame). *)
- PROCEDURE NoteIdx (b: BOOLEAN);
- (* Records index-only tails for the current actual (top frame). *)
- PROCEDURE ActEnd (pn: ARRAY OF CHAR; sfx, inExpr: BOOLEAN): INTEGER;
- (* Verifies arity and callee kind, reloads actuals reversed and
- emits the depth-correct call (0 = ok, 1 = error 233). *)
- PROCEDURE ActBeginNum (num: INTEGER);
- (* Opens an actual-parameter frame for the procedure numbered num
- (exported module procs, invisible by name after ExitModule). *)
- PROCEDURE ActEndNum (num: INTEGER; inExpr: BOOLEAN): INTEGER;
- (* By-number ActEnd: verifies arity, reloads actuals reversed and
- emits the global call (module procs are always global-level).
- 0 = ok, 1 = error 233. *)
- (* ---- control flow (E0/E1 with fixups) ---- *)
- PROCEDURE NewLabel (): INTEGER;
- PROCEDURE DefLabel (id: INTEGER);
- PROCEDURE Jmp (id: INTEGER);
- PROCEDURE Jz (id: INTEGER);
- (* Jump if false (pops the condition). *)
- PROCEDURE PushLoop (exit: INTEGER);
- PROCEDURE PopLoop;
- PROCEDURE TopLoop (VAR exit: INTEGER): BOOLEAN;
- (* Innermost LOOP exit label; FALSE outside any LOOP. *)
- PROCEDURE NoSupEnter;
- PROCEDURE NoSupExit;
- PROCEDURE CopyName (s: ARRAY OF CHAR; VAR d: ARRAY OF CHAR);
- (* Copies zero-terminated strings between any char arrays. *)
- PROCEDURE NoEmitEnter;
- PROCEDURE NoEmitExit;
- (* Suppresses code emission (not literal capture) in declarative
- contexts such as CONST initializers and subrange bounds. *)
- PROCEDURE NoSup (): BOOLEAN;
- (* Guard depth for unsupported constructs: while > 0 the grammar
- suppresses follow-on 230 errors to avoid cascades. *)
- END MGen.
|