Beispiel #1
0
        public override bool Equals(object obj)
        {
            ArrayVarType v2 = (obj as ArrayVarType);

            if (v2 == null)
            {
                return(false);
            }
            return(baseType.Equals(v2.baseType) && this.arrayDimensions.SequenceEqual(v2.arrayDimensions));
        }
Beispiel #2
0
    /// <summary>
    /// array-access -> ID LB expr-list RB
    /// </summary>
    /// <param name="vinfo"></param>
    /// <param name="exprListNode"></param>
    private void putArrayAddressInRcx(VarInfo vinfo, TreeNode exprListNode)
    {
        ArrayVarType typ = vinfo.VType as ArrayVarType;

        if (typ == null)
        {
            throw new Exception("ICE!!! Arraytype cannot be null or typ not Array type!! tpy: " + typ == null ? "null" : typ.typeString);
        }

        List <VarType> types;

        exprlistNodeCode(exprListNode.Children[2], out types); //expr-list -> expr expr-list'
        if (types.Count != typ.arrayDimensions.Count)
        {
            throw new Exception("Error!! Arrays dimension mismatch!!");
        }

        foreach (var t in types)
        {
            if (t != VarType.NUMBER)
            {
                throw new Exception("Error!! only numbers are valid as array indices!! type: " + t.typeString);
            }
        }

        emit("mov rcx, 0");
        for (int i = 0; i < typ.arrayDimensions.Count; i++)
        {
            int product = 1;
            for (int j = i + 1; j < typ.arrayDimensions.Count; j++)
            {
                product *= typ.arrayDimensions[j];
            }
            emit("pop rax");                    //get next from expr-list
            emit("movq xmm0, rax");             //convert to double
            emit("cvtsd2si rax, xmm0");         //convert to int
            emit("imul rax, rax,{0}", product); //dest, op1, op2
            emit("add rcx, rax");
        }

        if (vinfo.isGlobal)
        {
            emit("shl rcx, 3"); //same as imul rcx, 8 but faster
            emit("add rcx, {0}", vinfo.Label);
        }
        else
        {
            emit("lea rcx, [rcx*8+{0}]", vinfo.Label);
        }
    }
Beispiel #3
0
    static void typeNodeCode(TreeNode n, out VarType type)
    {
        VarType t1;
        var     nonArrayTypeNode = n.Children[0];
        var     n2 = nonArrayTypeNode.Children[0];

        switch (n2.Symbol)
        {
        case "NUMBER":
            t1 = VarType.NUMBER;
            break;

        case "STRING":
            t1 = VarType.STRING;
            break;

        case "VOID":
            t1 = VarType.VOID;
            break;

        default:
            throw new Exception("Internal Compiler Error.");
        }

        if (n.Children.Count == 1)
        {
            type = t1;
        }
        else
        {
            List <int> dims;
            numlistNodeCode(n.Children[2], out dims);
            foreach (int i in dims)
            {
                if (i < 0)
                {
                    break;
                }
            }
            type = new ArrayVarType(t1, dims);
        }
    }
Beispiel #4
0
    /// <summary>
    /// type -> non-array-type | non-array-type LB num-list RB
    /// </summary>
    /// <param name="n"></param>
    /// <param name="type"></param>
    private void typeNodeCode(TreeNode n, out VarType type)
    {
        VarType t1;

        nonarraytypeNodeCode(n.Children[0], out t1);        //Get type
        if (n.Children.Count == 4)
        {
            List <int> dims;
            numlistNodeCode(n.Children[2], out dims);
            foreach (var i in dims)
            {
                if (i < 0)
                {
                    throw new Exception("Error!! Value is not positive!! i: " + i.ToString());
                }
            }
            type = new ArrayVarType(t1, dims);
        }
        else
        {
            type = t1;
        }
    }
Beispiel #5
0
    static void putArrayAddressInRcx(VarInfo vinfo, TreeNode n)
    {
        bool         isPointer = false;
        ArrayVarType typ       = vinfo.VType as ArrayVarType;

        if (typ == null)
        {
            typ       = (vinfo.VType as PointerVarType).pointedToType as ArrayVarType;
            isPointer = true;
            if (typ == null)
            {
                throw new Exception("Internal Compiler Error.");
            }
        }
        List <VarType> types;

        exprlistNodeCode(n, out types);
        if (types.Count != typ.arrayDimensions.Count)
        {
            throw new Exception("Array dimension mismatch.");
        }
        foreach (var t in types)
        {
            if (t != VarType.NUMBER)
            {
                throw new Exception("Only numbers can be array indices.");
            }
        }
        emit("mov rcx,0");
        for (int i = 0; i < typ.arrayDimensions.Count; ++i)
        {
            int product = 1;
            for (int j = i + 1; j < typ.arrayDimensions.Count; ++j)
            {
                product *= typ.arrayDimensions[j];
            }
            emit("pop rax");
            emit("movq xmm0,rax");
            emit("cvtsd2si rax,xmm0");

            var abortlbl  = label();
            var resumelbl = label();
            emit("mov rdx,{0}", typ.arrayDimensions[i]);
            emit("cmp rax,rdx");
            emit("jge {0}", abortlbl);
            emit("cmp rax,0");
            emit("jl {0}", abortlbl);
            emit("jmp {0}", resumelbl);
            emit("{0}:", abortlbl);
            emit("call abort");
            emit("{0}:", resumelbl);

            emit("imul rax,rax,{0}", product);
            emit("add rcx,rax");
        }

        if (vinfo.isGlobal)
        {
            emit("imul rcx,8");
            emit("add rcx,{0}", vinfo.Label);
        }
        else
        {
            if (isPointer)
            {
                emit("mov rax,[{0}]", vinfo.Label);
                emit("lea rcx, [rcx*8+rax]");
            }
            else
            {
                emit("lea rcx,[rcx*8+{0}]", vinfo.Label);
            }
        }
    }
Beispiel #6
0
    /// <summary>
    /// factor -> NUM | LP expr RP | STRING-CONSTANT | ID | func-call
    /// </summary>
    /// <param name="n"></param>
    /// <param name="type"></param>
    private void factorNodeCode(TreeNode n, out VarType type)
    {
        var child = n.Children[0];

        switch (child.Symbol)
        {
        case "NUM":
            makeDouble_and_push(child.Token.Lexeme);
            type = VarType.NUMBER;
            break;

        case "LP":
            exprNodeCode(n.Children[1], out type);
            break;

        case "STRING-CONSTANT":     //Stores the address of the string data on stack
            string lbl;
            stringconstantNodeCode(child, out lbl);
            emit("mov rax, {0}", lbl);
            emit("push rax");
            type = VarType.STRING;
            break;

        case "ID":
            string vname = n.Children[0].Token.Lexeme;
            if (!symtable.ContainsInCurrentScopes(vname))
            {
                symtable.printScopes();
                throw new Exception("ERROR!!! Undeclared Variable: " + vname);
            }
            VarInfo      vi   = symtable[vname];
            ArrayVarType atyp = vi.VType as ArrayVarType;
            if (vi.VType == VarType.NUMBER || vi.VType == VarType.STRING || atyp != null)
            {
                emit("mov rax,[{0}]", symtable[vname].Label);
                emit("push rax");
                type = vi.VType;
            }
            else
            {
                throw new Exception("ICE!!! Expected type NUMBER, STRING, or ARRAY. Recieved: " + vi.VType);
            }
            break;

        case "func-call":
            funccallNodeCode(child, out type);
            if (type == VarType.VOID)
            {
                throw new Exception("ICE!!! Can't use VOID in math expressions");
            }
            emit("push rax");
            break;

        case "array-access":
            vname = child.Children[0].Token.Lexeme;
            var vinfo = symtable[vname];
            if (vinfo == null)
            {
                throw new Exception("Error!!! Trying to access undeclared variable: " + vname);
            }

            putArrayAddressInRcx(vinfo, n.Children[0]);
            emit("mov rax, [rcx]");
            emit("push rax");
            type = (vinfo.VType as ArrayVarType).baseType;
            break;

        default:
            throw new Exception("ICE!!! Expected NUM, LP, STRING-CONSTANT, or ID Recieved:" + child.Symbol);
        }
    }