// We will use standard x86-64 conventions -> RDI, RSI, RDX, RCX, R8, R9. // TODO: instruction templates covering hw register modifications public ILabel GenerateCall( ILocation result, IEnumerable <VirtualRegister> callArguments, ILabel onReturn, Function.Function callerFunction, Function.Function function) { var needStackOffset = function.GetStackArgumentsCount() % 2 == 1 ? 8 : 0; var preCall = new List <Node> { new AlignStackPointer(needStackOffset) } .Append(new Comment("Pass arguments")) .Concat(this.PassArguments(callerFunction, callArguments, function.Parent)) .Append(new ClearDF()) .Append(new Comment($"Call {function.MangledName}")) .Append( new UsesDefinesNode( HardwareRegisterUtils.ArgumentRegisters.Take(callArguments.Count() + 1).ToList(), HardwareRegisterUtils.CallerSavedRegisters)); 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 * function.GetStackArgumentsCount()))), new Comment("End of call"), }; var controlFlow = new FunctionCall(function, postCall.MakeTreeChain(this.labelFactory, onReturn)); return(preCall.MakeTreeChain(this.labelFactory, controlFlow)); }
private List <Node> GetArgumentSources(Function.Function function) { var registerArguments = HardwareRegisterUtils .ArgumentRegisters .Select(reg => new RegisterRead(reg)); var memoryArguments = Enumerable.Range(0, function.GetStackArgumentsCount()) .Select(n => (Node) new MemoryRead(HardwareRegister.RBP.OffsetAddress(n + 2))); return(registerArguments.Concat(memoryArguments).ToList()); }