public override void CGenStmt(Env env, CGenState state) { // Init this.Init.Map(_ => CGenExprStmt(env, _, state)); Int32 start_label = state.RequestLabel(); Int32 finish_label = state.RequestLabel(); Int32 continue_label = state.RequestLabel(); // start: state.CGenLabel(start_label); // test cont this.Cond.Map(_ => { Reg ret = CGenExprStmt(env, _, state); CGenTest(ret, state); return ret; }); // jz finish state.JZ(finish_label); // Body state.InLoop(continue_label, finish_label); this.Body.CGenStmt(env, state); state.OutLabels(); // continue: state.CGenLabel(continue_label); // Loop this.Loop.Map(_ => CGenExprStmt(env, _, state)); // jmp start state.JMP(start_label); // finish: state.CGenLabel(finish_label); }
public override void CGenStmt(Env env, CGenState state) { // Inside a switch statement, the initializations are ignored, // but the stack size should be changed. List<Tuple<Env, Decln>> declns; List<Tuple<Env, Stmt>> stmts; var compoundStmt = this.Stmt as CompoundStmt; if (compoundStmt == null) { throw new NotImplementedException(); } declns = compoundStmt.Declns; stmts = compoundStmt.Stmts; // Track all case values. IReadOnlyList<Int32> values = CaseLabelsGrabber.GrabLabels(this); // Make sure there are no duplicates. if (values.Distinct().Count() != values.Count) { throw new InvalidOperationException("case labels not unique."); } // Request labels for these values. Dictionary<Int32, Int32> value_to_label = values.ToDictionary(value => value, value => state.RequestLabel()); Int32 label_finish = state.RequestLabel(); Int32 num_default_stmts = stmts.Count(_ => _.Item2 is DefaultStmt); if (num_default_stmts > 1) { throw new InvalidOperationException("duplicate defaults."); } Int32 label_default = num_default_stmts == 1 ? state.RequestLabel() : label_finish; Int32 saved_stack_size = state.StackSize; Int32 stack_size = declns.Any() ? declns.Last().Item1.StackSize : saved_stack_size; // 1. Evaluate Expr. CGenExprStmt(env, this.Expr, state); // 2. Expand stack. state.CGenForceStackSizeTo(stack_size); // 3. Make the Jump list. foreach (KeyValuePair<Int32, Int32> value_label_pair in value_to_label) { state.CMPL(value_label_pair.Key, Reg.EAX); state.JZ(value_label_pair.Value); } state.JMP(label_default); // 4. List all the statements. state.InSwitch(label_finish, label_default, value_to_label); foreach (Tuple<Env, Stmt> env_stmt_pair in stmts) { env_stmt_pair.Item2.CGenStmt(env_stmt_pair.Item1, state); } state.OutLabels(); // 5. finish: state.CGenLabel(label_finish); // 6. Restore stack size. state.CGenForceStackSizeTo(saved_stack_size); }
public override void CGenStmt(Env env, CGenState state) { Int32 start_label = state.RequestLabel(); Int32 finish_label = state.RequestLabel(); Int32 continue_label = state.RequestLabel(); // start: state.CGenLabel(start_label); // Body state.InLoop(continue_label, finish_label); this.Body.CGenStmt(env, state); state.OutLabels(); state.CGenLabel(continue_label); // test Cond Reg ret = CGenExprStmt(env, this.Cond, state); CGenTest(ret, state); state.JNZ(start_label); state.CGenLabel(finish_label); }