public override int GenerateCode(int loc, IVirtualMachine vm, CheckerInformation info) { int copies = 0; foreach (ASTParam param in Params) { if (param.OptMechmode == MechMode.COPY && (param.FlowMode == FlowMode.INOUT || param.FlowMode == FlowMode.OUT)) { ++copies; } } vm.Enter(loc++, copies + Declarations.Count, 0); //CopyIn of inout copy parameters foreach (ASTParam param in Params) { if (param.OptMechmode == MechMode.COPY && param.FlowMode == FlowMode.INOUT) { vm.CopyIn(loc++, param.AddressLocation.Value, param.Address); } } //Generate body foreach (ASTCpsCmd cmd in Commands) { loc = cmd.GenerateCode(loc, vm, info); } //CopyOut of inout copy and out copy parameters bool omit = IsFunc; foreach (ASTParam param in Params) { if (omit) { omit = false; } else { if (param.OptMechmode == MechMode.COPY && (param.FlowMode == FlowMode.INOUT || param.FlowMode == FlowMode.OUT)) { vm.CopyOut(loc++, param.Address, param.AddressLocation.Value); } } } if (IsFunc) { //CopyOut return value //Can't use standard CopyOut, becuase it works with absolute target address and not with top of stack as needed! var paramIttr = Params.GetEnumerator(); paramIttr.MoveNext(); ASTParam result = paramIttr.Current; vm.LoadRel(loc++, result.Address); vm.Deref(loc++); vm.LoadRel(loc++, result.AddressLocation.Value); vm.Store(loc++); } //Return vm.Return(loc++, Params.Count - (IsFunc ? 1 : 0)); //For function the return size is one smaller, leaving the function expression result on the stack! return(loc); }
/* * program intDiv * global * proc divide(in copy m:int, in copy n:int, out ref q:int, out ref r:int) * do * q init := 0; * r init := m; * while r >= n do * q := q + 1; * r := r - n * endwhile * endproc; * * var m:int; * var n:int; * var q:int; * var r:int * do * ? m init; * ? n init; * call divide(m, n, q init, r init); * ! q; * ! r * endprogram */ public static void Test() { try { vm.Alloc(0, 4); vm.IntLoad(1, 0); vm.IntInput(2, "m"); vm.IntLoad(3, 1); vm.IntInput(4, "n"); vm.Alloc(5, 0); vm.IntLoad(6, 0); vm.Deref(7); vm.IntLoad(8, 1); vm.Deref(9); vm.IntLoad(10, 2); vm.IntLoad(11, 3); vm.Call(12, 20); vm.IntLoad(13, 2); vm.Deref(14); vm.IntOutput(15, "q"); vm.IntLoad(16, 3); vm.Deref(17); vm.IntOutput(18, "r"); vm.Stop(19); vm.Enter(20, 0, 0); vm.IntLoad(21, 0); vm.LoadRel(22, (-2)); vm.Deref(23); vm.Store(24); vm.LoadRel(25, (-4)); vm.Deref(26); vm.LoadRel(27, (-1)); vm.Deref(28); vm.Store(29); vm.LoadRel(30, (-1)); vm.Deref(31); vm.Deref(32); vm.LoadRel(33, (-3)); vm.Deref(34); vm.IntGE(35); vm.CondJump(36, 55); vm.LoadRel(37, (-2)); vm.Deref(38); vm.Deref(39); vm.IntLoad(40, 1); vm.IntAdd(41); vm.LoadRel(42, (-2)); vm.Deref(43); vm.Store(44); vm.LoadRel(45, (-1)); vm.Deref(46); vm.Deref(47); vm.LoadRel(48, (-3)); vm.Deref(49); vm.IntSub(50); vm.LoadRel(51, (-1)); vm.Deref(52); vm.Store(53); vm.UncondJump(54, 30); vm.Return(55, 4); } catch (IVirtualMachine.CodeTooSmallError e) { Console.WriteLine(e.ToString()); return; } try { vm.Execute(); } catch (IVirtualMachine.ExecutionError e) { Console.WriteLine(e.ToString()); return; } }