MGen.def 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. DEFINITION MODULE MGen;
  2. (* MC64 image emitter for the M2c scalar subset (see M2c.atg).
  3. Buffers a single-module MC64 image and writes "<Module>.MC4"
  4. (current directory) at EndModule. The image satisfies the
  5. reference loader (Loader2): magic "MC64", descriptor with name,
  6. TOINIT flag, global sizes (one 8-byte slot per variable), two
  7. procedures (0 = user code, 1 = decimal print helper), relative
  8. procedure-table cells, and the checksum rule.
  9. Lowered: scalar globals (INTEGER/CARDINAL/CHAR/BOOLEAN/enums as
  10. 32-bit ops on slots, REAL as binary64), CONST initializers that
  11. are plain literals (emitted as startup stores), full scalar
  12. expressions on the stack machine, IF/CASE/WHILE/REPEAT/LOOP+EXIT/
  13. FOR via E0/E1 jumps with fixups. Everything else is reported by
  14. the parser (error 230); this module only needs structurally
  15. valid placeholders for those cases.
  16. Test convention (no I/O in the language): if the source declares
  17. VAR ExitCode : INTEGER; (int family, VAR kind)
  18. the epilogue prints its value as decimal + CRLF through the
  19. embedded print procedure; otherwise the program just ends.
  20. Step 3 adds procedures: user procedures take table entries 1..N
  21. (0 = module body), run with ENTER frames, and are called via
  22. ED (global), EC (directly nested) or EE (display walk). *)
  23. TYPE
  24. LitStr = ARRAY [0 .. 63] OF CHAR;
  25. (* Literal text: "42", "-5", "0FFH", "3.14", "'a'", "TRUE". ""
  26. means "not a plain literal". *)
  27. PROCEDURE OpenModule (name: ARRAY OF CHAR);
  28. (* Resets all state; reserves slots 0..3 for the print helper. *)
  29. PROCEDURE DeclVar (name: ARRAY OF CHAR);
  30. (* Assigns the next global slot to name (any type; one slot). *)
  31. PROCEDURE DeclVarSized (name: ARRAY OF CHAR; slots: CARDINAL);
  32. (* Assigns slots global slots to name (composites); 0 = empty record. *)
  33. PROCEDURE DeclConst (name: ARRAY OF CHAR; lit: LitStr; t: INTEGER);
  34. (* Assigns a slot and buffers a startup initializer from the literal
  35. text (t is a SymTab.TypeIndex). Empty lit buffers a 0. *)
  36. PROCEDURE DeclConstInt (name: ARRAY OF CHAR; v: INTEGER);
  37. (* Assigns a slot with an INTEGER startup value (enum literals). *)
  38. PROCEDURE BeginBody;
  39. (* Flushes buffered CONST initializers as startup stores. *)
  40. PROCEDURE EndModule;
  41. (* Emits the epilogue, the print procedure, the procedure table,
  42. the descriptor, the checksum, and writes the .MC4 file. *)
  43. PROCEDURE LoadVar (name: ARRAY OF CHAR);
  44. (* Pushes the global (placeholder push-0 if unknown). *)
  45. PROCEDURE StoreVar (name: ARRAY OF CHAR);
  46. (* Pops into the global (dropped if unknown). *)
  47. PROCEDURE PushVar (name: ARRAY OF CHAR);
  48. (* Pushes a variable's value, frame-aware: globals via the global
  49. table, same-frame locals/params direct, outer frames via the
  50. display, VAR params indirect. Placeholder push-0 if unknown. *)
  51. PROCEDURE LoadTemp (t: INTEGER);
  52. PROCEDURE StoreTemp (t: INTEGER);
  53. (* Direct slot access for compiler temporaries. *)
  54. PROCEDURE TempGlobal (): INTEGER;
  55. (* Allocates a fresh hidden global slot, returns its index. *)
  56. PROCEDURE PushInt (v: INTEGER);
  57. (* Small encodings for 0..15; negatives via 0,mag,sub. *)
  58. PROCEDURE PushBits (b: LONGCARD);
  59. (* 8E + 8 bytes: CARDINAL values and REAL bit patterns. *)
  60. PROCEDURE ParseInt (s: ARRAY OF CHAR; VAR v: INTEGER): BOOLEAN;
  61. (* Decimal, H-suffixed hex, optional leading '-'. *)
  62. PROCEDURE ParseCard (s: ARRAY OF CHAR; VAR v: CARDINAL): BOOLEAN;
  63. (* Decimal or H-suffixed hex (for literals past MAXINT). *)
  64. PROCEDURE ParseReal (s: ARRAY OF CHAR; VAR b: LONGCARD): BOOLEAN;
  65. (* Decimal with optional fraction/exponent/sign to IEEE bits. *)
  66. PROCEDURE CharOrd (s: ARRAY OF CHAR): INTEGER;
  67. (* ORD of a 1-character literal such as 'a'. *)
  68. PROCEDURE NegFold (a: ARRAY OF CHAR; VAR q: LitStr);
  69. (* Folds a unary minus into literal text ("5" -> "-5"). *)
  70. PROCEDURE IsLit (s: ARRAY OF CHAR): BOOLEAN;
  71. (* TRUE for non-empty literal text. *)
  72. (* ---- stack operators (one opcode each, see mc64-spec.md §11) ---- *)
  73. PROCEDURE Add;
  74. PROCEDURE Sub;
  75. PROCEDURE MulU;
  76. PROCEDURE DivU;
  77. PROCEDURE ModU;
  78. PROCEDURE MulI;
  79. PROCEDURE DivI;
  80. PROCEDURE ModI (t: INTEGER);
  81. (* Signed a MOD b with truncation semantics via temp slot t:
  82. a - (a DIV b) * b. Caller passes TempGlobal(). *)
  83. PROCEDURE RealAdd;
  84. PROCEDURE RealSub;
  85. PROCEDURE RealMul;
  86. PROCEDURE RealDiv;
  87. PROCEDURE And;
  88. PROCEDURE Or;
  89. PROCEDURE Not;
  90. PROCEDURE Power2;
  91. (* Push (1 << pop) for set element masks. *)
  92. PROCEDURE FieldMask;
  93. (* (1<<hi)-(1<<lo) for set ranges. *)
  94. PROCEDURE BitIn;
  95. (* Push (pop in bitset(pop)). *)
  96. PROCEDURE Eq;
  97. PROCEDURE Neq;
  98. PROCEDURE ULt;
  99. PROCEDURE ULe;
  100. PROCEDURE UGt;
  101. PROCEDURE UGe;
  102. PROCEDURE ILt;
  103. PROCEDURE ILe;
  104. PROCEDURE IGt;
  105. PROCEDURE IGe;
  106. PROCEDURE RealEq;
  107. PROCEDURE RealNe;
  108. PROCEDURE RealLt;
  109. PROCEDURE RealLe;
  110. PROCEDURE RealGt;
  111. PROCEDURE RealGe;
  112. PROCEDURE NegInt;
  113. PROCEDURE NegReal;
  114. PROCEDURE IntToReal;
  115. (* BD int_to_long + BE long_to_real. *)
  116. PROCEDURE Dup;
  117. PROCEDURE Drop;
  118. PROCEDURE Swap;
  119. (* 21H exchange top two words. *)
  120. (* ---- frames, addresses, indirect access (see §5-§6) ---- *)
  121. PROCEDURE LoadLocal (sl: INTEGER);
  122. PROCEDURE StoreLocal (sl: INTEGER);
  123. (* 2C/3C direct frame access (locals negative, params >= 3).
  124. Same-frame VAR-param slots hold addresses: read them with
  125. LoadLocal, then LoadIndir0. *)
  126. PROCEDURE LoadIndir0;
  127. PROCEDURE StoreIndir0;
  128. (* 60H/70H slot-0 indirect (through VAR-param addresses). *)
  129. PROCEDURE FrameAddr (sl: INTEGER; np: CARDINAL);
  130. (* Pushes (display-frame(np) + slot*8) as a byte address. *)
  131. PROCEDURE LoadIndir;
  132. PROCEDURE StoreIndir;
  133. (* 41H/51H through a computed address. *)
  134. PROCEDURE LocalAddr (sl: INTEGER);
  135. (* 80H address of a same-frame slot. *)
  136. PROCEDURE GlobalAddr (name: ARRAY OF CHAR);
  137. (* 81H address of a global (push-0 if unknown). *)
  138. PROCEDURE PushAddr (name: ARRAY OF CHAR);
  139. (* Pushes a VAR-actual address: slot addresses for plain variables,
  140. slot contents for VAR params; display-aware. Push-0 if unknown. *)
  141. PROCEDURE StoreSetup (name: ARRAY OF CHAR);
  142. (* Emits an early store address (VAR-param or outer-frame targets)
  143. before the value expression; nothing for direct targets. *)
  144. PROCEDURE StoreFinish (name: ARRAY OF CHAR);
  145. (* Emits the store for a storable variable (global, param, local,
  146. VAR-param, outer frame). *)
  147. (* ---- composites: arrays, records, pointers, sets, strings ---- *)
  148. PROCEDURE IdxScale (lo: INTEGER; elemBytes: CARDINAL);
  149. (* [base idx] -> base+(idx-lo)*elemBytes (unchecked, 32-bit). *)
  150. PROCEDURE FieldAdd (offSlots: CARDINAL);
  151. (* [base] -> base+offSlots*8 (no-op when 0). *)
  152. PROCEDURE CopyBlock;
  153. (* 30H copy_block: pops size, src, dst (push dst, src, size). *)
  154. PROCEDURE LoadByte;
  155. (* [addr] -> [byte at addr] (0DH with index 0). *)
  156. PROCEDURE StoreByte;
  157. (* [addr value] -> [] (1DH with index 0). *)
  158. PROCEDURE PushBytes (n: CARDINAL);
  159. (* Pushes n as byte count (for ALLOCATE/copy sizes). *)
  160. PROCEDURE AllocOp;
  161. (* 40H 05H ALLOCATE: pops size, p-addr; *p := heap block. *)
  162. PROCEDURE DeallocOp;
  163. (* 40H 06H DEALLOCATE: pops size, p-addr; free + *p := NIL. *)
  164. PROCEDURE BitXor;
  165. (* E9H bitset symmetric difference (for SET - via AND/NOT). *)
  166. PROCEDURE EmitString (s: ARRAY OF CHAR);
  167. (* 8CH inline NUL-terminated string: pushes its code address.
  168. s includes quotes (e.g. "'abc'"); longer than 255 rejected. *)
  169. PROCEDURE StrLenOf (s: ARRAY OF CHAR): CARDINAL;
  170. (* Length without quotes (bytes excluding NUL). *)
  171. PROCEDURE StrComp;
  172. (* C4H string compare (see spec 12.1). *)
  173. (* ---- WITH statement (record scope) ---- *)
  174. PROCEDURE WithEnter (typ: INTEGER);
  175. (* Pops record address, stores to fresh temp, pushes WITH level.
  176. typ is a SymTab.TypeIndex (record type). *)
  177. PROCEDURE WithExit;
  178. (* Pops one WITH level. *)
  179. PROCEDURE WithDepth (): CARDINAL;
  180. (* Current WITH nesting (0 outside). *)
  181. PROCEDURE WithAddr (name: ARRAY OF CHAR);
  182. (* Pushes field address for visible WITH field (or push-0 if absent). *)
  183. PROCEDURE PrintNum (): CARDINAL;
  184. (* Number of the embedded decimal-print helper (maxNum+1). *)
  185. PROCEDURE CallPrint;
  186. (* Calls the print helper (expects value on stack), drops result. *)
  187. PROCEDURE SysCall;
  188. (* C3H SYSTEM host call (pops id+param; see spec 9.3). *)
  189. (* ---- procedures (see §5.2) ---- *)
  190. PROCEDURE ProcEntry (num: INTEGER; nLoc: CARDINAL);
  191. (* Records the procedure address and emits ENTER for nLoc locals. *)
  192. PROCEDURE CallProc (num: INTEGER);
  193. (* ED: call a global procedure (OFP = NIL). *)
  194. PROCEDURE CallNested (num: INTEGER);
  195. (* EC: call a directly nested procedure (OFP = FP). *)
  196. PROCEDURE CallDisplay (num: INTEGER; np: CARDINAL);
  197. (* 11H np display walk, then EE call with that frame. *)
  198. PROCEDURE Leave (nPar: CARDINAL; func: BOOLEAN);
  199. (* 84H (proper) or 85H (function) procedure leave. *)
  200. (* ---- actual parameters (nested-call-safe frame stack) ---- *)
  201. PROCEDURE ActBegin (pn: ARRAY OF CHAR);
  202. (* Opens an actual-parameter frame for a call to pn. *)
  203. PROCEDURE ActValue (t: INTEGER; v: BOOLEAN;
  204. vn: ARRAY OF CHAR): INTEGER;
  205. (* Checks one actual against its formal (0 = ok): VAR formals need
  206. a plain variable of identical type (address pushed), value
  207. formals need assignment compatibility (INTEGER widens to REAL).
  208. Always consumes the value (temp store). 1 means error 233. *)
  209. PROCEDURE ActIsVarNext (): BOOLEAN;
  210. (* TRUE if the current formal (actSt.n) is a VAR parameter
  211. (known callee, in range). Used to keep addresses (not values)
  212. for VAR a[i] actuals. *)
  213. PROCEDURE NoteSfx (b: BOOLEAN);
  214. (* Records tails-present for the current actual (top frame). *)
  215. PROCEDURE NoteIdx (b: BOOLEAN);
  216. (* Records index-only tails for the current actual (top frame). *)
  217. PROCEDURE ActEnd (pn: ARRAY OF CHAR; sfx, inExpr: BOOLEAN): INTEGER;
  218. (* Verifies arity and callee kind, reloads actuals reversed and
  219. emits the depth-correct call (0 = ok, 1 = error 233). *)
  220. (* ---- control flow (E0/E1 with fixups) ---- *)
  221. PROCEDURE NewLabel (): INTEGER;
  222. PROCEDURE DefLabel (id: INTEGER);
  223. PROCEDURE Jmp (id: INTEGER);
  224. PROCEDURE Jz (id: INTEGER);
  225. (* Jump if false (pops the condition). *)
  226. PROCEDURE PushLoop (exit: INTEGER);
  227. PROCEDURE PopLoop;
  228. PROCEDURE TopLoop (VAR exit: INTEGER): BOOLEAN;
  229. (* Innermost LOOP exit label; FALSE outside any LOOP. *)
  230. PROCEDURE NoSupEnter;
  231. PROCEDURE NoSupExit;
  232. PROCEDURE CopyName (s: ARRAY OF CHAR; VAR d: ARRAY OF CHAR);
  233. (* Copies zero-terminated strings between any char arrays. *)
  234. PROCEDURE NoEmitEnter;
  235. PROCEDURE NoEmitExit;
  236. (* Suppresses code emission (not literal capture) in declarative
  237. contexts such as CONST initializers and subrange bounds. *)
  238. PROCEDURE NoSup (): BOOLEAN;
  239. (* Guard depth for unsupported constructs: while > 0 the grammar
  240. suppresses follow-on 230 errors to avoid cascades. *)
  241. END MGen.