private SymbolOperand GetInternalAllocateStringCallTarget(ITypeSystem typeSystem) { RuntimeType runtimeType = typeSystem.GetType(@"Mosa.Internal.Runtime"); RuntimeMethod callTarget = runtimeType.FindMethod(@"AllocateString"); return(SymbolOperand.FromMethod(callTarget)); }
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()); } }
/// <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); }
/// <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); }
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); }
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); }
/// <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); } }
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); }
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); }
/// <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; } }
public VarInstruction(SymbolOperand name, OperandType type, Operand value = null) : base(OpCode.Var, name) { this.Type = type; this.Value = value; }
public NotInstruction(SymbolOperand tempName, Operand left) : base(OpCode.Not, tempName) { this.Left = left; }
public PreDecInstruction(SymbolOperand tempName, SymbolOperand left) : base(OpCode.PreDec, tempName) { this.Left = left; }
public AssignInstruction(OpCode opcode, SymbolOperand destName) : base(opcode) { this.Destination = destName; }
public StoreInstruction(SymbolOperand toName, Operand value) : base(OpCode.Store, toName) { this.Value = value; }
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); }
public LocalInstruction(SymbolOperand local) : base(OpCode.Local, local) { }
public ConstInstruction(SymbolOperand name, OperandType typeres, Operand value) : base(OpCode.Const, name) { this.TypeResolver = typeres; this.Value = value; }
public CltInstruction(SymbolOperand tempName, Operand left, Operand right) : base(OpCode.Clt, tempName) { this.Left = left; this.Right = right; }
/// <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); }