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 OperateULong(CGenState state) { state.CMPL(Reg.EBX, Reg.EAX); SetULong(state); state.MOVZBL(Reg.AL, Reg.EAX); }
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; switch (stmt.kind) { case Kind.COMPOUND: declns = ((CompoundStmt)stmt).declns; stmts = ((CompoundStmt)stmt).stmts; break; default: throw new NotImplementedException(); } // 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.kind == Kind.DEFAULT); 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, 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); }
/// <summary> /// <para>Before: %eax = left, %ebx = right, stack unchanged.</para> /// <para>After: with SetULong, %eax = left op right, stack unchanged.</para> /// </summary> public override sealed void OperateULong(CGenState state) { state.CMPL(Reg.EBX, Reg.EAX); SetULong(state); state.MOVZBL(Reg.AL, Reg.EAX); }