Пример #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());
            }
        }
Пример #2
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;
        }
Пример #3
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;
        }