Beispiel #1
0
        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;
        }
Beispiel #2
0
        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)
                             ));
        }
Beispiel #3
0
        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"));
        }
Beispiel #4
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));
            }
        }
Beispiel #5
0
        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));
            }
        }