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> VisitGetFieldExpression(GetFieldExpression expression) { if (expression.Left is NameExpression ne0 && ne0.Depth == 0) { yield return(Operation.Mov( NewRegister(8), new NameOperand($"Function{expression.Field}") )); yield break; } var str = (StructType)Types.TypeOf(expression.Left); var size = str.Fields[expression.Field] switch { NumberType nt => (nt.BitSize / 8), PointerType _ => 8, _ => throw new Exception("Getter value calculation must result in simple type") }; if (expression.Left is NameExpression ne && ne.Depth == 1) { var(onStack, idx) = CurrentFunctionParams.Params[expression.Field]; yield return(Operation.Mov( NewRegister(8), new Memory(new Shift(Register.Rsp, ParameterOffset(onStack, idx)), size) )); yield break; } foreach (var op in _addressVisitor.VisitExpression(expression.Left)) { yield return(op); } var adr = LastRegister; yield return(Operation.Mov( NewRegister(size), new Memory(new Shift(adr, TypeEvaluator.GetOffset(str, expression.Field)), adr.Size) )); }
public IEnumerable <Operation> VisitModule(Module module) { _addressVisitor = new ExpressionAddressVisitor(this); Types = new TypeEvaluator(this); yield return(new AsmLine("extern printf")); yield return(new AsmLine("extern ExitProcess")); yield return(new AsmLine("section .text")); yield return(new AsmLine("global Start")); yield return(new AsmLine("Start: jmp Function0")); FunctionParams = module .Entities .Select(v => ((Function)v).Type) .Distinct() .ToDictionary(v => v, v => new FunctionData(v, this)); foreach (var op in HardCode()) { yield return(op); } Module = module; foreach (var e in module.Entities) { foreach (var op in e.AcceptVisitor(this)) { yield return(op); } CurrentFunction++; } yield return(new AsmLine("section .data")); yield return(new AsmLine("fmt: db \"%d\", 10, 0")); }
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)); } }
public IEnumerable <Operation> MakeAssigner(Shift left, Shift right, BaseType type) { switch (type) { case EmptyType _: break; case FunctionType _: throw new Exception("Can not assign functions"); case NumberType numberType: { var r = NewRegister(numberType.BitSize / 8); yield return(Operation.Mov(r, new Memory(right, numberType.BitSize / 8))); yield return(Operation.Mov(new Memory(left, numberType.BitSize / 8), r)); break; } case PointerType _: { var r = NewRegister(8); yield return(Operation.Mov(r, new Memory(right, 8))); yield return(Operation.Mov(new Memory(left, 8), r)); break; } case StructType structType: foreach (var op in structType.Fields.SelectMany((f, i) => MakeAssigner( new Shift(left.Register, left.Shft + TypeEvaluator.GetOffset(structType, i)), new Shift(right.Register, right.Shft + TypeEvaluator.GetOffset(structType, i)), f ) )) { yield return(op); } break; default: throw new ArgumentOutOfRangeException(nameof(type)); } }