/// <summary> /// Link time code generator used to compile dynamically created methods during link time. /// </summary> /// <param name="compiler">The assembly compiler used to compile this method.</param> /// <param name="methodName">The name of the created method.</param> /// <param name="instructionSet">The instruction set.</param> /// <returns></returns> /// <exception cref="System.ArgumentNullException"><paramref name="compiler"/>, <paramref name="methodName"/> or <paramref name="instructionSet"/> is null.</exception> /// <exception cref="System.ArgumentException"><paramref name="methodName"/> is invalid.</exception> public static LinkerGeneratedMethod Compile(AssemblyCompiler compiler, string methodName, InstructionSet instructionSet, ITypeSystem typeSystem) { if (compiler == null) throw new ArgumentNullException(@"compiler"); if (methodName == null) throw new ArgumentNullException(@"methodName"); if (methodName.Length == 0) throw new ArgumentException(@"Invalid method name."); LinkerGeneratedType compilerGeneratedType = typeSystem.InternalTypeModule.GetType(@"Mosa.Tools.Compiler", @"LinkerGenerated") as LinkerGeneratedType; // Create the type if we need to. if (compilerGeneratedType == null) { compilerGeneratedType = new LinkerGeneratedType(typeSystem.InternalTypeModule, @"Mosa.Tools.Compiler", @"LinkerGenerated", null); typeSystem.AddInternalType(compilerGeneratedType); } MethodSignature signature = new MethodSignature(BuiltInSigType.Void, new SigType[0]); // Create the method // HACK: <$> prevents the method from being called from CIL LinkerGeneratedMethod method = new LinkerGeneratedMethod(typeSystem.InternalTypeModule, "<$>" + methodName, compilerGeneratedType, signature); compilerGeneratedType.AddMethod(method); LinkerMethodCompiler methodCompiler = new LinkerMethodCompiler(compiler, compiler.Pipeline.FindFirst<ICompilationSchedulerStage>(), method, instructionSet); methodCompiler.Compile(); return method; }
/// <summary> /// Initializes a new instance of the <see cref="AotMethodCompiler" /> class. /// </summary> /// <param name="compiler">The compiler.</param> /// <param name="method">The method.</param> /// <param name="basicBlocks">The basic blocks.</param> /// <param name="instructionSet">The instruction set.</param> public AotMethodCompiler(BaseCompiler compiler, MosaMethod method, BasicBlocks basicBlocks, InstructionSet instructionSet) : base(compiler, method, basicBlocks, instructionSet) { var compilerOptions = compiler.CompilerOptions; Pipeline.Add(new IMethodCompilerStage[] { new CILDecodingStage(), new BasicBlockBuilderStage(), new StackSetupStage(), new ExceptionPrologueStage(), new OperandAssignmentStage(), new StaticAllocationResolutionStage(), new CILTransformationStage(), new ConvertCompoundMoveStage(), (compilerOptions.EnableSSA) ? new PromoteLocalVariablesStage() : null, (compilerOptions.EnableSSA) ? new EdgeSplitStage() : null, (compilerOptions.EnableSSA) ? new PhiPlacementStage() : null, (compilerOptions.EnableSSA) ? new EnterSSAStage() : null, (compilerOptions.EnableSSA && compilerOptions.EnableSSAOptimizations) ? new SSAOptimizations() : null, (compilerOptions.EnableSSA) ? new LeaveSSA() : null, (compilerOptions.EnableSSA) ? new ConvertCompoundMoveStage() : null, new PlatformStubStage(), new PlatformEdgeSplitStage(), new GreedyRegisterAllocatorStage(), new StackLayoutStage(), new EmptyBlockRemovalStage(), new BlockOrderingStage(), new CodeGenerationStage(), }); }
/// <summary> /// Creates the ISR methods. /// </summary> private void CreateExceptionVector() { var type = TypeSystem.GetTypeByName("Mosa.Kernel.x86", "IDT"); if (type == null) return; var method = type.FindMethodByName("ExceptionHandlerType"); if (method == null) return; Operand exceptionMethod = Operand.CreateSymbolFromMethod(TypeSystem, method); Operand esp = Operand.CreateCPURegister(TypeSystem.BuiltIn.I4, GeneralPurposeRegister.ESP); BasicBlocks basicBlocks = new BasicBlocks(); InstructionSet instructionSet = new InstructionSet(25); Context ctx = instructionSet.CreateNewBlock(basicBlocks); basicBlocks.AddHeaderBlock(ctx.BasicBlock); // TODO - setup stack for call to the managed exception handler //1. //2. //3. Call the managed exception handler ctx.AppendInstruction(X86.Call, null, exceptionMethod); var vectorMethod = Compiler.CreateLinkerMethod("ExceptionVector"); Compiler.CompileMethod(vectorMethod, basicBlocks, instructionSet); }
/// <summary> /// Creates the interrupt service routine (ISR) methods. /// </summary> private void CreateInterruptVectors() { RuntimeType runtimeType = typeSystem.GetType(@"Mosa.Kernel.x86.IDT"); if (runtimeType == null) return; RuntimeMethod runtimeMethod = runtimeType.FindMethod(@"ProcessInterrupt"); if (runtimeMethod == null) return; Operand interruptMethod = Operand.CreateSymbolFromMethod(runtimeMethod); Operand esp = Operand.CreateCPURegister(BuiltInSigType.Int32, GeneralPurposeRegister.ESP); for (int i = 0; i <= 255; i++) { InstructionSet instructionSet = new InstructionSet(100); Context ctx = new Context(instructionSet); ctx.AppendInstruction(X86.Cli); if (i <= 7 || i >= 16 | i == 9) // For IRQ 8, 10, 11, 12, 13, 14 the cpu will automatically pushed the error code ctx.AppendInstruction(X86.Push, null, Operand.CreateConstant(BuiltInSigType.SByte, 0x0)); ctx.AppendInstruction(X86.Push, null, Operand.CreateConstant(BuiltInSigType.SByte, (byte)i)); ctx.AppendInstruction(X86.Pushad); ctx.AppendInstruction(X86.Call, null, interruptMethod); ctx.AppendInstruction(X86.Popad); ctx.AppendInstruction(X86.Add, esp, Operand.CreateConstant(BuiltInSigType.Int32, 0x08)); ctx.AppendInstruction(X86.Sti); ctx.AppendInstruction(X86.IRetd); LinkTimeCodeGenerator.Compile(this.compiler, @"InterruptISR" + i.ToString(), instructionSet, typeSystem); } }
/// <summary> /// Creates the ISR methods. /// </summary> private void CreateExceptionVector() { RuntimeType runtimeType = typeSystem.GetType(@"Mosa.Kernel.x86.IDT"); if (runtimeType == null) return; RuntimeMethod runtimeMethod = runtimeType.FindMethod(@"ExceptionHandler"); if (runtimeMethod == null) return; SymbolOperand exceptionMethod = SymbolOperand.FromMethod(runtimeMethod); RegisterOperand esp = new RegisterOperand(BuiltInSigType.Int32, GeneralPurposeRegister.ESP); InstructionSet instructionSet = new InstructionSet(100); Context ctx = new Context(instructionSet); // TODO - setup stack for call to the managed exception handler //1. //2. //3. Call the managed exception handler ctx.AppendInstruction(Instruction.CallInstruction, null, exceptionMethod); LinkTimeCodeGenerator.Compile(this.compiler, @"ExceptionVector", instructionSet, typeSystem); }
/// <summary> /// Initializes a new instance of the <see cref="BaseMethodCompiler" /> class. /// </summary> /// <param name="compiler">The assembly compiler.</param> /// <param name="method">The method to compile by this instance.</param> /// <param name="basicBlocks">The basic blocks.</param> /// <param name="instructionSet">The instruction set.</param> protected BaseMethodCompiler(BaseCompiler compiler, MosaMethod method, BasicBlocks basicBlocks, InstructionSet instructionSet) { this.Compiler = compiler; this.Method = method; this.Type = method.DeclaringType; this.Scheduler = compiler.CompilationScheduler; this.Architecture = compiler.Architecture; this.TypeSystem = compiler.TypeSystem; this.TypeLayout = Compiler.TypeLayout; this.InternalTrace = Compiler.InternalTrace; this.Linker = compiler.Linker; this.BasicBlocks = basicBlocks ?? new BasicBlocks(); this.InstructionSet = instructionSet ?? new InstructionSet(256); this.Pipeline = new CompilerPipeline(); this.StackLayout = new StackLayout(Architecture, method.Signature.Parameters.Count + (method.HasThis || method.HasExplicitThis ? 1 : 0)); this.VirtualRegisters = new VirtualRegisters(Architecture); this.LocalVariables = emptyOperandList; this.DominanceAnalysis = new DominanceAnalysis(Compiler.CompilerOptions.DominanceAnalysisFactory, this.BasicBlocks); EvaluateParameterOperands(); this.stop = false; Debug.Assert(this.Linker != null); }
/// <summary> /// Initializes a new instance of the <see cref="SimMethodCompiler" /> class. /// </summary> /// <param name="compiler">The compiler.</param> /// <param name="method">The method.</param> /// <param name="simAdapter">The sim adapter.</param> /// <param name="basicBlocks">The basic blocks.</param> /// <param name="instructionSet">The instruction set.</param> public SimMethodCompiler(SimCompiler compiler, MosaMethod method, ISimAdapter simAdapter, BasicBlocks basicBlocks, InstructionSet instructionSet) : base(compiler, method, basicBlocks, instructionSet) { var compilerOptions = Compiler.CompilerOptions; // Populate the pipeline Pipeline.Add(new IMethodCompilerStage[] { new CILDecodingStage(), new BasicBlockBuilderStage(), new StackSetupStage(), new ExceptionPrologueStage(), new OperandAssignmentStage(), //new SingleUseMarkerStage(), //new OperandUsageAnalyzerStage(), new StaticAllocationResolutionStage(), new CILTransformationStage(), new ConvertCompoundMoveStage(), //new CheckIROperandCountStage(), (compilerOptions.EnableSSA) ? new PromoteLocalVariablesStage() : null, (compilerOptions.EnableSSA) ? new EdgeSplitStage() : null, (compilerOptions.EnableSSA) ? new PhiPlacementStage() : null, (compilerOptions.EnableSSA) ? new EnterSSAStage() : null, (compilerOptions.EnableSSA && compilerOptions.EnableSSAOptimizations) ? new SSAOptimizations() : null, (compilerOptions.EnableSSA) ? new LeaveSSA() : null, (compilerOptions.EnableSSA) ? new ConvertCompoundMoveStage() : null, new PlatformStubStage(), //new CheckPlatformOperandCountStage(), new PlatformEdgeSplitStage(), new GreedyRegisterAllocatorStage(), new StackLayoutStage(), new EmptyBlockRemovalStage(), new BlockOrderingStage(), new SimCodeGeneratorStage(simAdapter), }); }
/// <summary> /// Initializes a new instance of the <see cref="TypeInitializerSchedulerStage"/> class. /// </summary> public TypeInitializerSchedulerStage() { instructionSet = new InstructionSet(1024); ctx = new Context(instructionSet); ctx.AppendInstruction(IR.IRInstruction.Prologue); //ctx.Other = 0; // stacksize }
/// <summary> /// Initializes a new instance of the <see cref="LinkerMethodCompiler"/> class. /// </summary> /// <param name="assemblyCompiler">The assembly compiler executing this method compiler.</param> /// <param name="method">The metadata of the method to compile.</param> /// <param name="instructionSet">The instruction set.</param> /// <exception cref="System.ArgumentNullException"><paramref name="assemblyCompiler"/>, <paramref name="method"/> or <paramref name="instructionSet"/> is null.</exception> public LinkerMethodCompiler(AssemblyCompiler assemblyCompiler, ICompilationSchedulerStage compilationScheduler, RuntimeMethod method, InstructionSet instructionSet) : base(assemblyCompiler, method.DeclaringType, method, instructionSet, compilationScheduler) { this.CreateBlock(-1, 0); this.Pipeline.AddRange(new IMethodCompilerStage[] { new SimpleTraceBlockOrderStage(), new PlatformStubStage(), new CodeGenerationStage(), }); assemblyCompiler.Architecture.ExtendMethodCompilerPipeline(this.Pipeline); }
/// <summary> /// Initializes a new instance of the <see cref="LinkerMethodCompiler"/> class. /// </summary> /// <param name="compiler">The assembly compiler executing this method compiler.</param> /// <param name="method">The metadata of the method to compile.</param> /// <param name="instructionSet">The instruction set.</param> public LinkerMethodCompiler(BaseCompiler compiler, RuntimeMethod method, InstructionSet instructionSet) : base(compiler, method, instructionSet) { BasicBlocks.CreateBlock(BasicBlock.PrologueLabel, 0); BasicBlocks.AddHeaderBlock(BasicBlocks.PrologueBlock); this.Pipeline.AddRange(new IMethodCompilerStage[] { new LoopAwareBlockOrderStage(), new PlatformStubStage(), new CodeGenerationStage(), }); compiler.Architecture.ExtendMethodCompilerPipeline(this.Pipeline); }
private static void CreatePrologueAndEpilogueBlocks(InstructionSet instructionSet, BasicBlocks basicBlocks) { // Create the prologue block var context = instructionSet.CreateNewBlock(basicBlocks, BasicBlock.PrologueLabel); // Add a jump instruction to the first block from the prologue context.AppendInstruction(IRInstruction.Jmp); context.SetBranch(0); var prologue = context.BasicBlock; basicBlocks.AddHeaderBlock(prologue); // Create the epilogue block context = instructionSet.CreateNewBlock(basicBlocks, BasicBlock.EpilogueLabel); var epilogue = context.BasicBlock; }
public static void Run(IInternalTrace internalLog, IPipelineStage stage, RuntimeMethod method, InstructionSet instructionSet, BasicBlocks basicBlocks) { if (internalLog == null) return; if (internalLog.TraceListener == null) return; if (!internalLog.TraceFilter.IsMatch(method, stage.Name)) return; StringBuilder text = new StringBuilder(); // Line number int index = 1; text.AppendLine(String.Format("IR representation of method {0} after stage {1}:", method, stage.Name)); text.AppendLine(); if (basicBlocks.Count > 0) { foreach (BasicBlock block in basicBlocks) { text.AppendFormat("Block #{0} - Label L_{1:X4}", index, block.Label); if (basicBlocks.IsHeaderBlock(block)) text.Append(" [Header]"); text.AppendLine(); text.AppendFormat(" Prev: "); text.AppendLine(ListBlocks(block.PreviousBlocks)); LogInstructions(text, new Context(instructionSet, block)); text.AppendFormat(" Next: "); text.AppendLine(ListBlocks(block.NextBlocks)); text.AppendLine(); index++; } } else { LogInstructions(text, new Context(instructionSet, 0)); } internalLog.TraceListener.SubmitInstructionTraceInformation(method, stage.Name, text.ToString()); }
private static void CreatePrologueAndEpilogueBlocks(InstructionSet instructionSet, BasicBlocks basicBlocks) { // Create the prologue block Context context = new Context(instructionSet); // Add a jump instruction to the first block from the prologue context.AppendInstruction(IRInstruction.Jmp); context.SetBranch(0); context.Label = BasicBlock.PrologueLabel; var prologue = basicBlocks.CreateBlock(BasicBlock.PrologueLabel, context.Index); basicBlocks.AddHeaderBlock(prologue); // Create the epilogue block context = new Context(instructionSet); // Add null instruction, necessary to generate a block index context.AppendInstruction(null); context.Label = BasicBlock.EpilogueLabel; var epilogue = basicBlocks.CreateBlock(BasicBlock.EpilogueLabel, context.Index); }
protected override void Run() { var typeInitializer = Compiler.Pipeline.FindFirst<TypeInitializerSchedulerStage>().TypeInitializerMethod; var basicBlocks = new BasicBlocks(); var instructionSet = new InstructionSet(25); var context = instructionSet.CreateNewBlock(basicBlocks); basicBlocks.AddHeaderBlock(context.BasicBlock); var entryPoint = Operand.CreateSymbolFromMethod(TypeSystem, typeInitializer); context.AppendInstruction(IRInstruction.Call, null, entryPoint); context.MosaMethod = typeInitializer; var method = Compiler.CreateLinkerMethod(StartUpName); Compiler.CompileMethod(method, basicBlocks, instructionSet); Linker.EntryPoint = Linker.GetSymbol(method.FullName, SectionKind.Text); }
/// <summary> /// Creates the interrupt service routine (ISR) methods. /// </summary> private void CreateInterruptVectors() { var type = TypeSystem.GetTypeByName("Mosa.Kernel.x86", "IDT"); if (type == null) return; var method = type.FindMethodByName("ProcessInterrupt"); if (method == null) return; Operand interrupt = Operand.CreateSymbolFromMethod(TypeSystem, method); Operand esp = Operand.CreateCPURegister(TypeSystem.BuiltIn.I4, GeneralPurposeRegister.ESP); for (int i = 0; i <= 255; i++) { BasicBlocks basicBlocks = new BasicBlocks(); InstructionSet instructionSet = new InstructionSet(25); Context ctx = instructionSet.CreateNewBlock(basicBlocks); basicBlocks.AddHeaderBlock(ctx.BasicBlock); ctx.AppendInstruction(X86.Cli); if (i <= 7 || i >= 16 | i == 9) // For IRQ 8, 10, 11, 12, 13, 14 the cpu will automatically pushed the error code ctx.AppendInstruction(X86.Push, null, Operand.CreateConstantUnsignedInt(TypeSystem, 0)); ctx.AppendInstruction(X86.Push, null, Operand.CreateConstantUnsignedInt(TypeSystem, (uint)i)); ctx.AppendInstruction(X86.Pushad); ctx.AppendInstruction(X86.Call, null, interrupt); ctx.AppendInstruction(X86.Popad); ctx.AppendInstruction(X86.Add, esp, esp, Operand.CreateConstantUnsignedInt(TypeSystem, 8)); ctx.AppendInstruction(X86.Sti); ctx.AppendInstruction(X86.IRetd); var interruptMethod = Compiler.CreateLinkerMethod("InterruptISR" + i.ToString()); Compiler.CompileMethod(interruptMethod, basicBlocks, instructionSet); } }
/// <summary> /// Splits the block. /// </summary> /// <param name="ctx">The context.</param> /// <returns></returns> private Context Split(Context ctx, BasicBlocks basicBlocks, InstructionSet instructionSet) { Context current = ctx.Clone(); Context next = ctx.Clone(); next.AppendInstruction(IRInstruction.BlockStart); BasicBlock nextBlock = basicBlocks.CreateBlockWithAutoLabel(next.Index, current.BasicBlock.EndIndex); Context nextContext = new Context(instructionSet, nextBlock); foreach (BasicBlock block in current.BasicBlock.NextBlocks) { nextBlock.NextBlocks.Add(block); block.PreviousBlocks.Remove(current.BasicBlock); block.PreviousBlocks.Add(nextBlock); } current.BasicBlock.NextBlocks.Clear(); current.AppendInstruction(IRInstruction.BlockEnd); current.BasicBlock.EndIndex = current.Index; return nextContext; }
/// <summary> /// Creates a method compiler /// </summary> /// <param name="method">The method to compile.</param> /// <param name="basicBlocks">The basic blocks.</param> /// <param name="instructionSet">The instruction set.</param> /// <returns></returns> public abstract BaseMethodCompiler CreateMethodCompiler(MosaMethod method, BasicBlocks basicBlocks, InstructionSet instructionSet);
/// <summary> /// Initializes a new instance of the <see cref="BaseMethodCompiler"/> class. /// </summary> /// <param name="assemblyCompiler">The assembly compiler.</param> /// <param name="type">The type, which owns the method to compile.</param> /// <param name="method">The method to compile by this instance.</param> /// <param name="instructionSet">The instruction set.</param> /// <param name="compilationScheduler">The compilation scheduler.</param> protected BaseMethodCompiler(AssemblyCompiler assemblyCompiler, RuntimeType type, RuntimeMethod method, InstructionSet instructionSet, ICompilationSchedulerStage compilationScheduler) { if (compilationScheduler == null) throw new ArgumentNullException(@"compilationScheduler"); this.assemblyCompiler = assemblyCompiler; this.method = method; this.type = type; this.compilationScheduler = compilationScheduler; this.moduleTypeSystem = method.Module; this.architecture = assemblyCompiler.Architecture; this.typeSystem = assemblyCompiler.TypeSystem; this.typeLayout = AssemblyCompiler.TypeLayout; this.internalTrace = AssemblyCompiler.InternalTrace; this.linker = assemblyCompiler.Pipeline.FindFirst<IAssemblyLinker>(); this.plugSystem = assemblyCompiler.Pipeline.FindFirst<IPlugSystem>(); this.parameters = new List<Operand>(new Operand[method.Parameters.Count]); this.basicBlocks = new BasicBlocks(); this.instructionSet = instructionSet ?? new InstructionSet(256); this.pipeline = new CompilerPipeline(); this.stackLayout = new StackLayout(architecture, method.Parameters.Count + (method.Signature.HasThis || method.Signature.HasExplicitThis ? 1 : 0)); this.virtualRegisterLayout = new VirtualRegisterLayout(architecture, stackLayout); EvaluateParameterOperands(); }
/// <summary> /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// </summary> public void Dispose() { if (pipeline == null) throw new ObjectDisposedException(@"MethodCompilerBase"); foreach (IMethodCompilerStage mcs in pipeline) { IDisposable d = mcs as IDisposable; if (d != null) d.Dispose(); } pipeline = null; architecture = null; linker = null; method = null; type = null; instructionSet = null; basicBlocks = null; stackLayout = null; locals = null; }
/// <summary> /// Replaces this operand in all uses and defs with the given operand. /// </summary> /// <param name="replacement">The replacement operand.</param> /// <param name="instructionSet">The instruction set.</param> public void Replace(Operand replacement, InstructionSet instructionSet) { // Iterate all definition sites first foreach (int index in Definitions.ToArray()) { Context ctx = new Context(instructionSet, index); if (ctx.Result != null) { // Is this the operand? if (ReferenceEquals(ctx.Result, this)) { ctx.Result = replacement; } } } // Iterate all use sites foreach (int index in Uses.ToArray()) { Context ctx = new Context(instructionSet, index); int opIdx = 0; foreach (Operand r in ctx.Operands) { // Is this the operand? if (ReferenceEquals(r, this)) { ctx.SetOperand(opIdx, replacement); } opIdx++; } } }
/// <summary> /// Initializes a new instance of the <see cref="Context"/> class. /// </summary> /// <param name="instructionSet">The instruction set.</param> public Context(InstructionSet instructionSet) : this(instructionSet, null, -1) { }
/// <summary> /// Initializes a new instance of the <see cref="Context"/> class. /// </summary> /// <param name="instructionSet">The instruction set.</param> /// <param name="basicBlock">The basic block.</param> public Context(InstructionSet instructionSet, BasicBlock basicBlock) : this(instructionSet, basicBlock, basicBlock.Index) { }
/// <summary> /// Initializes a new instance of the <see cref="Context"/> class. /// </summary> /// <param name="instructionSet">The instruction set.</param> /// <param name="index">The index.</param> public Context(InstructionSet instructionSet, int index) : this(instructionSet, null, index) { }
protected override void Run() { if (multibootMethod == null) { multibootHeader = Linker.CreateSymbol(MultibootHeaderSymbolName, SectionKind.Text, 1, 0x30); multibootMethod = Compiler.CreateLinkerMethod("MultibootInit"); Linker.EntryPoint = Linker.GetSymbol(multibootMethod.FullName, SectionKind.Text); WriteMultibootHeader(); return; } var typeInitializerSchedulerStage = Compiler.Pipeline.FindFirst<TypeInitializerSchedulerStage>(); var ecx = Operand.CreateCPURegister(TypeSystem.BuiltIn.I4, GeneralPurposeRegister.ECX); var eax = Operand.CreateCPURegister(TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EAX); var ebx = Operand.CreateCPURegister(TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EBX); var ebp = Operand.CreateCPURegister(TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EBP); var basicBlocks = new BasicBlocks(); var instructionSet = new InstructionSet(25); var ctx = instructionSet.CreateNewBlock(basicBlocks); basicBlocks.AddHeaderBlock(ctx.BasicBlock); // set sentinal on the stack to indicate the start of the stack var zero = Operand.CreateConstant(TypeSystem.BuiltIn.I4, 0); ctx.AppendInstruction(X86.Mov, Operand.CreateMemoryAddress(TypeSystem.BuiltIn.I4, ebp, 0), zero); // store multiboot registers eax and ebx at 0x200000 and 0x200004 respectively ctx.AppendInstruction(X86.Mov, ecx, Operand.CreateConstantSignedInt(TypeSystem, 0x200000)); ctx.AppendInstruction(X86.Mov, Operand.CreateMemoryAddress(TypeSystem.BuiltIn.I4, ecx, 0), eax); ctx.AppendInstruction(X86.Mov, Operand.CreateMemoryAddress(TypeSystem.BuiltIn.I4, ecx, 4), ebx); // call type initializer var entryPoint = Operand.CreateSymbolFromMethod(TypeSystem, typeInitializerSchedulerStage.TypeInitializerMethod); ctx.AppendInstruction(X86.Call, null, entryPoint); // should never get here ctx.AppendInstruction(X86.Ret); Compiler.CompileMethod(multibootMethod, basicBlocks, instructionSet); }
/// <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 = BuiltInSigType.Int32; 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); ctx.AppendInstruction(X86.Mov, ecx, new ConstantOperand(I4, 0x200000)); ctx.AppendInstruction(X86.Mov, new MemoryOperand(ecx.Register, I4, new IntPtr(0x0)), eax); ctx.AppendInstruction(X86.Mov, new MemoryOperand(ecx.Register, I4, new IntPtr(0x4)), ebx); SymbolOperand entryPoint = SymbolOperand.FromMethod(typeInitializerSchedulerStage.TypeInitializerMethod); ctx.AppendInstruction(X86.Call, null, entryPoint); ctx.AppendInstruction(X86.Ret); LinkerGeneratedMethod method = LinkTimeCodeGenerator.Compile(this.compiler, @"MultibootInit", instructionSet, typeSystem); linker.EntryPoint = linker.GetSymbol(method.ToString()); } }
/// <summary> /// Creates a method compiler /// </summary> /// <param name="method">The method to compile.</param> /// <param name="basicBlocks">The basic blocks.</param> /// <param name="instructionSet">The instruction set.</param> /// <returns> /// An instance of a MethodCompilerBase for the given type/method pair. /// </returns> public override BaseMethodCompiler CreateMethodCompiler(MosaMethod method, BasicBlocks basicBlocks, InstructionSet instructionSet) { return new ExplorerMethodCompiler(this, method, basicBlocks, instructionSet, emitBinary); }
/// <summary> /// Setups the specified compiler. /// </summary> /// <param name="compiler">The compiler.</param> public void Setup(IMethodCompiler compiler) { if (compiler == null) throw new ArgumentNullException(@"compiler"); methodCompiler = compiler; instructionSet = compiler.InstructionSet; basicBlocks = compiler.BasicBlocks; architecture = compiler.Architecture; typeModule = compiler.Method.Module; typeSystem = compiler.TypeSystem; typeLayout = compiler.TypeLayout; callingConvention = architecture.GetCallingConvention(); architecture.GetTypeRequirements(BuiltInSigType.IntPtr, out nativePointerSize, out nativePointerAlignment); }
/// <summary> /// Creates the method compiler. /// </summary> /// <param name="method">The method.</param> /// <param name="basicBlocks">The basic blocks.</param> /// <param name="instructionSet">The instruction set.</param> /// <returns> /// An instance of a MethodCompilerBase for the given type/method pair. /// </returns> public override BaseMethodCompiler CreateMethodCompiler(MosaMethod method, BasicBlocks basicBlocks, InstructionSet instructionSet) { return new AotMethodCompiler(this, method, basicBlocks, instructionSet); }
/// <summary> /// Initializes a new instance of the <see cref="Context"/> class. /// </summary> /// <param name="instructionSet">The instruction set.</param> /// <param name="block">The basic block.</param> /// <param name="index">The index.</param> public Context(InstructionSet instructionSet, BasicBlock block, int index) { this.instructionSet = instructionSet; this.index = index; this.block = block; }
/// <summary> /// Initializes a new instance of the <see cref="BaseMethodCompiler"/> class. /// </summary> /// <param name="compiler">The assembly compiler.</param> /// <param name="method">The method to compile by this instance.</param> /// <param name="instructionSet">The instruction set.</param> protected BaseMethodCompiler(BaseCompiler compiler, RuntimeMethod method, InstructionSet instructionSet) { this.compiler = compiler; this.method = method; this.type = method.DeclaringType; this.compilationScheduler = compiler.Scheduler; this.moduleTypeSystem = method.Module; this.architecture = compiler.Architecture; this.typeSystem = compiler.TypeSystem; this.typeLayout = Compiler.TypeLayout; this.internalTrace = Compiler.InternalTrace; this.linker = compiler.Linker; this.basicBlocks = new BasicBlocks(); this.instructionSet = instructionSet ?? new InstructionSet(256); this.pipeline = new CompilerPipeline(); this.stackLayout = new StackLayout(architecture, method.Parameters.Count + (method.Signature.HasThis || method.Signature.HasExplicitThis ? 1 : 0)); this.virtualRegisterLayout = new VirtualRegisterLayout(architecture, stackLayout); EvaluateParameterOperands(); this.stopMethodCompiler = false; }