public void Visit(SubVarCallNode n)
        {
            var children = n.GetChildren();

            foreach (var child in children)
            {
                child.Accept(this);
            }
        }
Example #2
0
 public void Visit(SubVarCallNode n)
 {
     PrintDOTIDLabel(n);
     PrintDOTParentChild(n);
     foreach (var child in n.GetChildren())
     {
         child.Accept(this);
     }
 }
Example #3
0
        public void Visit(SubVarCallNode n)
        {
            var children = n.GetChildren();

            foreach (var child in children)
            {
                child.Accept(this);
            }

            var callChainPointerReg = Registers.R12;
            var varName             = n.VarName;
            int varOffset;

            (string type, List <int> dims)varType;
            int typeSize;
            FunctionSymbolTableEntry tableForIndexing;

            switch (n.SymTable)
            {
            case FunctionSymbolTableEntry f:
            {
                if (f.MemoryLayout.Contains(varName))
                {
                    varOffset = f.MemoryLayout.GetOffset(varName);
                    varType   = f.MemoryLayout.GetVarType(varName);
                    typeSize  = f.MemoryLayout.GetTypeSize(varName);
                }
                else
                {
                    var classTable = _globalSymbolTable.GetClassSymbolTableByName(f.ScopeSpec);
                    varOffset = classTable.MemoryLayout.GetOffset(varName);
                    varType   = classTable.MemoryLayout.GetVarType(varName);
                    typeSize  = classTable.MemoryLayout.GetTypeSize(varName);

                    _writer.WriteInstruction(Instructions.Lw, callChainPointerReg, $"-8({FSPReg})");
                }
            }
                tableForIndexing = f;
                break;

            case ClassSymbolTable c:
                varOffset        = c.MemoryLayout.GetOffset(varName);
                varType          = c.MemoryLayout.GetVarType(varName);
                typeSize         = c.MemoryLayout.GetTypeSize(varName);
                tableForIndexing = (FunctionSymbolTableEntry)n.SecondarySymTable;
                break;

            default:
                throw new InvalidOperationException("Unknown table type");
            }

            _writer.WriteComment("SUB VAR CALL");

            // Get variable address
            _writer.WriteComment("Compute absolute address of variable, (we don't have lea...)");
            var absoluteAddressReg = PopRegister();

            _writer.WriteInstruction(Instructions.Add, absoluteAddressReg, absoluteAddressReg, callChainPointerReg); // grab callchain address
            _writer.WriteInstruction(Instructions.Addi, absoluteAddressReg, absoluteAddressReg, $"{varOffset}");     // Add offset, we have absolute address now

            // Get variable address with indexing, if used
            //           x  y  z
            // integer a[3][3][3]
            // a[1][0][2] -> a + 1*sizeof(integer)*3*3 + 0*sizeof(integer)*3 + 2*sizeof(integer)
            //                     ^               ^
            //                      typeSize       runningMultiplier
            var indicesNode = (IndicesNode)children[1];
            var indices     = indicesNode.TemporaryVariableNames;

            if (indices.Count > 0)
            {
                _writer.WriteComment("Computing address from array index");

                // Set type size register
                var typeSizeReg = PopRegister();
                _writer.WriteInstruction(Instructions.Addi, typeSizeReg, typeSizeReg, $"{typeSize}");

                var runningMultiplierReg     = PopRegister(); // 3*3
                var indexValueReg            = PopRegister();
                var indexingElementOffsetReg = PopRegister(); // the 1*sizeof(integer)*3*3 value will be stored here and added to absoluteAddressReg
                for (int i = 0; i < indices.Count; ++i)
                {
                    _writer.WriteComment($"Computing for {i}th index");

                    // Set runningMultiplierReg
                    if (i == 0) // InitialValue
                    {
                        _writer.WriteInstruction(Instructions.Addi, runningMultiplierReg, runningMultiplierReg, "1");
                    }
                    else
                    {
                        _writer.WriteInstruction(Instructions.Muli, runningMultiplierReg, runningMultiplierReg, $"{varType.dims[i]}");
                    }

                    // Clear indexingElementOffsetReg
                    _writer.WriteInstruction(Instructions.Sub, indexingElementOffsetReg, indexingElementOffsetReg, indexingElementOffsetReg);
                    _writer.WriteInstruction(Instructions.Addi, indexingElementOffsetReg, indexingElementOffsetReg, "1"); // set initial multiplier value

                    // Load index value
                    var indexOffset = tableForIndexing.MemoryLayout.GetOffset(indices.FastReverse().ToList()[i]);
                    _writer.WriteInstruction(Instructions.Lw, indexValueReg, $"{indexOffset}({FSPReg})");

                    _writer.WriteInstruction(Instructions.Mul, indexingElementOffsetReg, indexValueReg, typeSizeReg);                     // 1*sizeof(integer)
                    _writer.WriteInstruction(Instructions.Mul, indexingElementOffsetReg, indexingElementOffsetReg, runningMultiplierReg); // 1*sizeof(integer)*3*3

                    // Add indexingElementOffsetReg to absoluteAddressReg
                    _writer.WriteInstruction(Instructions.Add, absoluteAddressReg, absoluteAddressReg, indexingElementOffsetReg);
                }

                PushRegister(indexingElementOffsetReg);
                PushRegister(indexValueReg);
                PushRegister(runningMultiplierReg);
                PushRegister(typeSizeReg);
            }

            //NOTE: R12 has address now
            // Store absolute address into temp var associated to this SubVarCall
            //_writer.WriteComment("Storing final address");
            //var tempVarOffset = table.MemoryLayout.GetOffset(n.TemporaryVariableName);
            //_writer.WriteInstruction(Instructions.Sw, $"{tempVarOffset}({FSPReg})", absoluteAddressReg);
            _writer.WriteInstruction(Instructions.Add, callChainPointerReg, Registers.R0, absoluteAddressReg);
            PushRegister(absoluteAddressReg);
        }
Example #4
0
        public void Visit(SubVarCallNode n)
        {
            var children = n.GetChildren();

            children[0].SymTable = n.SymTable;
            children[0].Accept(this);
            children[1].SymTable = n.SecondarySymTable;
            children[1].Accept(this);

            var varNameToken = ((IdentifierNode)children[0]).Token;

            n.VarName = varNameToken.Lexeme;
            n.NumDims = ((IndicesNode)children[1]).NumDims;

            Dictionary <string, (string, List <int>)> varsInScope;

            switch (n.SymTable)
            {
            case FunctionSymbolTableEntry f:
            {
                var classTable = _globalTable.GetClassSymbolTableByName(f.ScopeSpec);
                Dictionary <string, (string, List <int>)> classVars = classTable?.GetVariablesInScope() ?? new Dictionary <string, (string, List <int>)>();
                var funcVars = f.GetVariablesInScope();
                varsInScope = new Dictionary <string, (string, List <int>)>();

                foreach (var v in classVars)
                {
                    varsInScope.Add(v.Key, v.Value);
                }

                foreach (var v in funcVars)
                {
                    if (!varsInScope.ContainsKey(v.Key))
                    {
                        varsInScope.Add(v.Key, v.Value);
                    }
                    else
                    {
                        _errorStream.WriteLine($"Variable '{v.Key}' used in {f.ToStringSignature()} is already defined in the class");
                        Console.WriteLine($"Error: Variable '{v.Key}' used in {f.ToStringSignature()} is already defined in the class");
                    }
                }
            }
            break;

            case ClassSymbolTable s:
            {
                varsInScope = s.GetVariablesInScope();
            }
            break;

            default:
                throw new InvalidOperationException("Unknown table entry type found");
            }

            (string Type, List <int> Dims)typeDims;
            if (!varsInScope.TryGetValue(n.VarName, out typeDims))
            {
                _errorStream.WriteLine($"Use of undeclared variable \"{n.VarName}\" ({varNameToken.StartLine}:{varNameToken.StartColumn})");
                Console.WriteLine($"Error: Use of undeclared variable \"{n.VarName}\" ({varNameToken.StartLine}:{varNameToken.StartColumn})");
            }
            else
            {
                n.ScopeSpec = typeDims.Type;
                n.ExprType  = typeDims;

                if (n.NumDims > typeDims.Dims.Count)
                {
                    _errorStream.WriteLine($"Data member \"{n.VarName}\" used with more dims than defined! max: {typeDims.Dims.Count}, had: {n.NumDims}");
                    Console.WriteLine($"Error: Data member \"{n.VarName}\" used with more dims than defined! max: {typeDims.Dims.Count}, had: {n.NumDims}");
                }

                // Say var defined as float a[5][5][5]
                // and used a[2], the type of the expression is now float[5][5]
                n.ExprType = (typeDims.Type, typeDims.Dims.Skip(n.NumDims).ToList());
            }
        }