Beispiel #1
0
        private void CalculateClassSize(ClassSymbolTable classTable)
        {
            var varsInScope = classTable.GetVariablesInScope();

            foreach (var varInScope in varsInScope)
            {
                var type = varInScope.Value;

                var multiplier = 1;
                foreach (var dim in type.dims)
                {
                    multiplier *= dim;
                }

                if (string.Equals(type.type, TypeConstants.IntType))
                {
                    classTable.MemoryLayout.AddEntry(type, varInScope.Key, TypeConstants.IntTypeSize, TypeConstants.IntTypeSize * multiplier);
                }
                else if (string.Equals(type.type, TypeConstants.FloatType))
                {
                    classTable.MemoryLayout.AddEntry(type, varInScope.Key, TypeConstants.FloatTypeSize, TypeConstants.FloatTypeSize * multiplier);
                }
                else
                {
                    var varClassTable = _globalSymbolTable.GetClassSymbolTableByName(type.type);
                    if (varClassTable.MemoryLayout.TotalSize == 0)
                    {
                        CalculateClassSize(varClassTable);
                    }

                    classTable.MemoryLayout.AddEntry(type, varInScope.Key, varClassTable.MemoryLayout.TotalSize, varClassTable.MemoryLayout.TotalSize * multiplier);
                }
            }
        }
        private int GetSize(Token token)
        {
            int size;

            switch (token.TokenType)
            {
            case TokenType.Integer:
                size = TypeConstants.IntTypeSize;
                break;

            case TokenType.Float:
                size = TypeConstants.FloatTypeSize;
                break;

            case TokenType.Identifier:
                var table = _globalSymbolTable.GetClassSymbolTableByName(token.Lexeme);
                size = table.MemoryLayout.TotalSize;
                break;

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

            return(size);
        }
Beispiel #3
0
        public void Visit(FuncCallNode n)
        {
            var children = n.GetChildren();

            var first = children.First();

            first.SymTable          = n.SymTable;
            first.SecondarySymTable = n.SymTable;
            first.CallerTable       = n.SymTable;
            first.Accept(this);

            var currentScopeSpec = first.ScopeSpec;

            foreach (var node in children.Skip(1))
            {
                if (string.IsNullOrEmpty(currentScopeSpec))
                {
                    _errorStream.WriteLine($"ASSERT: Use of variable with no scopespec.");
                    Console.WriteLine($"ASSERT: Use of variable with no scopespec.");
                    break;
                }

                var classTable = _globalTable.GetClassSymbolTableByName(currentScopeSpec);
                if (classTable == null)
                {
                    _errorStream.WriteLine($"ScopeSpec \"{currentScopeSpec}\" refers to a non existing class.");
                    Console.WriteLine($"Error: ScopeSpec \"{currentScopeSpec}\" refers to a non existing class.");
                    break;
                }

                node.SymTable          = classTable;
                node.SecondarySymTable = n.SymTable;
                node.CallerTable       = n.SymTable;
                node.Accept(this);
                currentScopeSpec = node.ScopeSpec;
            }
        }
        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);
        }