Пример #1
0
        private SymbolOperand GetInternalAllocateStringCallTarget(ITypeSystem typeSystem)
        {
            RuntimeType   runtimeType = typeSystem.GetType(@"Mosa.Internal.Runtime");
            RuntimeMethod callTarget  = runtimeType.FindMethod(@"AllocateString");

            return(SymbolOperand.FromMethod(callTarget));
        }
Пример #2
0
        public SymbolOperand NewSymbol(string name, OperandType type)
        {
            var symbolOperand = new SymbolOperand(name, type, this.CurrentBlock.Name);

            this.CurrentBlock[name] = symbolOperand;
            return(symbolOperand);
        }
        /// <summary>
        /// Performs stage specific processing on the compiler context.
        /// </summary>
        void IAssemblyCompilerStage.Run()
        {
            if (!secondStage)
            {
                IntPtr entryPoint = WriteMultibootEntryPoint();
                WriteMultibootHeader(entryPoint);
                secondStage = true;
            }
            else
            {
                ITypeInitializerSchedulerStage typeInitializerSchedulerStage = this.compiler.Pipeline.FindFirst <ITypeInitializerSchedulerStage>();

                SigType         I4  = new SigType(CilElementType.I4);
                RegisterOperand ecx = new RegisterOperand(I4, GeneralPurposeRegister.ECX);
                RegisterOperand eax = new RegisterOperand(I4, GeneralPurposeRegister.EAX);
                RegisterOperand ebx = new RegisterOperand(I4, GeneralPurposeRegister.EBX);

                InstructionSet instructionSet = new InstructionSet(16);
                Context        ctx            = new Context(instructionSet, -1);

                ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, ecx, new ConstantOperand(I4, 0x200000));
                ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, new MemoryOperand(I4, ecx.Register, new IntPtr(0x0)), eax);
                ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, new MemoryOperand(I4, ecx.Register, new IntPtr(0x4)), ebx);

                SymbolOperand entryPoint = SymbolOperand.FromMethod(typeInitializerSchedulerStage.Method);

                ctx.AppendInstruction(CPUx86.Instruction.CallInstruction, null, entryPoint);
                ctx.AppendInstruction(CPUx86.Instruction.RetInstruction);

                LinkerGeneratedMethod method = LinkTimeCodeGenerator.Compile(this.compiler, @"MultibootInit", instructionSet, typeSystem);
                this.linker.EntryPoint = this.linker.GetSymbol(method.ToString());
            }
        }
Пример #4
0
        /// <summary>
        /// Emits the displacement operand.
        /// </summary>
        /// <param name="displacement">The displacement operand.</param>
        public void WriteDisplacement(Operand displacement)
        {
            byte[] disp;

            MemberOperand member = displacement as MemberOperand;
            LabelOperand  label  = displacement as LabelOperand;
            SymbolOperand symbol = displacement as SymbolOperand;

            if (label != null)
            {
                int pos = (int)(_codeStream.Position - _codeStreamBasePosition);
                disp = LittleEndianBitConverter.GetBytes((uint)_linker.Link(LinkType.AbsoluteAddress | LinkType.I4, _compiler.Method.ToString(), pos, 0, label.Name, IntPtr.Zero));
            }
            else if (member != null)
            {
                int pos = (int)(_codeStream.Position - _codeStreamBasePosition);
                disp = LittleEndianBitConverter.GetBytes((uint)_linker.Link(LinkType.AbsoluteAddress | LinkType.I4, _compiler.Method.ToString(), pos, 0, member.Member.ToString(), member.Offset));
            }
            else if (symbol != null)
            {
                int pos = (int)(_codeStream.Position - _codeStreamBasePosition);
                disp = LittleEndianBitConverter.GetBytes((uint)_linker.Link(LinkType.AbsoluteAddress | LinkType.I4, _compiler.Method.ToString(), pos, 0, symbol.Name, IntPtr.Zero));
            }
            else
            {
                disp = LittleEndianBitConverter.GetBytes((displacement as MemoryOperand).Offset.ToInt32());
            }

            _codeStream.Write(disp, 0, disp.Length);
        }
Пример #5
0
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="typeSystem">The type system.</param>
        public void ReplaceIntrinsicCall(Context context, ITypeSystem typeSystem)
        {
            SymbolOperand callTargetOperand  = this.GetInternalAllocateStringCallTarget(typeSystem);
            SymbolOperand methodTableOperand = new SymbolOperand(BuiltInSigType.IntPtr, StringClassMethodTableSymbolName);
            Operand       lengthOperand      = context.Operand1;
            Operand       result             = context.Result;

            context.SetInstruction(IR.Instruction.CallInstruction, result, callTargetOperand, methodTableOperand, lengthOperand);
        }
Пример #6
0
        private Operand InsertLoadBeforeInstruction(Context context, string symbolName, SigType type)
        {
            Context before = context.InsertBefore();
            Operand result = this.methodCompiler.CreateTemporary(type);
            Operand op     = new SymbolOperand(type, symbolName);

            before.SetInstruction(Instruction.Get(OpCode.Ldc_i4), result, op);

            return(result);
        }
Пример #7
0
        public Operand Visit(ILGenerator generator, NullCoalescingNode nullc)
        {
            SymbolOperand retval = generator.SymbolTable.NewTempSymbol(OperandType.Auto, "retval");

            generator.Emmit(new VarInstruction(retval, null));

            // Get a (non-resolved) label to skip the if
            var leftExitPoint = generator.ProgramBuilder.NewLabel();

            // Generate the condition and check the result, using exitPoint
            // as the destination if the condition is true
            var           left = nullc.Left.Visit(generator);
            SymbolOperand tmp  = generator.SymbolTable.NewTempSymbol(OperandType.Auto, "check");

            generator.Emmit(new VarInstruction(tmp, null));
            generator.Emmit(new CeqInstruction(tmp, left, new ImmediateOperand(OperandType.Null, null)));
            generator.Emmit(new NotInstruction(tmp, tmp));
            generator.Emmit(new IfFalseInstruction(tmp, leftExitPoint));

            generator.Emmit(new StoreInstruction(retval, left));

            // We need to add a goto instruction to jump from inside
            // the if's then body, that way we don't fall through the else part.
            // The goto destination address is not know yet, because it needs to be resolved
            // after generating the else body
            var @goto = new GotoInstruction(null);

            generator.Emmit(@goto);

            // The exitPoint for the if's then will be the entryPoint
            // for the if's else part
            Label elseEntryPoint = leftExitPoint;

            // Backpatch the elseEntryPoint (thenExitPoint) here
            generator.BindLabel(elseEntryPoint);

            // Generate the label for the (pending) goto instruction
            var elseExitPoint = generator.ProgramBuilder.NewLabel();

            @goto.SetDestination(elseExitPoint);

            var right = nullc.Right.Visit(generator);

            generator.Emmit(new StoreInstruction(retval, right));

            // Finally, backpatch the goto to jump from the then's body to avoid
            // fall through the else's body
            generator.BindLabel(elseExitPoint);

            return(retval);
        }
Пример #8
0
        /// <summary>
        /// Emits the specified platform instruction.
        /// </summary>
        /// <param name="ctx">The context.</param>
        /// <param name="emitter">The emitter.</param>
        protected override void Emit(Context ctx, MachineCodeEmitter emitter)
        {
            Operand       destinationOperand = ctx.Operand1;
            SymbolOperand destinationSymbol  = destinationOperand as SymbolOperand;

            if (destinationSymbol != null)
            {
                emitter.WriteByte(0xE8);
                emitter.Call(destinationSymbol);
            }
            else
            {
                RegisterOperand registerOperand = destinationOperand as RegisterOperand;
                emitter.Emit(RegCall, registerOperand);
            }
        }
        /// <summary>
        /// Creates the ISR methods.
        /// </summary>
        private void CreateISRMethods()
        {
            // Get RuntimeMethod for the Mosa.Kernel.x86.IDT.InterruptHandler
            RuntimeType rt = typeSystem.GetType(@"Mosa.Kernel.x86.IDT");

            if (rt == null)
            {
                return;
            }

            RuntimeMethod InterruptMethod = FindMethod(rt, "InterruptHandler");

            if (InterruptMethod == null)
            {
                return;
            }

            SymbolOperand interruptMethod = SymbolOperand.FromMethod(InterruptMethod);

            SigType I1 = new SigType(CilElementType.I1);
            SigType I4 = new SigType(CilElementType.I4);

            RegisterOperand esp = new RegisterOperand(I4, GeneralPurposeRegister.ESP);

            for (int i = 0; i <= 255; i++)
            {
                InstructionSet set = new InstructionSet(100);
                Context        ctx = new Context(set, -1);

                ctx.AppendInstruction(CPUx86.Instruction.CliInstruction);
                if (i <= 7 || i >= 16 | i == 9)                 // For IRQ 8, 10, 11, 12, 13, 14 the cpu automatically pushed the error code
                {
                    ctx.AppendInstruction(CPUx86.Instruction.PushInstruction, null, new ConstantOperand(I1, 0x0));
                }
                ctx.AppendInstruction(CPUx86.Instruction.PushInstruction, null, new ConstantOperand(I1, (byte)i));
                ctx.AppendInstruction(CPUx86.Instruction.PushadInstruction);
                ctx.AppendInstruction(CPUx86.Instruction.CallInstruction, null, interruptMethod);
                ctx.AppendInstruction(CPUx86.Instruction.PopadInstruction);
                ctx.AppendInstruction(CPUx86.Instruction.AddInstruction, esp, new ConstantOperand(I4, 0x08));
                ctx.AppendInstruction(CPUx86.Instruction.StiInstruction);
                ctx.AppendInstruction(CPUx86.Instruction.IRetdInstruction);

                //LinkerGeneratedMethod method =
                LinkTimeCodeGenerator.Compile(this.compiler, @"InterruptISR" + i.ToString(), set, typeSystem);
            }
        }
Пример #10
0
        private Operand MakeVariableAssignment(VariableAssignmentNode node, ILGenerator generator)
        {
            SymbolOperand leftHandSide  = node.Accessor.Visit(generator) as SymbolOperand;
            Operand       rightHandSide = node.Right.Visit(generator);

            // If right-hand side exists and has a type, do some type checking

            /*if (rightHandSide.Type != leftHandSide.Type)
             *  throw new AstWalkerException($"Cannot convert {rightHandSide.Type} to {leftHandSide.Type} ('{leftHandSide.Name}')");*/

            if (node.Operator.Type == TokenType.Assignment)
            {
                generator.Emmit(new StoreInstruction(leftHandSide, rightHandSide));
                return(leftHandSide);
            }


            Instruction instr = null;

            switch (node.Operator.Type)
            {
            case TokenType.IncrementAndAssign:
                instr = new AddInstruction(leftHandSide, leftHandSide, rightHandSide);
                break;

            case TokenType.DecrementAndAssign:
                instr = new SubInstruction(leftHandSide, leftHandSide, rightHandSide);
                break;

            case TokenType.MultAndAssign:
                instr = new MultInstruction(leftHandSide, leftHandSide, rightHandSide);
                break;

            case TokenType.DivideAndAssign:
                instr = new DivInstruction(leftHandSide, leftHandSide, rightHandSide);
                break;

            default:
                throw new InvalidInstructionException($"Unsupported operation: {node.Operator.Value} ({node.Operator.Type})");
            }

            generator.Emmit(instr);

            return(leftHandSide);
        }
Пример #11
0
        public Operand Visit(ILGenerator generator, CallableNode node)
        {
            Operand target = node.Target.Visit(generator);

            // Generate the "param" instructions
            List <ParamInstruction> parameters = node.Arguments.Expressions.Select(a => new ParamInstruction(a.Visit(generator))).ToList();

            parameters.Reverse();

            parameters.ForEach(p => generator.Emmit(p));

            // Generate the call instruction
            generator.Emmit(new CallInstruction(target, parameters.Count));

            SymbolOperand dest = generator.SymbolTable.NewTempSymbol(OperandType.Null);

            generator.Emmit(new VarInstruction(dest, OperandType.Null));
            return(dest);
        }
Пример #12
0
        /// <summary>
        /// Calls the specified target.
        /// </summary>
        /// <param name="symbolOperand">The symbol operand.</param>
        public void Call(SymbolOperand symbolOperand)
        {
            long address = _linker.Link(
                LinkType.RelativeOffset | LinkType.I4,
                _compiler.Method.ToString(),
                (int)(_codeStream.Position - _codeStreamBasePosition),
                (int)(_codeStream.Position - _codeStreamBasePosition) + 4,
                symbolOperand.Name,
                IntPtr.Zero
                );

            if (address == 0L)
            {
                this.WriteByte(0);
                this.WriteByte(0);
                this.WriteByte(0);
                this.WriteByte(0);
            }
            else
            {
                this._codeStream.Position += 4;
            }
        }
Пример #13
0
 public VarInstruction(SymbolOperand name, OperandType type, Operand value = null)
     : base(OpCode.Var, name)
 {
     this.Type  = type;
     this.Value = value;
 }
Пример #14
0
 public NotInstruction(SymbolOperand tempName, Operand left)
     : base(OpCode.Not, tempName)
 {
     this.Left = left;
 }
Пример #15
0
 public PreDecInstruction(SymbolOperand tempName, SymbolOperand left)
     : base(OpCode.PreDec, tempName)
 {
     this.Left = left;
 }
Пример #16
0
 public AssignInstruction(OpCode opcode, SymbolOperand destName)
     : base(opcode)
 {
     this.Destination = destName;
 }
Пример #17
0
 public StoreInstruction(SymbolOperand toName, Operand value)
     : base(OpCode.Store, toName)
 {
     this.Value = value;
 }
Пример #18
0
        public Operand Visit(ILGenerator generator, BinaryNode binary)
        {
            Operand left  = binary.Left.Visit(generator);
            Operand right = binary.Right.Visit(generator);

            SymbolOperand tmpname = generator.SymbolTable.NewTempSymbol(OperandType.Auto);

            Instruction instr = null;

            switch (binary.Operator.Type)
            {
            case TokenType.Addition:
                instr = new AddInstruction(tmpname, left, right);
                break;

            case TokenType.Minus:
                instr = new SubInstruction(tmpname, left, right);
                break;

            case TokenType.Multiplication:
                instr = new MultInstruction(tmpname, left, right);
                break;

            case TokenType.Division:
                instr = new DivInstruction(tmpname, left, right);
                break;


            case TokenType.Or:
                instr = new OrInstruction(tmpname, left, right);
                break;

            case TokenType.And:
                instr = new AndInstruction(tmpname, left, right);
                break;


            case TokenType.GreatThan:
                instr = new CgtInstruction(tmpname, left, right);
                break;

            case TokenType.GreatThanEqual:
                instr = new CgteInstruction(tmpname, left, right);
                break;

            case TokenType.LessThan:
                instr = new CltInstruction(tmpname, left, right);
                break;

            case TokenType.LessThanEqual:
                instr = new ClteInstruction(tmpname, left, right);
                break;


            case TokenType.Equal:
            case TokenType.NotEqual:     // Use NOT instruction
                instr = new CeqInstruction(tmpname, left, right);
                break;
            }

            generator.Emmit(new VarInstruction(tmpname, null));
            generator.Emmit(instr);

            if (binary.Operator.Type == TokenType.NotEqual)
            {
                SymbolOperand notname = generator.SymbolTable.NewTempSymbol(OperandType.Auto);
                generator.Emmit(new VarInstruction(notname, null));
                generator.Emmit(new NotInstruction(notname, tmpname));
                return(notname);
            }

            return(tmpname);
        }
Пример #19
0
 public LocalInstruction(SymbolOperand local)
     : base(OpCode.Local, local)
 {
 }
Пример #20
0
 public ConstInstruction(SymbolOperand name, OperandType typeres, Operand value)
     : base(OpCode.Const, name)
 {
     this.TypeResolver = typeres;
     this.Value        = value;
 }
Пример #21
0
 public CltInstruction(SymbolOperand tempName, Operand left, Operand right)
     : base(OpCode.Clt, tempName)
 {
     this.Left  = left;
     this.Right = right;
 }
Пример #22
0
        /// <summary>
        /// Schedules the specified method for invocation in the main.
        /// </summary>
        /// <param name="method">The method.</param>
        public void Schedule(RuntimeMethod method)
        {
            SymbolOperand symbolOperand = SymbolOperand.FromMethod(method);

            ctx.AppendInstruction(IR.Instruction.CallInstruction, null, symbolOperand);
        }