public IEnumerable <Operation> VisitBlock(Block block) { LocalVariables = TypeEvaluator.RoundBy8(TypeEvaluator.SizeOf(block.Variables)); FunctionFrame += LocalVariables; yield return(Operation.Sub(Register.Rsp, LocalVariables)); foreach (var op in block.Statements.SelectMany(s => s.AcceptVisitor(this))) { yield return(op); } yield return(Operation.Add(Register.Rsp, LocalVariables)); FunctionFrame -= LocalVariables; }
public IEnumerable <Operation> VisitCallExpression(CallExpression callExpression) { var type = (FunctionType)Types.TypeOf(callExpression.Function); var pars = FunctionParams[type]; var offset = TypeEvaluator.RoundBy8(TypeEvaluator.SizeOf(pars.StackStruct)); FunctionFrame += offset; yield return(Operation.Sub(Register.Rsp, offset)); var registerResults = new List <AnyRegister>(); var arguments = callExpression.Params; for (var i = 0; i < arguments.Count; i++) { var(onStack, place) = pars.Params[i]; if (onStack) { foreach (var op in _addressVisitor.VisitExpression(arguments[i])) { yield return(op); } var adr = LastRegister; foreach (var op in MakeAssigner( new Shift(Register.Rsp, place), new Shift(adr, 0), Types.TypeOf(arguments[i]) ) ) { yield return(op); } } else { foreach (var op in arguments[i].AcceptVisitor(this)) { yield return(op); } registerResults.Add(LastRegister); } } foreach (var op in callExpression.Function.AcceptVisitor(this)) { yield return(op); } var func = LastRegister; foreach (var(res, i) in registerResults.Select((v, i) => (v, i))) { yield return(Operation.Mov(Params[i], res)); } yield return(new UnaryOperation(UnaryOperation.OpCode.Call, func)); FunctionFrame -= offset; yield return(Operation.Add(Register.Rsp, offset)); if (SimpleTypeSize(type.Result) is { } size&& size > 0) { yield return(Operation.Mov(NewRegister(size), Register.Rax)); } }