Beispiel #1
0
 public override void CGenStmt(Env env, CGenState state) {
     if (this.ExprOpt.IsSome) {
         Int32 stack_size = state.StackSize;
         this.ExprOpt.Value.CGenValue(state);
         state.CGenForceStackSizeTo(stack_size);
     }
 }
Beispiel #2
0
 public override void CGenStmt(Env env, CGenState state) {
     foreach (Tuple<Env, Decln> decln in this.Declns) {
         decln.Item2.CGenDecln(decln.Item1, state);
     }
     foreach (Tuple<Env, Stmt> stmt in this.Stmts) {
         stmt.Item2.CGenStmt(stmt.Item1, state);
     }
 }
        public void CGenDecln(Env env, CGenState state) {
            //     .text
            //     [.globl <func>]
            // <func>:
            //     pushl %ebp
            //     movl %esp, %ebp
            // 
            state.TEXT();
            Env.Entry entry = env.Find(this.name).Value;
            state.COMMENT(ToString());
            switch (entry.Kind) {
            case Env.EntryKind.GLOBAL:
                switch (this.scs) {
                case StorageClass.AUTO:
                case StorageClass.EXTERN:
                    state.GLOBL(this.name);
                    break;
                case StorageClass.STATIC:
                    // static definition
                    break;
                default:
                    throw new InvalidOperationException();
                }
                break;
            default:
                throw new InvalidOperationException();
            }
            state.CGenFuncStart(this.name);

            state.InFunction(GotoLabelsGrabber.GrabLabels(this.stmt));

            this.stmt.CGenStmt(env, state);

            state.CGenLabel(state.ReturnLabel);
            state.OutFunction();

            //     leave
            //     ret
            state.LEAVE();
            state.RET();
            state.NEWLINE();
        }
 public ConstDouble(Double value, Env env)
     : base(env) {
     this.Value = value;
 }
Beispiel #5
0
 public Variable(ExprType type, String name, Env env) {
     this.Name = name;
     this.Env = env;
     this.Type = type;
 }
Beispiel #6
0
        // MakeCast
        // ========
        // input: Expr, Type
        // output: TypeCast
        // converts Expr to Type
        // 
        public static Expr MakeCast(Expr expr, ExprType type, Env env) {

            // if two types are equal, return Expr
            if (EqualType(expr.Type, type)) {
                return expr;
            }

            // from pointer
            if (expr.Type.Kind == ExprTypeKind.POINTER) {
                return FromPointer(expr, type, env);
            }

            // to pointer
            if (type.Kind == ExprTypeKind.POINTER) {
                return ToPointer(expr, type, env);
            }

            switch (expr.Type.Kind) {
                // from signed integral
                case ExprTypeKind.CHAR:
                case ExprTypeKind.SHORT:
                case ExprTypeKind.LONG:
                    return SignedIntegralToArith(expr, type);

                // from unsigned integral
                case ExprTypeKind.UCHAR:
                case ExprTypeKind.USHORT:
                case ExprTypeKind.ULONG:
                    return UnsignedIntegralToArith(expr, type);

                // from float
                case ExprTypeKind.FLOAT:
                case ExprTypeKind.DOUBLE:
                    return FloatToArith(expr, type);

                case ExprTypeKind.VOID:
                case ExprTypeKind.POINTER:
                case ExprTypeKind.FUNCTION:
                case ExprTypeKind.ARRAY:
                case ExprTypeKind.INCOMPLETE_ARRAY:
                case ExprTypeKind.STRUCT_OR_UNION:
                default:
                    throw new InvalidOperationException("Error: expression Type not supported for casting from.");
            }

        }
Beispiel #7
0
        /// <summary>
        /// From:
        ///     pointer
        /// To:
        ///     pointer, integral
        /// </summary>
        public static Expr FromPointer(Expr expr, ExprType type, Env env) {
            ExprTypeKind from = expr.Type.Kind;
            ExprTypeKind to = type.Kind;

            if (from != ExprTypeKind.POINTER) {
                throw new InvalidOperationException("Expected a pointer.");
            }

            // if we are casting to another pointer, do a nop
            if (to == ExprTypeKind.POINTER) {
                if (expr.IsConstExpr) {
                    return new ConstPtr(((ConstPtr)expr).Value, type, env);
                }
                return new TypeCast(TypeCastType.NOP, expr, type, env);
            }

            // if we are casting to an integral
            if (type.IsIntegral) {
                // pointer -> ulong -> whatever integral
                if (expr.IsConstExpr) {
                    expr = new ConstULong(((ConstPtr)expr).Value, env);
                } else {
                    expr = new TypeCast(TypeCastType.NOP, expr, new ULongType(type.IsConst, type.IsVolatile), env);
                }
                return MakeCast(expr, type, env);
            }

            throw new InvalidOperationException("Casting from a pointer to an unsupported Type.");
        }
Beispiel #8
0
 public Reg CGenExprStmt(Env env, Expr expr, CGenState state) {
     Int32 stack_size = state.StackSize;
     Reg ret = expr.CGenValue(state);
     state.CGenForceStackSizeTo(stack_size);
     return ret;
 }
 public ConstPtr(UInt32 value, ExprType type, Env env)
     : base(env) {
     this.Value = value;
     this.Type = type;
 }
Beispiel #10
0
 protected ConstExpr(Env env) {
     this.Env = env;
 }
Beispiel #11
0
 public ConstUChar(Byte value, Env env)
     : base(env) {
     this.Value = value;
 }
Beispiel #12
0
 public ConstUShort(UInt16 value, Env env)
     : base(env) {
     this.Value = value;
 }
Beispiel #13
0
 public ConstULong(UInt32 value, Env env)
     : base(env) {
     this.Value = value;
 }
Beispiel #14
0
 public ConstStringLiteral(String value, Env env)
     : base(env) {
     this.Value = value;
 }
Beispiel #15
0
 public override void CGenStmt(Env env, CGenState state) {
     state.CGenLabel(state.GotoLabel(this.Label));
     state.CGenForceStackSizeTo(state.StackSize);
     this.Stmt.CGenStmt(env, state);
 }
Beispiel #16
0
 public override void CGenStmt(Env env, CGenState state) {
     Int32 label = state.BreakLabel;
     state.JMP(label);
 }
Beispiel #17
0
        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);
        }
Beispiel #18
0
 public abstract void CGenStmt(Env env, CGenState state);
Beispiel #19
0
        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);
        }
Beispiel #20
0
        public override void CGenStmt(Env env, CGenState state) {
            ExprType ret_type = env.GetCurrentFunction().ReturnType;

            Int32 stack_size = state.StackSize;

            if (this.ExprOpt.IsSome) {
                // Evaluate the Value.
                this.ExprOpt.Value.CGenValue(state);

                // If the function returns a struct, copy it to the address given by 8(%ebp).
                if (this.ExprOpt.Value.Type is StructOrUnionType) {
                    state.MOVL(Reg.EAX, Reg.ESI);
                    state.MOVL(2 * ExprType.SIZEOF_POINTER, Reg.EBP, Reg.EDI);
                    state.MOVL(this.ExprOpt.Value.Type.SizeOf, Reg.ECX);
                    state.CGenMemCpy();
                    state.MOVL(2 * ExprType.SIZEOF_POINTER, Reg.EBP, Reg.EAX);
                }

                // Restore stack size.
                state.CGenForceStackSizeTo(stack_size);
            }
            // Jump to end of the function.
            state.JMP(state.ReturnLabel);
        }
Beispiel #21
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);
        }
Beispiel #22
0
 private TypeCast(TypeCastType kind, Expr expr, ExprType type, Env env) {
     this.Expr = expr;
     this.Kind = kind;
     this.Type = type;
     this.Env = env;
 }
Beispiel #23
0
 public override void CGenStmt(Env env, CGenState state) {
     Int32 label = state.CaseLabel(this.Value);
     state.CGenLabel(label);
     this.Stmt.CGenStmt(env, state);
 }
Beispiel #24
0
        /// <summary>
        /// From:
        ///     pointer, integral
        /// To:
        ///     pointer
        /// </summary>
        public static Expr ToPointer(Expr expr, ExprType type, Env env) {
            ExprTypeKind from = expr.Type.Kind;
            ExprTypeKind to = type.Kind;

            if (to != ExprTypeKind.POINTER) {
                throw new InvalidOperationException("Error: expected casting to pointer.");
            }

            if (from == ExprTypeKind.POINTER) {
                if (expr.IsConstExpr) {
                    return new ConstPtr(((ConstPtr)expr).Value, type, env);
                }
                return new TypeCast(TypeCastType.NOP, expr, type, env);
            }

            if (expr.Type.IsIntegral) {
                // if we are casting from an integral

                // whatever integral -> ulong
                switch (expr.Type.Kind) {
                    case ExprTypeKind.CHAR:
                    case ExprTypeKind.SHORT:
                    case ExprTypeKind.LONG:
                        expr = SignedIntegralToArith(expr, new ULongType(type.IsConst, type.IsVolatile));
                        break;
                    case ExprTypeKind.UCHAR:
                    case ExprTypeKind.USHORT:
                    case ExprTypeKind.ULONG:
                        expr = UnsignedIntegralToArith(expr, new ULongType(type.IsConst, type.IsVolatile));
                        break;
                    default:
                        break;
                }

                // ulong -> pointer
                if (expr.IsConstExpr) {
                    return new ConstPtr(((ConstULong)expr).Value, type, env);
                }
                return new TypeCast(TypeCastType.NOP, expr, type, env);
            }
            if (expr.Type is FunctionType) {
                if (!expr.Type.EqualType(((PointerType)type).RefType)) {
                    throw new InvalidOperationException("Casting from an incompatible function.");
                }

                // TODO: only allow compatible Type?
                return new TypeCast(TypeCastType.NOP, expr, type, env);

            }
            if (expr.Type is ArrayType) {

                // TODO: allow any pointer Type to cast to?
                return new TypeCast(TypeCastType.NOP, expr, type, env);
            }

            throw new InvalidOperationException("Error: casting from an unsupported Type to pointer.");
        }
Beispiel #25
0
 public override void CGenStmt(Env env, CGenState state) {
     Int32 label = state.DefaultLabel;
     state.CGenLabel(label);
     this.Stmt.CGenStmt(env, state);
 }
Beispiel #26
0
        public override void CGenStmt(Env env, CGenState state) {
            Reg ret = CGenExprStmt(env, this.Cond, state);

            CGenTest(ret, state);

            Int32 false_label = state.RequestLabel();
            Int32 finish_label = state.RequestLabel();

            state.JZ(false_label);

            this.TrueStmt.CGenStmt(env, state);

            state.JMP(finish_label);

            state.CGenLabel(false_label);

            this.FalseStmt.CGenStmt(env, state);

            state.CGenLabel(finish_label);
        }
Beispiel #27
0
 public override void CGenStmt(Env env, CGenState state) {
     Int32 label = state.GotoLabel(this.Label);
     state.JMP(label);
 }
Beispiel #28
0
        // * function;
        // * extern function;
        // * static function;
        // * obj;
        // * obj = Init;
        // * static obj;
        // * static obj = Init;
        // * extern obj;
        // * extern obj = Init;
        public void CGenDecln(Env env, CGenState state) {

            if (env.IsGlobal()) {

                if (this.initr.IsSome) {
                    Initr initr = this.initr.Value;
                    switch (this.scs) {
                        case StorageClass.AUTO:
                            state.GLOBL(this.name);
                            break;

                        case StorageClass.EXTERN:
                            throw new InvalidProgramException();

                        case StorageClass.STATIC:
                            break;

                        case StorageClass.TYPEDEF:
                            // Ignore.
                            return;

                        default:
                            throw new InvalidProgramException();
                    }

                    state.DATA();

                    state.ALIGN(ExprType.ALIGN_LONG);

                    state.CGenLabel(this.name);

                    Int32 last = 0;
                    initr.Iterate(this.type, (Int32 offset, Expr expr) => {
                        if (offset > last) {
                            state.ZERO(offset - last);
                        }

                        if (!expr.IsConstExpr) {
                            throw new InvalidOperationException("Cannot initialize with non-const expression.");
                        }

                        switch (expr.Type.Kind) {
                            // TODO: without const char/short, how do I initialize?
                            case ExprTypeKind.CHAR:
                            case ExprTypeKind.UCHAR:
                            case ExprTypeKind.SHORT:
                            case ExprTypeKind.USHORT:
                                throw new NotImplementedException();
                            case ExprTypeKind.LONG:
                                state.LONG(((ConstLong)expr).Value);
                                break;

                            case ExprTypeKind.ULONG:
                                state.LONG((Int32)((ConstULong)expr).Value);
                                break;

                            case ExprTypeKind.POINTER:
                                state.LONG((Int32)((ConstPtr)expr).Value);
                                break;

                            case ExprTypeKind.FLOAT:
                                byte[] float_bytes = BitConverter.GetBytes(((ConstFloat)expr).Value);
                                Int32 intval = BitConverter.ToInt32(float_bytes, 0);
                                state.LONG(intval);
                                break;

                            case ExprTypeKind.DOUBLE:
                                byte[] double_bytes = BitConverter.GetBytes(((ConstDouble)expr).Value);
                                Int32 first_int = BitConverter.ToInt32(double_bytes, 0);
                                Int32 second_int = BitConverter.ToInt32(double_bytes, 4);
                                state.LONG(first_int);
                                state.LONG(second_int);
                                break;

                            default:
                                throw new InvalidProgramException();
                        }

                        last = offset + expr.Type.SizeOf;
                    });

                } else {

                    // Global without initialization.

                    switch (this.scs) {
                        case StorageClass.AUTO:
                            // .comm name,size,align
                            break;

                        case StorageClass.EXTERN:
                            break;

                        case StorageClass.STATIC:
                            // .local name
                            // .comm name,size,align
                            state.LOCAL(this.name);
                            break;

                        case StorageClass.TYPEDEF:
                            // Ignore.
                            return;

                        default:
                            throw new InvalidProgramException();
                    }

                    if (this.type.Kind != ExprTypeKind.FUNCTION) {
                        state.COMM(this.name, this.type.SizeOf, ExprType.ALIGN_LONG);
                    }

                    
                }

                state.NEWLINE();

            } else {
                // stack object

                state.CGenExpandStackTo(env.StackSize, ToString());

                Int32 stack_size = env.StackSize;

                // pos should be equal to stack_size, but whatever...
                Int32 pos = env.Find(this.name).Value.Offset;
                if (this.initr.IsNone) {
                    return;
                }

                Initr initr = this.initr.Value;
                initr.Iterate(this.type, (Int32 offset, Expr expr) => {
                    Reg ret = expr.CGenValue(state);
                    switch (expr.Type.Kind) {
                        case ExprTypeKind.CHAR:
                        case ExprTypeKind.UCHAR:
                            state.MOVB(Reg.EAX, pos + offset, Reg.EBP);
                            break;

                        case ExprTypeKind.SHORT:
                        case ExprTypeKind.USHORT:
                            state.MOVW(Reg.EAX, pos + offset, Reg.EBP);
                            break;

                        case ExprTypeKind.DOUBLE:
                            state.FSTPL(pos + offset, Reg.EBP);
                            break;

                        case ExprTypeKind.FLOAT:
                            state.FSTPS(pos + offset, Reg.EBP);
                            break;

                        case ExprTypeKind.LONG:
                        case ExprTypeKind.ULONG:
                        case ExprTypeKind.POINTER:
                            state.MOVL(Reg.EAX, pos + offset, Reg.EBP);
                            break;

                        case ExprTypeKind.STRUCT_OR_UNION:
                            state.MOVL(Reg.EAX, Reg.ESI);
                            state.LEA(pos + offset, Reg.EBP, Reg.EDI);
                            state.MOVL(expr.Type.SizeOf, Reg.ECX);
                            state.CGenMemCpy();
                            break;

                        case ExprTypeKind.ARRAY:
                        case ExprTypeKind.FUNCTION:
                            throw new InvalidProgramException($"How could a {expr.Type.Kind} be in a init list?");

                        default:
                            throw new InvalidProgramException();
                    }

                    state.CGenForceStackSizeTo(stack_size);

                });

            } // stack object
        }
Beispiel #29
0
 public ConstFloat(Single value, Env env)
     : base(env) {
     this.Value = value;
 }