Exemplo n.º 1
0
        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);
        }
Exemplo n.º 2
0
 public override void OperateULong(CGenState state) {
     state.CMPL(Reg.EBX, Reg.EAX);
     SetULong(state);
     state.MOVZBL(Reg.AL, Reg.EAX);
 }
Exemplo n.º 3
0
        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);
        }
Exemplo n.º 4
0
 /// <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);
 }