Ejemplo n.º 1
0
        void GenStatement(AST n, IList <Tuple <string, FrontEnd.CbType, int, int> > LocalVariables)
        {
            Loc variable;

            switch (n.Tag)
            {
            case NodeType.Assign:
                // DONE ; NEEDS CHECKING
                int reg;
                Loc lhs = GenVariable(n[0], LocalVariables);        // LHS

                // check for call
                if (n[1].Tag == NodeType.Call)
                {
                    GenStatement(n[1], LocalVariables);             // RHS
                    reg = 1;
                }
                else
                {
                    reg = GenExpression(n[1], LocalVariables);              // RHS
                }
                if (lhs.Type == MemType.Word || lhs.Type == MemType.Byte)
                {
                    Asm.Append("str", Loc.RegisterName(reg), lhs);
                }
                else
                {
                    throw new Exception("unsupported memory type " + lhs.Type.ToString());
                }
                freeReg(reg);
                break;

            case NodeType.LocalDecl:
                // DONE ; NEEDS CHECKING

                int offset;
                int typeSize;
                if (n[0].Type == FrontEnd.CbType.Int || n[0].Type == FrontEnd.CbType.String || n[0].Type is FrontEnd.CbArray)
                {
                    typeSize = 4;
                }
                else if (n[0].Type is FrontEnd.CbStruct)
                {
                    typeSize = getTypeSize(n[0].Type);
                }
                else     // unknown
                {
                    throw new Exception(string.Format("Unknown local declaration type '{0}'", n[0].Type));
                }

                // add newly declared variables to array
                for (int i = 0; i < n[1].NumChildren; i++)
                {
                    offset = getNextOffset(LocalVariables);
                    LocalVariables.Add(Tuple.Create(((AST_leaf)n[1][i]).Sval, n[0].Type, offset, typeSize));
                }

                break;

            case NodeType.Block:
                // DONE
                for (int i = 0; i < n.NumChildren; i++)
                {
                    GenStatement(n[i], LocalVariables);
                }
                break;

            case NodeType.Read:
                // DONE
                variable = GenVariable(n[1], LocalVariables);
                Asm.Append("bl", "cb.ReadInt");
                Asm.Append("str", Loc.RegisterName(0), variable);
                break;

            case NodeType.Call:
                // Note the special case: cbio.Write(x) where x is an int or a string expression.
                // The argument x must be loaded into register r0 and then a bl instruction
                // with cb.WriteInt or cb.WriteString as the destination must be generated.
                // Otherwise for a call to a method in the CFlat program, the actual parameters
                // should be evaluated in reverse order and pushed onto the stack; then a
                // bl instruction to the method generated; that is followed by an add immediate
                // instruction to pop the stack of all the parameters.

                // cbio.Write(x)
                if (n[0].Tag == NodeType.Dot)
                {
                    int regw = GenExpression(n[1][0], LocalVariables);
                    Asm.Append("mov", "r0", Loc.RegisterName(regw));
                    // print integer
                    if (n[1][0].Type == FrontEnd.CbType.Int)
                    {
                        Asm.Append("bl", "cb.WriteInt");
                    }
                    // print string
                    else if (n[1][0].Type == FrontEnd.CbType.String)
                    {
                        Asm.Append("bl", "cb.WriteString");
                    }
                    else
                    {
                        throw new Exception("Invalid parameter to cbio.Write: " + n[1][0].Tag.ToString());
                    }
                    freeReg(regw);
                }
                // regular method call
                else
                {
                    int tmpr = getReg();

                    AST param     = n[1];
                    int totalSize = 0;
                    for (int i = 0; i < param.NumChildren; i++)
                    {
                        int size = getTypeSize(param[i].Type);
                        totalSize += size;

                        int register = GenExpression(param[i], LocalVariables);
                        variable = new LocRegOffset(sp, -size, MemType.Word);
                        Asm.Append("str", Loc.RegisterName(register), variable + "!");
                    }
                    Console.WriteLine("Calculated {0} bytes required for parameters of method '{1}'", totalSize, ((AST_leaf)n[0]).Sval);

                    // go to method
                    Asm.Append("bl", ((AST_leaf)n[0]).Sval);
                    // pop bytes off stack
                    Asm.Append("add", "sp", "sp", "#" + totalSize.ToString());
                    // move result out of scratch register
                    Asm.Append("mov", Loc.RegisterName(tmpr), "r0");
                    // store result in local variable
                    variable = new LocRegOffset(fp, -totalSize, MemType.Byte);
                    Asm.Append("str", Loc.RegisterName(tmpr), variable);
                    Console.WriteLine("Method call register r{0}", tmpr);
                    freeReg(tmpr);
                }

                break;

            case NodeType.Return:
                // DONE ; NEEDS CHECKING ; MAYBE NEEDS TO DO A LOT MORE
                // load result into r1 if something is returned
                if (n.NumChildren > 0)       // FIX ME: "n[0].Tag != CbType.Empty" does not work
                {
                    int ret = GenExpression(n[0], LocalVariables);
                    Asm.Append("mov", Loc.RegisterName(1), Loc.RegisterName(ret));
                }

                // return statement is a transfer to the label held in 'returnLabel'
                Asm.Append("b", returnLabel);
                break;

            case NodeType.PlusPlus:
                // DONE
                int    pp   = GenExpression(n[0], LocalVariables);
                string preg = Loc.RegisterName(pp);
                Asm.Append("add", preg, preg, "#1");
                freeReg(pp);
                break;

            case NodeType.MinusMinus:
                // DONE
                int    mm   = GenExpression(n[0], LocalVariables);
                string mreg = Loc.RegisterName(mm);
                Asm.Append("sub", mreg, mreg, "#1");
                freeReg(mm);
                break;

            case NodeType.If:
                // DONE
                string tl   = getNewLabel();
                string lend = getNewLabel();

                // no else statement
                if (n[2].Tag == NodeType.Empty)
                {
                    // if
                    GenConditional(n[0], tl, lend, LocalVariables);
                    // then
                    Asm.AppendLabel(tl);
                    GenStatement(n[1], LocalVariables);
                    Asm.Append("b", lend);
                }
                // else statement
                else
                {
                    string fl = getNewLabel();
                    // if
                    GenConditional(n[0], tl, fl, LocalVariables);
                    // then
                    Asm.AppendLabel(tl);
                    GenStatement(n[1], LocalVariables);
                    Asm.Append("b", lend);
                    // else
                    Asm.AppendLabel(fl);
                    GenStatement(n[2], LocalVariables);
                }
                // end of if statement
                Asm.AppendLabel(lend);
                break;

            case NodeType.While:
                // DONE ; NEEDS CHECKING
                string wcond  = getNewLabel();
                string wstart = getNewLabel();
                string wend   = getNewLabel();

                // while
                Asm.AppendLabel(wcond);
                GenConditional(n[0], wstart, wend, LocalVariables);
                // then do
                Asm.AppendLabel(wstart);
                GenStatement(n[1], LocalVariables);
                Asm.Append("b", wcond);
                // end of loop
                Asm.AppendLabel(wend);
                break;

            case NodeType.Break:
                // DONE ; NEEDS CHECKING ; MIGHT NEED TO DO A LOT MORE
                Asm.Append("b", returnLabel);
                break;

            case NodeType.Empty:
                // DONE
                // no code to generate!
                break;

            default:
                throw new Exception("Unexpected tag: " + n.Tag.ToString());
            }
        }
Ejemplo n.º 2
0
        /********************** AST Traversal Methods ************************/

        int GenExpression(AST n, IList <Tuple <string, FrontEnd.CbType, int, int> > LocalVariables)
        {
            int result = 0;
            int lhs, rhs;
            Loc mem;

            switch (n.Tag)
            {
            case NodeType.Ident:
                // DONE ; NEEDS CHECKING
                mem    = GenVariable(n, LocalVariables);
                result = getReg();
                Asm.Append("ldr", Loc.RegisterName(result), mem);
                break;

            case NodeType.Dot:
                // DONE ; NEEDS CHECKING
                mem    = GenVariable(n, LocalVariables);
                result = getReg();
                Asm.Append("ldr", Loc.RegisterName(result), mem);
                break;

            case NodeType.Index:
                // DONE
                mem    = GenVariable(n, LocalVariables);
                result = getReg();
                Asm.Append("ldr", Loc.RegisterName(result), mem);
                break;

            case NodeType.Add:
                // DONE
                result = lhs = GenExpression(n[0], LocalVariables);
                rhs    = GenExpression(n[1], LocalVariables);
                Asm.Append("add", Loc.RegisterName(lhs), Loc.RegisterName(lhs),
                           Loc.RegisterName(rhs));
                freeReg(rhs);
                break;

            case NodeType.StringConst:
                // DONE
                result = getReg();
                string slab = createStringConstant(((AST_leaf)n).Sval);
                Asm.Append("ldr", Loc.RegisterName(result), "=" + slab);
                break;

            case NodeType.UnaryMinus:
                // DONE
                result = lhs = GenExpression(n[0], LocalVariables);
                Asm.Append("rsb", Loc.RegisterName(lhs), Loc.RegisterName(lhs), "#0");
                break;

            case NodeType.Sub:
                // DONE
                result = lhs = GenExpression(n[0], LocalVariables);
                rhs    = GenExpression(n[1], LocalVariables);
                Asm.Append("sub", Loc.RegisterName(lhs), Loc.RegisterName(lhs),
                           Loc.RegisterName(rhs));
                freeReg(rhs);
                break;

            case NodeType.Mul:
                // DONE
                lhs    = GenExpression(n[0], LocalVariables);
                rhs    = GenExpression(n[1], LocalVariables);
                result = getReg();
                Asm.Append("mul", Loc.RegisterName(result), Loc.RegisterName(lhs),
                           Loc.RegisterName(rhs));
                freeReg(lhs);
                freeReg(rhs);
                break;

            case NodeType.Div:
                // DONE
                result = lhs = GenExpression(n[0], LocalVariables);
                rhs    = GenExpression(n[1], LocalVariables);
                Asm.Append("mov", "r0", Loc.RegisterName(lhs));
                Asm.Append("mov", "r1", Loc.RegisterName(rhs));
                Asm.Append("bl", "cb.DivMod");
                Asm.Append("mov", Loc.RegisterName(lhs), "r0");
                freeReg(rhs);
                break;

            case NodeType.Mod:
                // DONE
                result = lhs = GenExpression(n[0], LocalVariables);
                rhs    = GenExpression(n[1], LocalVariables);
                Asm.Append("mov", "r0", Loc.RegisterName(lhs));
                Asm.Append("mov", "r1", Loc.RegisterName(rhs));
                Asm.Append("bl", "cb.DivMod");
                Asm.Append("mov", Loc.RegisterName(lhs), "r1");
                freeReg(rhs);
                break;

            case NodeType.IntConst:
                // DONE
                result = getReg();
                int val = ((AST_leaf)n).Ival;
                if (255 >= val && val >= 0)
                {
                    Asm.Append("mov", Loc.RegisterName(result), "#" + val.ToString());
                }
                else if (-255 <= val && val < 0)
                {
                    Asm.Append("mvn", Loc.RegisterName(result), "#" + (-val).ToString());
                }
                else
                {
                    Asm.Append("ldr", Loc.RegisterName(result), "=" + val.ToString());
                }
                break;

            case NodeType.NewStruct:
                notImplemented(n, "GenExpression");
                break;

            case NodeType.NewArray:
                // DONE ; NEEDS CHECKING
                // calculate heap space needed (4 bytes for length of array, and 'size' bytes for each element)
                int length = ((AST_leaf)n[1]).Ival;
                int size   = getTypeSize(n[0].Type);
                int space  = (length * size) + 4;
                int reg    = getReg();
                Asm.Append("mov", "r0", "#" + space.ToString());
                // request space from the malloc routine
                Asm.Append("bl", "cb.Malloc");
                Asm.Append("mov", Loc.RegisterName(reg), "#" + length.ToString());
                // store array size in first word, and advance pointer to first element
                mem = new LocRegOffset(0, size, MemType.Word);
                Asm.Append("str", Loc.RegisterName(reg), mem);
                freeReg(reg);
                result = 0;
                break;

            default:
                throw new Exception("Unexpected tag: " + n.Tag.ToString());
            }
            return(result);
        }
Ejemplo n.º 3
0
        Loc GenVariable(AST n, IList <Tuple <string, FrontEnd.CbType, int, int> > LocalVariables)
        {
            Loc     result = null;
            int     lhs, offset = 0;
            MemType mtyp;

            switch (n.Tag)
            {
            case NodeType.Ident:
                // The ident must be a local variable or a formal parameter.
                // In either case, the memory location is at an offset from
                // the frame pointer register.

                // determine offset
                offset = getOffset(LocalVariables, ((AST_leaf)n).Sval);
                Console.WriteLine("Offset: {0}", offset);
                // local variable
                if (offset != -1)
                {
                    result = new LocRegOffset(fp, -offset, MemType.Word);
                }
                else
                {
                    int reg = getReg();
                    Asm.Append("ldr", Loc.RegisterName(reg), "=" + ((AST_leaf)n).Sval);
                    result = new LocRegOffset(reg, 0, MemType.Word);
                }

                break;

            case NodeType.Dot:
                // FIX ME

                // case where expression is String.Length
                if (n[0].Type == FrontEnd.CbType.String)
                {
                    lhs = getReg();
                    int reg = GenExpression(n[0], LocalVariables);
                    Asm.Append("mov", "r0", Loc.RegisterName(reg));
                    Asm.Append("bl", "cb.StrLen");
                    offset = 0;
                    mtyp   = MemType.Word;
                }
                // case where expression is Array.Length
                else if (n[0].Type is FrontEnd.CbArray)
                {
                    lhs    = GenExpression(n[0], LocalVariables);
                    offset = -4;
                    mtyp   = MemType.Word;
                }
                // case where expression is Struct.Field
                else if (n[0].Type is FrontEnd.CbStruct)
                {
                    // FIX ME
                    // The left operand must be an expression with a struct type.
                    // The right operand must be the name of a field in that struct.
                    // The code should set result to a LocRegOffset instance where
                    // the register comes from n[0] and the offset from n[1].

                    // get memory location of struct
                    lhs = GenExpression(n[0], LocalVariables);

                    string structName = getStructName(n[0].Type);
                    string fieldName  = ((AST_leaf)n[1]).Sval;

                    offset = -1;
                    Dictionary <string, Tuple <int, int> > fields;
                    if (structs.TryGetValue(structName, out fields))
                    {
                        Tuple <int, int> properties;
                        if (fields.TryGetValue(fieldName, out properties))
                        {
                            offset = properties.Item1;
                        }
                    }
                    if (offset == -1)
                    {
                        throw new Exception(string.Format("Struct {0} does not contain field '{1}'; Line {2}", structName, fieldName, n.LineNumber));
                    }

                    offset = -offset;
                    mtyp   = MemType.Word;
                }
                else
                {
                    throw new Exception("Unknown Dot operation with left node type " + n[0].Type.ToString());
                }

                result = new LocRegOffset(lhs, offset, mtyp);
                break;

            case NodeType.Index:
                // The left operand must be an expression with an array or string type
                // The right operand must be an int expression to use as an index.
                // The code should set result to a LocRegIndex instance where
                // the register comes from n[0] and the offset from n[1].
                lhs = GenExpression(n[0], LocalVariables);

                // get the offset
                offset = GenExpression(n[1], LocalVariables);
                Asm.Append("add", Loc.RegisterName(offset), "#1");
                // struct
                if (n[0].Tag == NodeType.Dot)
                {
                    int typeSize = getTypeSize(n[0].Type);          // FIX ME: does this work?
                    Asm.Append("ldr", "r1", "=" + typeSize.ToString());
                    Asm.Append("rsb", "r1", "r1", "#0");
                    Asm.Append("mul", Loc.RegisterName(offset), Loc.RegisterName(offset), "r1");
                }
                // regular array
                else
                {
                    Asm.Append("ldr", "r2", "=-4");
                    Asm.Append("mul", Loc.RegisterName(offset), Loc.RegisterName(offset), "r1");
                }

                mtyp   = MemType.Byte;
                result = new LocRegIndex(lhs, offset, mtyp);

                break;
            }
            return(result);
        }