Exemple #1
0
        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();
        }
Exemple #2
0
        public override void CGenAddress(CGenState state)
        {
            Env.Entry entry  = this.Env.Find(this.Name).Value;
            Int32     offset = entry.Offset;

            switch (entry.Kind)
            {
            case Env.EntryKind.FRAME:
            case Env.EntryKind.STACK:
                state.LEA(offset, Reg.EBP, Reg.EAX);
                return;

            case Env.EntryKind.GLOBAL:
                state.LEA(this.Name, Reg.EAX);
                return;

            case Env.EntryKind.ENUM:
            case Env.EntryKind.TYPEDEF:
            default:
                throw new InvalidProgramException("cannot get the address of " + entry.Kind);
            }
        }
Exemple #3
0
        public override Reg CGenValue(CGenState state)
        {
            Env.Entry entry = this.Env.Find(this.Name).Value;

            Int32 offset = entry.Offset;

            //if (entry.Kind == Env.EntryKind.STACK) {
            //    offset = -offset;
            //}

            switch (entry.Kind)
            {
            case Env.EntryKind.ENUM:
                // 1. If the variable is an enum constant,
                //    return the Value in %eax.
                state.MOVL(offset, Reg.EAX);
                return(Reg.EAX);

            case Env.EntryKind.FRAME:
            case Env.EntryKind.STACK:
                // 2. If the variable is a function argument or a local variable,
                //    the address would be offset(%ebp).
                switch (this.Type.Kind)
                {
                case ExprTypeKind.LONG:
                case ExprTypeKind.ULONG:
                case ExprTypeKind.POINTER:
                    // %eax = offset(%ebp)
                    state.MOVL(offset, Reg.EBP, Reg.EAX);
                    return(Reg.EAX);

                case ExprTypeKind.FLOAT:
                    // %st(0) = offset(%ebp)
                    state.FLDS(offset, Reg.EBP);
                    return(Reg.ST0);

                case ExprTypeKind.DOUBLE:
                    // %st(0) = offset(%ebp)
                    state.FLDL(offset, Reg.EBP);
                    return(Reg.ST0);

                case ExprTypeKind.STRUCT_OR_UNION:
                    // %eax = address
                    state.LEA(offset, Reg.EBP, Reg.EAX);
                    return(Reg.EAX);

                //state.LEA(offset, Reg.EBP, Reg.ESI); // source address
                //state.CGenExpandStackBy(Utils.RoundUp(Type.SizeOf, 4));
                //state.LEA(0, Reg.ESP, Reg.EDI); // destination address
                //state.MOVL(Type.SizeOf, Reg.ECX); // nbytes
                //state.CGenMemCpy();
                //return Reg.STACK;

                case ExprTypeKind.VOID:
                    throw new InvalidProgramException("How could a variable be void?");
                // %eax = $0
                // state.MOVL(0, Reg.EAX);
                // return Reg.EAX;

                case ExprTypeKind.FUNCTION:
                    throw new InvalidProgramException("How could a variable be a function designator?");
                // %eax = function_name
                // state.MOVL(name, Reg.EAX);
                // return Reg.EAX;

                case ExprTypeKind.CHAR:
                    // %eax = [char -> long](off(%ebp))
                    state.MOVSBL(offset, Reg.EBP, Reg.EAX);
                    return(Reg.EAX);

                case ExprTypeKind.UCHAR:
                    // %eax = [uchar -> ulong](off(%ebp))
                    state.MOVZBL(offset, Reg.EBP, Reg.EAX);
                    return(Reg.EAX);

                case ExprTypeKind.SHORT:
                    // %eax = [short -> long](off(%ebp))
                    state.MOVSWL(offset, Reg.EBP, Reg.EAX);
                    return(Reg.EAX);

                case ExprTypeKind.USHORT:
                    // %eax = [ushort -> ulong](off(%ebp))
                    state.MOVZWL(offset, Reg.EBP, Reg.EAX);
                    return(Reg.EAX);

                case ExprTypeKind.ARRAY:
                    // %eax = (off(%ebp))
                    state.LEA(offset, Reg.EBP, Reg.EAX);         // source address
                    return(Reg.EAX);

                default:
                    throw new InvalidOperationException($"Cannot get value of {this.Type.Kind}");
                }

            case Env.EntryKind.GLOBAL:
                switch (this.Type.Kind)
                {
                case ExprTypeKind.CHAR:
                    state.MOVSBL(this.Name, Reg.EAX);
                    return(Reg.EAX);

                case ExprTypeKind.UCHAR:
                    state.MOVZBL(this.Name, Reg.EAX);
                    return(Reg.EAX);

                case ExprTypeKind.SHORT:
                    state.MOVSWL(this.Name, Reg.EAX);
                    return(Reg.EAX);

                case ExprTypeKind.USHORT:
                    state.MOVZWL(this.Name, Reg.EAX);
                    return(Reg.EAX);

                case ExprTypeKind.LONG:
                case ExprTypeKind.ULONG:
                case ExprTypeKind.POINTER:
                    state.MOVL(this.Name, Reg.EAX);
                    return(Reg.EAX);

                case ExprTypeKind.FUNCTION:
                    state.MOVL("$" + this.Name, Reg.EAX);
                    return(Reg.EAX);

                case ExprTypeKind.FLOAT:
                    state.FLDS(this.Name);
                    return(Reg.ST0);

                case ExprTypeKind.DOUBLE:
                    state.FLDL(this.Name);
                    return(Reg.ST0);

                case ExprTypeKind.STRUCT_OR_UNION:
                    state.MOVL($"${this.Name}", Reg.EAX);
                    return(Reg.EAX);

                //state.LEA(name, Reg.ESI); // source address
                //state.CGenExpandStackBy(Utils.RoundUp(Type.SizeOf, 4));
                //state.LEA(0, Reg.ESP, Reg.EDI); // destination address
                //state.MOVL(Type.SizeOf, Reg.ECX); // nbytes
                //state.CGenMemCpy();
                //return Reg.STACK;

                case ExprTypeKind.VOID:
                    throw new InvalidProgramException("How could a variable be void?");
                //state.MOVL(0, Reg.EAX);
                //return Reg.EAX;

                case ExprTypeKind.ARRAY:
                    state.MOVL($"${this.Name}", Reg.EAX);
                    return(Reg.EAX);

                default:
                    throw new InvalidProgramException("cannot get the Value of a " + this.Type.Kind);
                }

            case Env.EntryKind.TYPEDEF:
            default:
                throw new InvalidProgramException("cannot get the Value of a " + entry.Kind);
            }
        }