MGen.def 12 KB

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