Ejemplo n.º 1
0
 /// <summary>
 /// Creates a new verifier
 /// </summary>
 /// <param name="virtualMachine">The virtual machine</param>
 public Verifier(VirtualMachine virtualMachine)
 {
     this.virtualMachine = virtualMachine;
     this.intType = this.virtualMachine.TypeProvider.GetPrimitiveType(PrimitiveTypes.Int);
     this.floatType = this.virtualMachine.TypeProvider.GetPrimitiveType(PrimitiveTypes.Float);
     this.voidType = this.virtualMachine.TypeProvider.GetPrimitiveType(PrimitiveTypes.Void);
 }
        /// <summary>
        /// Handles the given function call argument
        /// </summary>
        /// <param name="compilationData">The compilation data</param>
        /// <param name="argumentIndex">The index of the argument</param>
        /// <param name="argumentType">The type of the argument</param>
        /// <param name="argumentRegisters">The virtual registers for the arguments</param>
        /// <param name="aliveRegistersStack">The alive registers stack</param>
        /// <param name="toCall">The function to call</param>
        public void CallFunctionArgument(
            CompilationData compilationData,
            int argumentIndex, VMType argumentType,
            IReadOnlyList<VirtualRegister> argumentRegisters,
            IDictionary<HardwareRegister, int> aliveRegistersStack,
            FunctionDefinition toCall)
        {
            var virtualAssembler = compilationData.VirtualAssembler;
            var regAlloc = compilationData.RegisterAllocation;
            var generatedCode = compilationData.Function.GeneratedCode;
            int thisNumArgs = compilationData.Function.Definition.Parameters.Count;
            int numArgs = toCall.Parameters.Count;

            int argsStart = 1 + compilationData.StackSize / Assembler.RegisterSize;

            if (virtualAssembler.NeedSpillRegister)
            {
                argsStart += 1;
            }

            int alignment = this.CalculateStackAlignment(compilationData, toCall.Parameters, aliveRegistersStack.Count);

            var virtualReg = argumentRegisters[numArgs - 1 - argumentIndex];
            var virtualRegStack = regAlloc.GetStackIndex(virtualReg);

            //Check if to pass argument by via the stack
            if (argumentIndex >= numRegisterArguments)
            {
                //Move arguments to the stack
                HardwareRegister spillReg;
                int stackOffset = 0;

                if (argumentType.IsPrimitiveType(PrimitiveTypes.Float))
                {
                    spillReg = virtualAssembler.GetFloatSpillRegister();

                    if (!virtualRegStack.HasValue)
                    {
                        stackOffset = aliveRegistersStack[virtualAssembler.GetFloatRegisterForVirtual(virtualReg).Value];
                    }
                }
                else
                {
                    spillReg = virtualAssembler.GetIntSpillRegister();

                    if (!virtualRegStack.HasValue)
                    {
                        stackOffset = aliveRegistersStack[virtualAssembler.GetIntRegisterForVirtual(virtualReg).Value];
                    }
                }

                var argMemory = new MemoryOperand();

                if (virtualRegStack.HasValue)
                {
                    argMemory = new MemoryOperand(
                        Register.BP,
                        virtualAssembler.CalculateStackOffset(virtualRegStack.Value));
                }
                else
                {
                    argMemory = new MemoryOperand(
                        Register.BP,
                        -(argsStart + stackOffset)
                        * Assembler.RegisterSize);
                }

                Assembler.Move(generatedCode, spillReg, argMemory);
                Assembler.Push(generatedCode, spillReg);
            }
            else
            {
                HardwareRegister argReg;
                int stackOffset = 0;

                if (argumentType.IsPrimitiveType(PrimitiveTypes.Float))
                {
                    argReg = floatArgumentRegisters[argumentIndex];

                    if (!virtualRegStack.HasValue)
                    {
                        stackOffset = aliveRegistersStack[virtualAssembler.GetFloatRegisterForVirtual(virtualReg).Value];
                    }
                }
                else
                {
                    argReg = intArgumentRegisters[argumentIndex];

                    if (!virtualRegStack.HasValue)
                    {
                        stackOffset = aliveRegistersStack[virtualAssembler.GetIntRegisterForVirtual(virtualReg).Value];
                    }
                }

                var argMemory = new MemoryOperand();

                if (virtualRegStack.HasValue)
                {
                    argMemory = new MemoryOperand(
                        Register.BP,
                        virtualAssembler.CalculateStackOffset(virtualRegStack.Value));
                }
                else
                {
                    argMemory = new MemoryOperand(
                        Register.BP,
                        -(argsStart + stackOffset)
                        * Assembler.RegisterSize);
                }

                Assembler.Move(generatedCode, argReg, argMemory);
            }
        }
        /// <summary>
        /// Moves an argument to the stack
        /// </summary>
        /// <param name="compilationData">The compilation data</param>
        /// <param name="argumentIndex">The argument index</param>
        /// <param name="argumentType">The type of the argument</param>
        private void MoveArgumentToStack(CompilationData compilationData, int argumentIndex, VMType argumentType)
        {
            var generatedCode = compilationData.Function.GeneratedCode;
            int argStackOffset = -(1 + argumentIndex) * Assembler.RegisterSize;

            if (argumentIndex >= numRegisterArguments)
            {
                int stackArgumentIndex = this.GetStackArgumentIndex(compilationData, argumentIndex);

                var argStackSource = new MemoryOperand(
                    Register.BP,
                    Assembler.RegisterSize * (6 + stackArgumentIndex));

                HardwareRegister tmpReg;

                if (argumentType.IsPrimitiveType(PrimitiveTypes.Float))
                {
                    tmpReg = compilationData.VirtualAssembler.GetFloatSpillRegister();
                }
                else
                {
                    tmpReg = new IntRegister(Register.AX);
                }

                Assembler.Move(generatedCode, tmpReg, argStackSource);
                Assembler.Move(generatedCode, new MemoryOperand(Register.BP, argStackOffset), tmpReg);
            }
            else
            {
                //var argReg = floatArgumentRegisters[argumentIndex];
                HardwareRegister argReg;

                if (argumentType.IsPrimitiveType(PrimitiveTypes.Float))
                {
                    argReg = floatArgumentRegisters[argumentIndex];
                }
                else
                {
                    argReg = intArgumentRegisters[argumentIndex];
                }

                Assembler.Move(generatedCode, new MemoryOperand(Register.BP, argStackOffset), argReg);
            }
        }
Ejemplo n.º 4
0
 /// <summary>
 /// Asserts that the given types are equal
 /// </summary>
 private void AssertSameType(Function function, Instruction instruction, int index, VMType expectedType, VMType actualType)
 {
     if (expectedType != actualType)
     {
         throw new VerificationException(
             $"Expected type '{expectedType}' but got type '{actualType}'.",
             function, instruction, index);
     }
 }