Ejemplo n.º 1
0
        public ILabel GenerateClosureCall(
            ILocation result,
            IEnumerable <VirtualRegister> callArguments,
            ILabel onReturn,
            Function.Function callerFunction,
            FunType funType,
            VirtualRegister funPtr)
        {
            var needStackOffset = funType.GetStackArgumentsCount() % 2 == 1 ? 8 : 0;
            var funPtrRead      = new RegisterRead(funPtr);
            var funCodePtr      = new MemoryRead(
                new ArithmeticBinaryOperation(AST.ArithmeticOperationType.Addition, funPtrRead, new IntegerImmediateValue(0)));
            var funClosurePtr = new MemoryRead(
                new ArithmeticBinaryOperation(AST.ArithmeticOperationType.Addition, funPtrRead, new IntegerImmediateValue(16)));
            var preCall = new List <Node>
            {
                new AlignStackPointer(needStackOffset)
            }
            .Append(new Comment("Pass arguments"))
            .Concat(this.PassClosureArguments(callArguments, funClosurePtr))
            .Append(new ClearDF())
            .Append(new Comment($"Call closure function"))
            .Append(
                new UsesDefinesNode(
                    HardwareRegisterUtils.ArgumentRegisters.Take(callArguments.Count() + 1).ToList(),
                    HardwareRegisterUtils.CallerSavedRegisters))
            .Append(new RegisterWrite(HardwareRegister.RAX, funCodePtr));

            var postCall = new List <Node>
            {
                new Comment("Copy function result to variable"),
                this.readWriteGenerator.GenerateWrite(callerFunction, result, new RegisterRead(HardwareRegister.RAX)),
                new Comment("Restore RSP alignment"),
                new AlignStackPointer(-(needStackOffset + (8 * funType.GetStackArgumentsCount()))),
                new Comment("End of call"),
            };

            var controlFlow = new ComputedFunctionCall(postCall.MakeTreeChain(this.labelFactory, onReturn));

            return(preCall.MakeTreeChain(this.labelFactory, controlFlow));
        }