public TraceLog(TraceType type, MosaMethod method, string stage, bool active) : this(type) { this.Stage = stage; this.Method = method; this.Active = active; }
public bool IsScheduled(MosaMethod method) { lock (methods) { return methods.Contains(method); } }
public TraceLog(TraceType type, MosaMethod method, string stage, TraceFilter filter) : this(type) { this.Stage = stage; this.Method = method; this.Active = filter.IsMatch(this.Method, this.Stage); }
/// <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="threadID">The thread identifier.</param> protected BaseMethodCompiler(BaseCompiler compiler, MosaMethod method, BasicBlocks basicBlocks, int threadID) { Compiler = compiler; Method = method; Type = method.DeclaringType; Scheduler = compiler.CompilationScheduler; Architecture = compiler.Architecture; TypeSystem = compiler.TypeSystem; TypeLayout = compiler.TypeLayout; Trace = compiler.CompilerTrace; Linker = compiler.Linker; BasicBlocks = basicBlocks ?? new BasicBlocks(); Pipeline = new CompilerPipeline(); StackLayout = new StackLayout(Architecture, method.Signature.Parameters.Count + (method.HasThis || method.HasExplicitThis ? 1 : 0)); VirtualRegisters = new VirtualRegisters(Architecture); LocalVariables = emptyOperandList; ThreadID = threadID; DominanceAnalysis = new Dominance(Compiler.CompilerOptions.DominanceAnalysisFactory, BasicBlocks); PluggedMethod = compiler.PlugSystem.GetPlugMethod(Method); stop = false; MethodData = compiler.CompilerData.GetCompilerMethodData(Method); MethodData.Counters.Clear(); EvaluateParameterOperands(); }
/// <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), }); }
public TraceLog(TraceType type, MosaMethod method, string stage, TraceFilter filter) : this(type) { Stage = stage; Method = method; Active = filter.IsMatch(Method, Stage); }
/// <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(), }); }
public bool IsMatch(MosaMethod method, string stage) { if (!Active) return false; return IsMatch(method.DeclaringType.Name, method.Name, stage); }
/// <summary> /// Calculates the stack size for parameters. /// </summary> /// <param name="typeLayout">The type layouts.</param> /// <param name="operands">The operands.</param> /// <param name="method">The method.</param> /// <returns></returns> protected static int CalculateStackSizeForParameters(MosaTypeLayout typeLayout, BaseArchitecture architecture, List<Operand> operands, MosaMethod method) { Debug.Assert((method.Signature.Parameters.Count + (method.HasThis ? 1 : 0) == operands.Count) || (method.DeclaringType.IsDelegate && method.Signature.Parameters.Count == operands.Count), method.FullName); int offset = method.Signature.Parameters.Count - operands.Count; int result = 0; for (int index = operands.Count - 1; index >= 0; index--) { Operand operand = operands[index]; int size, alignment; architecture.GetTypeRequirements(typeLayout, operand.Type, out size, out alignment); var param = (index + offset >= 0) ? method.Signature.Parameters[index + offset] : null; if (param != null && operand.IsR8 && param.ParameterType.IsR4) { // adjust for parameter size on stack when method parameter is R4 while the calling variable is R8 architecture.GetTypeRequirements(typeLayout, param.ParameterType, out size, out alignment); } result = (int)Alignment.AlignUp(result, (uint)alignment) + size; } return result; }
public CompilerTrace(IInternalTrace internalTrace, MosaMethod method, string stage) : this(internalTrace) { this.Stage = stage; this.Method = method; this.Active = internalTrace.TraceFilter.IsMatch(this.Method, this.Stage); }
/// <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); }
public TraceLog(TraceType type, MosaMethod method, string stage, string section, bool active) : this(type) { Stage = stage; Section = section; Method = method; Active = active; }
/// <summary> /// Gets the plug. /// </summary> /// <param name="method">The method.</param> /// <returns></returns> public MosaMethod GetPlugMethod(MosaMethod method) { MosaMethod plug = null; plugMethods.TryGetValue(method, out plug); return plug; }
public CompilerMethodData(MosaMethod mosaMethod) { if (mosaMethod == null) throw new ArgumentNullException("mosaMethod"); Method = mosaMethod; this.Calls = new List<MosaMethod>(); this.CalledBy = new List<MosaMethod>(); this.CompileCount = 0; }
void ITraceListener.SubmitInstructionTraceInformation(MosaMethod method, string stage, string log) { if (string.IsNullOrEmpty(MethodPipelineExportDirectory)) return; string filename = (method.FullName + ".txt").Replace("<", "[").Replace(">", "]"); if (filename.Length > 200) filename = filename.Substring(0, 200); string fullname = Path.Combine(MethodPipelineExportDirectory, filename); File.AppendAllText(fullname, "[" + stage + "]" + Environment.NewLine + Environment.NewLine + log + Environment.NewLine); }
/// <summary> /// Initializes a new instance of the <see cref="ExplorerMethodCompiler" /> class. /// </summary> /// <param name="compiler">The compiler.</param> /// <param name="method">The method.</param> /// <param name="basicBlocks">The basic blocks.</param> /// <param name="threadID">The thread identifier.</param> public ExplorerMethodCompiler(ExplorerCompiler compiler, MosaMethod method, BasicBlocks basicBlocks, int threadID) : base(compiler, method, basicBlocks, threadID) { var compilerOptions = Compiler.CompilerOptions; // Populate the pipeline Pipeline.Add(new IMethodCompilerStage[] { new CILDecodingStage(), new ExceptionPrologueStage(), new OperandAssignmentStage(), new StackSetupStage(), new CILProtectedRegionStage(), new ExceptionStage(), new StaticAllocationResolutionStage(), new CILTransformationStage(), new UnboxValueTypeStage(), (compilerOptions.EnableInlinedMethods) ? new InlineStage() : null, (compilerOptions.EnableSSA) ? new EdgeSplitStage() : null, (compilerOptions.EnableSSA) ? new PhiPlacementStage() : null, (compilerOptions.EnableSSA) ? new EnterSSAStage() : null, (compilerOptions.EnableSparseConditionalConstantPropagation && compilerOptions.EnableSSA) ? new SparseConditionalConstantPropagationStage() : null, (compilerOptions.EnableOptimizations) ? new IROptimizationStage() : null, //(compilerOptions.TwoPassOptimizationStages && compilerOptions.EnableOptimizations && compilerOptions.EnableSparseConditionalConstantPropagation && compilerOptions.EnableSSA) ? new SparseConditionalConstantPropagationStage() : null, //(compilerOptions.TwoPassOptimizationStages && compilerOptions.EnableOptimizations && compilerOptions.EnableSparseConditionalConstantPropagation && compilerOptions.EnableSSA) ? new IROptimizationStage() : null, (compilerOptions.EnableSSA) ? new LeaveSSA() : null, new IRCleanupStage(), (compilerOptions.EnableInlinedMethods) ? new InlineEvaluationStage() : null, //new StopStage(), new PlatformStubStage(), new PlatformEdgeSplitStage(), new VirtualRegisterRenameStage(), new GreedyRegisterAllocatorStage(), new StackLayoutStage(), new EmptyBlockRemovalStage(), new BlockOrderingStage(), new CodeGenerationStage(compilerOptions.EmitBinary), new GraphVizStage(), (compilerOptions.EmitBinary) ? new ProtectedRegionLayoutStage() : null, (compilerOptions.EmitBinary) ? new DisassemblyStage() : null }); }
public CompilerMethodData GetCompilerMethodData(MosaMethod method) { lock (compilerMethods) { CompilerMethodData compilerMethod; if (!compilerMethods.TryGetValue(method, out compilerMethod)) { compilerMethod = new CompilerMethodData(method); compilerMethods.Add(method, compilerMethod); } return compilerMethod; } }
public MethodData GetMethodData(MosaMethod method, bool create) { lock (methodDataStore) { MethodData methodData = null; if (!methodDataStore.TryGetValue(method, out methodData)) { if (create) { methodData = new MethodData(); methodDataStore.Add(method, methodData); } } return methodData; } }
protected override void Run() { Debug.Assert(setupMethod == null, "SSE setup method already generated!"); setupMethod = Compiler.CreateLinkerMethod("SSEInit"); var eax = Operand.CreateCPURegister(TypeSystem.BuiltIn.U4, GeneralPurposeRegister.EAX); var cr0 = Operand.CreateCPURegister(TypeSystem.BuiltIn.U4, ControlRegister.CR0); var cr4 = Operand.CreateCPURegister(TypeSystem.BuiltIn.U4, ControlRegister.CR4); var basicBlocks = new BasicBlocks(); var block = basicBlocks.CreateBlock(); basicBlocks.AddHeadBlock(block); var ctx = new Context(block); /* ;enable SSE and the like mov eax, cr0 and ax, 0xFFFB ;clear coprocessor emulation CR0.EM or ax, 0x2 ;set coprocessor monitoring CR0.MP mov cr0, eax mov eax, cr4 or ax, 3 << 9 ;set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time mov cr4, eax ret */ ctx.AppendInstruction(X86.MovCR, eax, cr0); ctx.AppendInstruction(X86.And, eax, eax, Operand.CreateConstant(TypeSystem.BuiltIn.U4, 0xFFFB)); ctx.AppendInstruction(X86.Or, eax, eax, Operand.CreateConstant(TypeSystem.BuiltIn.U4, 0x2)); ctx.AppendInstruction(X86.MovCR, cr0, eax); ctx.AppendInstruction(X86.MovCR, eax, cr4); ctx.AppendInstruction(X86.Or, eax, eax, Operand.CreateConstant(TypeSystem.BuiltIn.U4, 0x600)); ctx.AppendInstruction(X86.MovCR, cr4, eax); ctx.AppendInstruction(X86.Ret); Compiler.CompileMethod(setupMethod, basicBlocks, 0); var typeInitializerSchedulerStage = Compiler.PostCompilePipeline.FindFirst<TypeInitializerSchedulerStage>(); typeInitializerSchedulerStage.Schedule(setupMethod); }
public static void Run(IInternalTrace internalLog, string stage, MosaMethod method, InstructionSet instructionSet, BasicBlocks basicBlocks) { if (internalLog == null) return; if (internalLog.TraceListener == null) return; if (!internalLog.TraceFilter.IsMatch(method, stage)) return; StringBuilder text = new StringBuilder(); text.AppendLine(String.Format("IR representation of method {0} after stage {1}:", method.FullName, stage)); text.AppendLine(); if (basicBlocks.Count > 0) { foreach (BasicBlock block in basicBlocks) { text.AppendFormat("Block #{0} - Label L_{1:X4}", block.Sequence, 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(); } } else { LogInstructions(text, new Context(instructionSet, 0)); } internalLog.TraceListener.SubmitInstructionTraceInformation(method, stage, text.ToString()); }
/// <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="threadID">The thread identifier.</param> public AotMethodCompiler(BaseCompiler compiler, MosaMethod method, BasicBlocks basicBlocks, int threadID) : base(compiler, method, basicBlocks, threadID) { var compilerOptions = compiler.CompilerOptions; // Populate the pipeline Pipeline.Add(new IMethodCompilerStage[] { new CILDecodingStage(), new ExceptionPrologueStage(), new OperandAssignmentStage(), new StackSetupStage(), new CILProtectedRegionStage(), new ExceptionStage(), new StaticAllocationResolutionStage(), new CILTransformationStage(), new ConvertCompoundStage(), new UnboxValueTypeStage(), (compilerOptions.EnableInlinedMethods) ? new InlineStage() : null, (compilerOptions.EnableVariablePromotion) ? new PromoteTempVariablesStage() : null, (compilerOptions.EnableSSA) ? new EdgeSplitStage() : null, (compilerOptions.EnableSSA) ? new PhiPlacementStage() : null, (compilerOptions.EnableSSA) ? new EnterSSAStage() : null, (compilerOptions.EnableOptimizations && compilerOptions.EnableSparseConditionalConstantPropagation && compilerOptions.EnableSSA) ? new SparseConditionalConstantPropagationStage() : null, (compilerOptions.EnableOptimizations) ? new IROptimizationStage() : null, (compilerOptions.TwoPassOptimizationStages && compilerOptions.EnableOptimizations && compilerOptions.EnableSparseConditionalConstantPropagation && compilerOptions.EnableSSA) ? new SparseConditionalConstantPropagationStage() : null, (compilerOptions.TwoPassOptimizationStages && compilerOptions.EnableOptimizations && compilerOptions.EnableSparseConditionalConstantPropagation && compilerOptions.EnableSSA) ? new IROptimizationStage() : null, (compilerOptions.EnableSSA) ? new LeaveSSA() : null, new IRCleanupStage(), (compilerOptions.EnableInlinedMethods) ? new InlineEvaluationStage() : null, new PlatformStubStage(), new PlatformEdgeSplitStage(), new GreedyRegisterAllocatorStage(), new StackLayoutStage(), new EmptyBlockRemovalStage(), new BlockOrderingStage(), new CodeGenerationStage(), new ProtectedRegionLayoutStage(), }); }
public static void Run(CompilerTrace compilerTrace, string stage, MosaMethod method, BasicBlocks basicBlocks) { if (compilerTrace == null) return; if (!compilerTrace.TraceFilter.IsMatch(method, stage)) return; var traceLog = new TraceLog(TraceType.InstructionList, method, stage, true); traceLog.Log(String.Format("IR representation of method {0} after stage {1}:", method.FullName, stage)); traceLog.Log(); if (basicBlocks.Count > 0) { foreach (var block in basicBlocks) { traceLog.Log(String.Format("Block #{0} - Label L_{1:X4}", block.Sequence, block.Label) + (basicBlocks.IsHeadBlock(block) ? " [Header]" : string.Empty)); traceLog.Log(" Prev: " + ListBlocks(block.PreviousBlocks)); LogInstructions(traceLog, block.First); traceLog.Log(" Next: " + ListBlocks(block.NextBlocks)); traceLog.Log(); } } else { traceLog.Log("No instructions."); } compilerTrace.NewTraceLog(traceLog); }
/// <summary> /// Schedules the specified method for invocation in the main. /// </summary> /// <param name="method">The method.</param> private void Schedule(MosaMethod method) { var symbol = Operand.CreateSymbolFromMethod(method, TypeSystem); start.AppendInstruction(IRInstruction.CallStatic, null, symbol); }
/// <summary> /// Calculates the stack size for parameters. /// </summary> /// <param name="typeLayout">The type layouts.</param> /// <param name="operands">The operands.</param> /// <param name="method">The method.</param> /// <returns></returns> protected static int CalculateStackSizeForParameters(MosaTypeLayout typeLayout, BaseArchitecture architecture, List <Operand> operands, MosaMethod method) { Debug.Assert((method.Signature.Parameters.Count + (method.HasThis ? 1 : 0) == operands.Count) || (method.DeclaringType.IsDelegate && method.Signature.Parameters.Count == operands.Count), method.FullName); int offset = method.Signature.Parameters.Count - operands.Count; int result = 0; for (int index = operands.Count - 1; index >= 0; index--) { Operand operand = operands[index]; int size, alignment; architecture.GetTypeRequirements(typeLayout, operand.Type, out size, out alignment); var param = (index + offset >= 0) ? method.Signature.Parameters[index + offset] : null; if (param != null && operand.IsR8 && param.ParameterType.IsR4) { // adjust for parameter size on stack when method parameter is R4 while the calling variable is R8 architecture.GetTypeRequirements(typeLayout, param.ParameterType, out size, out alignment); } result = (int)Alignment.AlignUp(result, (uint)alignment) + size; } return(result); }
private void treeView_BeforeSelect(object sender, TreeViewCancelEventArgs e) { CurrentMethodSelected = GetCurrentMethod(); }
/// <summary> /// Gets the method table offset. /// </summary> /// <param name="method">The method.</param> /// <returns></returns> public int GetMethodTableOffset(MosaMethod method) { ResolveType(method.DeclaringType); return(methodTableOffsets[method]); }
public void Schedule(MosaMethod method) { Setup(); Compiler.MethodScheduler.Schedule(method); }
private string GetMethodNameConsiderPlug(MosaMethod method) { var plugMethod = Compiler.PlugSystem.GetReplacement(method); return((plugMethod == null) ? method.FullName : plugMethod.FullName); }
/// <summary> /// Appends the instruction. /// </summary> /// <param name="instruction">The instruction.</param> /// <param name="target">The target.</param> public void AppendInstruction(BaseInstruction instruction, MosaMethod target) { AppendInstruction(); Node.SetInstruction(instruction, target); }
private void ResolveMethod(MosaMethod method) { GenericArgumentResolver resolver = new GenericArgumentResolver(); bool hasOpening = method.DeclaringType.HasOpenGenericParams; if (method.DeclaringType.GenericArguments.Count > 0) { foreach (var i in method.DeclaringType.GenericArguments.GetGenericArguments()) hasOpening |= i.HasOpenGenericParameter(); resolver.PushTypeGenericArguments(method.DeclaringType.GenericArguments.GetGenericArguments()); } if (method.GenericArguments.Count > 0) { foreach (var i in method.GenericArguments.GetGenericArguments()) hasOpening |= i.HasOpenGenericParameter(); resolver.PushMethodGenericArguments(method.GenericArguments.GetGenericArguments()); } using (var mosaMethod = metadata.Controller.MutateMethod(method)) { var desc = method.GetUnderlyingObject<UnitDesc<MethodDef, MethodSig>>(); MosaType returnType = metadata.Loader.GetType(resolver.Resolve(desc.Signature.RetType)); hasOpening |= returnType.HasOpenGenericParams; List<MosaParameter> pars = new List<MosaParameter>(); Debug.Assert(desc.Signature.GetParamCount() + (desc.Signature.HasThis ? 1 : 0) == desc.Definition.Parameters.Count); foreach (var param in desc.Definition.Parameters) { if (!param.IsNormalMethodParameter) continue; var paramType = metadata.Loader.GetType(resolver.Resolve(desc.Signature.Params[param.MethodSigIndex])); var parameter = metadata.Controller.CreateParameter(); using (var mosaParameter = metadata.Controller.MutateParameter(parameter)) { mosaParameter.Name = param.Name; mosaParameter.ParameterAttributes = (MosaParameterAttributes)param.ParamDef.Attributes; mosaParameter.ParameterType = paramType; mosaParameter.DeclaringMethod = method; ResolveCustomAttributes(mosaParameter, param.ParamDef); } pars.Add(parameter); hasOpening |= paramType.HasOpenGenericParams; } mosaMethod.Signature = new MosaMethodSignature(returnType, pars); foreach (var methodImpl in desc.Definition.Overrides) { Debug.Assert(methodImpl.MethodBody == desc.Definition); mosaMethod.Overrides.Add(ResolveMethodOperand(methodImpl.MethodDeclaration, null)); } if (desc.Definition.HasBody) ResolveBody(desc.Definition, mosaMethod, desc.Definition.Body, resolver); mosaMethod.HasOpenGenericParams = hasOpening; ResolveCustomAttributes(mosaMethod, desc.Definition); } }
private void Patch(MosaMethod targetMethod, MosaMethod method) { Trace(InternalTrace.CompilerEvent.Plug, targetMethod.FullName + " with " + method.FullName); Compiler.PlugSystem.CreatePlug(method, targetMethod); }
protected override void RunPreCompile() { foreach (var type in TypeSystem.AllTypes) { string plugTypeTarget = null; var typeAttribute = type.FindCustomAttribute(PlugTypeAttribute); if (typeAttribute != null) { plugTypeTarget = (string)typeAttribute.Arguments[0].Value; } foreach (var method in type.Methods) { if (!method.IsStatic) { continue; } string plugMethodTarget = null; var methodAttribute = method.FindCustomAttribute(PlugMethodAttribute); if (methodAttribute != null) { plugMethodTarget = (string)methodAttribute.Arguments[0].Value; } if (plugTypeTarget != null || plugMethodTarget != null) { string targetAssemblyName; string targetFullTypeName; string targetMethodName; if (plugMethodTarget != null) { targetAssemblyName = ParseAssembly(plugMethodTarget); targetFullTypeName = ParseFullTypeName(plugMethodTarget); targetMethodName = ParseMethod(plugMethodTarget); } else { targetAssemblyName = ParseAssembly(plugTypeTarget); targetFullTypeName = RemoveModule(plugTypeTarget); targetMethodName = method.Name; } string targetNameSpace = ParseNameSpace(targetFullTypeName); string targetTypeName = ParseType(targetFullTypeName); MosaType targetType; if (targetAssemblyName != null) { targetType = TypeSystem.GetTypeByName(TypeSystem.GetModuleByAssembly(targetAssemblyName), targetNameSpace, targetTypeName); } else { targetType = TypeSystem.GetTypeByName(targetNameSpace, targetTypeName); } if (targetType == null) { NewCompilerTraceEvent(CompilerEvent.Warning, String.Format("Plug target type {0} not found. Ignoring plug.", targetAssemblyName != null ? (targetFullTypeName + "(in " + targetAssemblyName + ")") : targetFullTypeName)); continue; } MosaMethod targetMethod = null; foreach (var targetMethodCandidate in targetType.Methods) { if (targetMethodCandidate.Name == targetMethodName) { if (targetMethodCandidate.IsStatic) { if (targetMethodCandidate.Equals(method)) { targetMethod = targetMethodCandidate; break; } } else { if (MatchesWithStaticThis(targetMethodCandidate, method)) { targetMethod = targetMethodCandidate; break; } } } } if (targetMethod != null) { Patch(targetMethod, method); } else { NewCompilerTraceEvent(CompilerEvent.Warning, String.Format("No matching plug target method {0} found in type {1}. Ignoring plug.", targetMethodName, targetType.ToString())); } } } } }
public MethodData GetMethodData(MosaMethod method) { return(CompilerData.GetMethodData(method)); }
private void TreeView_AfterSelect(object sender, TreeViewEventArgs e) { CurrentMethodSelected = GetCurrentMethod(); NodeSelected(); }
protected void UpdateTree(MosaMethod method) { typeSystemTree.Update(method); }
public void CreatePlug(MosaMethod plug, MosaMethod methodToPlug) { plugMethods.Add(methodToPlug, plug); }
private TreeNode GetOrCreateNode(MosaMethod method) { if (map.TryGetValue(method, out TreeNode methodNode)) { return(methodNode); } var type = method.DeclaringType; if (!map.TryGetValue(type, out TreeNode typeNode)) { typeNode = GetOrCreateNode(type); } if (method.ShortName.StartsWith("set_") || method.ShortName.StartsWith("get_")) { return(null); } // find "Methods" node TreeNode methodsNode = null; foreach (var node in typeNode.Nodes) { if (((TreeNode)node).Text == "Methods") { methodsNode = (TreeNode)node; break; } } if (methodsNode == null) { methodsNode = new TreeNode("Methods"); typeNode.Nodes.Add(methodsNode); } methodNode = new TreeNode(method.ShortName) { Tag = method }; map.Add(method, methodNode); AddToTree(methodNode, methodsNode); if (method.IsStatic) { methodNode.Text += " [Static]"; } if (method.IsAbstract) { methodNode.Text += " [Abstract]"; } if (method.IsNewSlot) { methodNode.Text += " [NewSlot]"; } if (method.IsVirtual) { methodNode.Text += " [Virtual]"; } if (method.IsFinal) { methodNode.Text += " [Final]"; } if (method.IsSpecialName) { methodNode.Text += " [SpecialName]"; } if (method.IsRTSpecialName) { methodNode.Text += " [RTSpecialName]"; } if (method.GenericArguments.Count != 0) { var genericParameterNodes = new TreeNode("Generic Arguments Types"); methodNode.Nodes.Add(genericParameterNodes); foreach (var genericParameter in method.GenericArguments) { var GenericParameterNode = new TreeNode(genericParameter.Name); genericParameterNodes.Nodes.Add(GenericParameterNode); } } return(methodNode); }
public void TrackMethodInvoked(MosaMethod method) { }
/// <summary> /// Sets the instruction. /// </summary> /// <param name="instruction">The instruction.</param> /// <param name="target">The target.</param> public void SetInstruction(BaseInstruction instruction, MosaMethod target) { Node.SetInstruction(instruction, target); }
private LinkerSymbol CreateMethodDefinition(MosaMethod method) { // Emit method name var methodNameSymbol = EmitStringWithLength(Metadata.NameString + method.FullName, method.FullName); // Emit method table var methodTableSymbol = Linker.DefineSymbol(Metadata.MethodDefinition + method.FullName, SectionKind.ROData, TypeLayout.NativePointerAlignment, (method.Signature.Parameters.Count + 9) * TypeLayout.NativePointerSize); var writer = new EndianAwareBinaryWriter(methodTableSymbol.Stream, Architecture.Endianness); // 1. Pointer to Name Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, writer.Position, methodNameSymbol, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 2. Pointer to Custom Attributes if (method.CustomAttributes.Count > 0) { var customAttributeListSymbol = CreateCustomAttributesTable(method); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, writer.Position, customAttributeListSymbol, 0); } writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 3. Attributes writer.Write((uint)method.MethodAttributes, TypeLayout.NativePointerSize); // 4. Local Stack Size (16 Bits) && Parameter Stack Size (16 Bits) var methodData = Compiler.CompilerData.GetMethodData(method); int value = methodData.LocalMethodStackSize | (methodData.ParameterStackSize << 16); writer.Write(value, TypeLayout.NativePointerSize); // 5. Pointer to Method if (method.HasImplementation && !method.HasOpenGenericParams && !method.DeclaringType.HasOpenGenericParams /*&& !methodData.Inlined*/) // TODO: Inline { if (Compiler.MethodScanner.IsMethodInvoked(method)) { Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, writer.Position, GetMethodNameConsiderPlug(method), 0); } } writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 6. Pointer to return type Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, writer.Position, Metadata.TypeDefinition + method.Signature.ReturnType.FullName, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 7. Pointer to Exception Handler Table if (method.ExceptionHandlers.Count != 0 && Compiler.MethodScanner.IsMethodInvoked(method)) { Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, writer.Position, Metadata.ProtectedRegionTable + method.FullName, 0); } writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 8. Pointer to GC Tracking information // TODO: This has yet to be designed. writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 9. Number of Parameters writer.Write((uint)method.Signature.Parameters.Count, TypeLayout.NativePointerSize); // 10. Pointers to Parameter Definitions foreach (var parameter in method.Signature.Parameters) { // Create definition and get the symbol var parameterDefinitionSymbol = CreateParameterDefinition(parameter); // Link Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, writer.Position, parameterDefinitionSymbol, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); } return(methodTableSymbol); }
public MosaMethod CompileMethod(MosaMethod method) { return(CompileMethod(method, 0)); }
/// <summary> /// Creates a method compiler /// </summary> /// <param name="method">The method to compile.</param> /// <param name="basicBlocks">The basic blocks.</param> /// <param name="threadID"></param> /// <returns> /// An instance of a MethodCompilerBase for the given type/method pair. /// </returns> protected override BaseMethodCompiler CreateMethodCompiler(MosaMethod method, BasicBlocks basicBlocks, int threadID) { return(new SimMethodCompiler(this, method, simAdapter, basicBlocks, threadID)); }
/// <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> protected override BaseMethodCompiler CreateMethodCompiler(MosaMethod method, BasicBlocks basicBlocks, int threadID) { return(new ExplorerMethodCompiler(this, method, basicBlocks, threadID)); }
/// <summary> /// Expands method call instruction represented by the context to perform the method call. /// </summary> /// <param name="compiler">The compiler.</param> /// <param name="context">The context.</param> public override void MakeCall(BaseMethodCompiler compiler, Context context) { /* * Calling convention is right-to-left, pushed on the stack. Return value in EAX for integral * types 4 bytes or less, XMM0 for floating point and EAX:EDX for 64-bit. If this is a method * of a type, the this argument is moved to ECX right before the call. * If return value is value type, a stack local is allocated as a hidden parameter in caller * stack, the callee will then store the return value in the allocated space * The return value is the first parameter (even before this) * The callee will place the address of the return value into EAX and the caller will then * either retrieve the return value using compound move or will let one of the callers higher * in the caller chain handle the retrieval of the return value using compound move. */ Operand target = context.Operand1; Operand result = context.Result; MosaMethod method = context.InvokeMethod; //Debug.Assert(method != null, context.ToString()); Operand scratch = Operand.CreateCPURegister(compiler.TypeLayout.TypeSystem.BuiltIn.Pointer, scratchRegister); var operands = BuildOperands(context); context.Empty(); int stackSize = 0; int returnSize = 0; if (method != null) { stackSize = CalculateStackSizeForParameters(compiler.TypeLayout, architecture, operands, method); returnSize = CalculateReturnSize(compiler, method); } else { stackSize = CalculateStackSizeForParameters(compiler.TypeLayout, architecture, operands); returnSize = CalculateReturnSize(compiler, result); } if (stackSize != 0 || returnSize != 0) { ReserveStackSizeForCall(compiler, context, returnSize + stackSize, scratch); if (method != null) { PushOperands(compiler, context, method, operands, returnSize + stackSize, scratch); } else { PushOperands(compiler, context, operands, returnSize + stackSize, scratch); } } // the mov/call two-instructions combo is to help facilitate the register allocator architecture.InsertMoveInstruction(context, scratch, target); architecture.InsertCallInstruction(context, scratch); CleanupReturnValue(compiler, context, result); FreeStackAfterCall(compiler, context, returnSize + stackSize); }
public MosaMethod LoadGenericMethodInstance(IMethodDefOrRef method, IList <TypeSig> genericArguments, GenericArgumentResolver resolver) { var declType = GetType(resolver.Resolve(method.DeclaringType.ToTypeSig())); MDToken token; if (method is MethodDef) { token = ((MethodDef)method).MDToken; } else { token = ((MemberRef)method).ResolveMethodThrow().MDToken; } MosaMethod mosaMethod = null; UnitDesc <MethodDef, MethodSig> desc = null; foreach (var m in declType.Methods) { desc = m.GetUnderlyingObject <UnitDesc <MethodDef, MethodSig> >(); if (desc.Token.Token == token) { mosaMethod = m; break; } } if (mosaMethod == null) { throw new AssemblyLoadException(); } var resolvedGenericArguments = new List <TypeSig>(); foreach (var genericArg in genericArguments) { resolvedGenericArguments.Add(resolver.Resolve(genericArg)); } resolver.PushMethodGenericArguments(resolvedGenericArguments); // Check for existing generic method instance var newSig = resolver.Resolve(method.MethodSig); // Need to make sure we pop otherwise it will cause bugs resolver.PopMethodGenericArguments(); var comparer = new SigComparer(); foreach (var m in declType.Methods) { var mDesc = m.GetUnderlyingObject <UnitDesc <MethodDef, MethodSig> >(); if (mDesc.Definition != desc.Definition || !comparer.Equals(mDesc.Signature, newSig)) { continue; } if (m.GenericArguments.Count != resolvedGenericArguments.Count) { continue; } if (m.GenericArguments.Count > 0) { var failedGenericArgumentMatch = false; for (var i = 0; i < m.GenericArguments.Count; i++) { if (comparer.Equals(resolvedGenericArguments[i], m.GenericArguments[i].GetTypeSig())) { continue; } failedGenericArgumentMatch = true; break; } if (failedGenericArgumentMatch) { continue; } } return(m); } mosaMethod = metadata.Controller.CreateMethod(mosaMethod); using (var _mosaMethod = metadata.Controller.MutateMethod(mosaMethod)) { bool hasOpening = mosaMethod.DeclaringType.HasOpenGenericParams; _mosaMethod.GenericArguments.Clear(); foreach (var resolvedGenericArg in resolvedGenericArguments) { hasOpening |= resolvedGenericArg.HasOpenGenericParameter(); var t = GetType(resolvedGenericArg); _mosaMethod.GenericArguments.Add(t); } _mosaMethod.UnderlyingObject = desc.Clone(newSig); _mosaMethod.DeclaringType = declType; _mosaMethod.HasOpenGenericParams = hasOpening; } using (var decl = metadata.Controller.MutateType(declType)) decl.Methods.Add(mosaMethod); metadata.Resolver.EnqueueForResolve(mosaMethod); return(mosaMethod); }
protected string FormatRuntimeMember(MosaMethod method) { return method.Name; }
private void Patch(MosaMethod targetMethod, MosaMethod method) { NewCompilerTraceEvent(CompilerEvent.Plug, targetMethod.FullName + " with " + method.FullName); Compiler.PlugSystem.CreatePlug(method, targetMethod); }
private void UpdateMethodInformation(MosaMethod method) { UpdateStages(); UpdateDebugStages(); UpdateCounters(); }
/// <summary> /// Calculates the remaining space. /// </summary> /// <param name="compiler">The compiler.</param> /// <param name="typeLayout">The type layouts.</param> /// <param name="context">The context.</param> /// <param name="method">The method.</param> /// <param name="operands">The operand stack.</param> /// <param name="space">The space.</param> /// <param name="scratch">The scratch.</param> private void PushOperands(BaseMethodCompiler compiler, MosaTypeLayout typeLayout, Context context, MosaMethod method, List <Operand> operands, int space, Operand scratch) { Debug.Assert((method.Signature.Parameters.Count + (method.HasThis ? 1 : 0) == operands.Count) || (method.DeclaringType.IsDelegate && method.Signature.Parameters.Count == operands.Count)); int offset = method.Signature.Parameters.Count - operands.Count; for (int index = operands.Count - 1; index >= 0; index--) { Operand operand = operands[index]; MosaType param = (index + offset >= 0) ? method.Signature.Parameters[index + offset].ParameterType : null; int size, alignment; if (param != null && operand.IsR8 && param.IsR4) { architecture.GetTypeRequirements(typeLayout, param, out size, out alignment); } else { architecture.GetTypeRequirements(typeLayout, operand.Type, out size, out alignment); } size = Alignment.AlignUp(size, alignment); space -= size; Push(compiler, typeLayout, context, operand, space, size, scratch); } }
/// <summary> /// Creates a new symbol <see cref="Operand" /> for the given symbol name. /// </summary> /// <param name="typeSystem">The type system.</param> /// <param name="method">The method.</param> /// <returns></returns> public static Operand CreateSymbolFromMethod(TypeSystem typeSystem, MosaMethod method) { var operand = CreateUnmanagedSymbolPointer(typeSystem, method.FullName); operand.Method = method; return operand; }
private void ResolveMethod(MosaMethod method) { GenericArgumentResolver resolver = new GenericArgumentResolver(); bool hasOpening = method.DeclaringType.HasOpenGenericParams; if (method.DeclaringType.GenericArguments.Count > 0) { foreach (var i in method.DeclaringType.GenericArguments.GetGenericArguments()) { hasOpening |= i.HasOpenGenericParameter(); } resolver.PushTypeGenericArguments(method.DeclaringType.GenericArguments.GetGenericArguments()); } if (method.GenericArguments.Count > 0) { foreach (var i in method.GenericArguments.GetGenericArguments()) { hasOpening |= i.HasOpenGenericParameter(); } resolver.PushMethodGenericArguments(method.GenericArguments.GetGenericArguments()); } using (var mosaMethod = metadata.Controller.MutateMethod(method)) { var desc = method.GetUnderlyingObject <UnitDesc <MethodDef, MethodSig> >(); MosaType returnType = metadata.Loader.GetType(resolver.Resolve(desc.Signature.RetType)); hasOpening |= returnType.HasOpenGenericParams; List <MosaParameter> pars = new List <MosaParameter>(); Debug.Assert(desc.Signature.GetParamCount() + (desc.Signature.HasThis ? 1 : 0) == desc.Definition.Parameters.Count); foreach (var param in desc.Definition.Parameters) { if (!param.IsNormalMethodParameter) { continue; } var paramType = metadata.Loader.GetType(resolver.Resolve(desc.Signature.Params[param.MethodSigIndex])); var parameter = metadata.Controller.CreateParameter(); using (var mosaParameter = metadata.Controller.MutateParameter(parameter)) { mosaParameter.Name = param.Name; mosaParameter.ParameterAttributes = (MosaParameterAttributes)param.ParamDef.Attributes; mosaParameter.ParameterType = paramType; mosaParameter.DeclaringMethod = method; ResolveCustomAttributes(mosaParameter, param.ParamDef); } pars.Add(parameter); hasOpening |= paramType.HasOpenGenericParams; } mosaMethod.Signature = new MosaMethodSignature(returnType, pars); foreach (var methodImpl in desc.Definition.Overrides) { Debug.Assert(methodImpl.MethodBody == desc.Definition); mosaMethod.Overrides.Add(ResolveMethodOperand(methodImpl.MethodDeclaration, null)); } if (desc.Definition.HasBody) { ResolveBody(desc.Definition, mosaMethod, desc.Definition.Body, resolver); } mosaMethod.HasOpenGenericParams = hasOpening; ResolveCustomAttributes(mosaMethod, desc.Definition); } }
private bool MatchesWithStaticThis(MosaMethod targetMethod, MosaMethod plugMethod) { if (!targetMethod.Signature.ReturnType.Equals(plugMethod.Signature.ReturnType)) return false; if (targetMethod.Signature.Parameters.Count != plugMethod.Signature.Parameters.Count - 1) return false; if (plugMethod.Signature.Parameters[0].Type.IsValueType && !plugMethod.Signature.Parameters[0].Type.IsManagedPointer) return false; // TODO: Compare plug.Parameters[0].Type to the target's type for (int i = 0; i < targetMethod.Signature.Parameters.Count; i++) { if (!targetMethod.Signature.Parameters[i].Equals(plugMethod.Signature.Parameters[i + 1])) return false; } return true; }
void ITraceListener.OnMethodCompiled(MosaMethod method) { }
private void ResolveBody(MethodDef methodDef, MosaMethod.Mutator method, CilBody body, GenericArgumentResolver resolver) { method.LocalVariables.Clear(); int index = 0; foreach (var variable in body.Variables) { method.LocalVariables.Add(new MosaLocal( variable.Name ?? "V_" + index, metadata.Loader.GetType(resolver.Resolve(variable.Type)), variable.Type.IsPinned)); index++; } method.ExceptionBlocks.Clear(); foreach (var eh in body.ExceptionHandlers) { method.ExceptionBlocks.Add(new MosaExceptionHandler( (ExceptionHandlerType)eh.HandlerType, ResolveOffset(body, eh.TryStart), ResolveOffset(body, eh.TryEnd), ResolveOffset(body, eh.HandlerStart), ResolveOffset(body, eh.HandlerEnd), eh.CatchType == null ? null : metadata.Loader.GetType(resolver.Resolve(eh.CatchType.ToTypeSig())), eh.FilterStart == null ? null : (int?)eh.FilterStart.Offset )); } method.MaxStack = methodDef.Body.MaxStack; method.Code.Clear(); for (int i = 0; i < body.Instructions.Count; i++) { method.Code.Add(ResolveInstruction(methodDef, body, i, resolver)); } }
private static void MeasureCompileTime(Stopwatch stopwatch, MosaCompiler compiler, MosaMethod method, int iterations) { Console.WriteLine($"Method: {method}"); double min = double.MaxValue; double max = double.MinValue; double total = 0; for (int i = 0; i < iterations; i++) { var start = stopwatch.Elapsed.TotalMilliseconds; compiler.CompileSingleMethod(method); var elapsed = stopwatch.Elapsed.TotalMilliseconds - start; min = Math.Min(min, elapsed); max = Math.Max(max, elapsed); total += elapsed; //Console.WriteLine($"Elapsed: {elapsed.ToString("F2")} ms"); } double avg = total / iterations; Console.WriteLine($"Elapsed: {max.ToString("F2")} ms (worst)"); Console.WriteLine($"Elapsed: {avg.ToString("F2")} ms (average)"); Console.WriteLine($"Elapsed: {min.ToString("F2")} ms (best)"); }
public void Schedule(MosaMethod method) { if (method.IsAbstract || method.HasOpenGenericParams) return; if (method.IsLinkerGenerated) return; queue.Enqueue(method); lock (methods) { if (!methods.Contains(method)) { methods.Add(method); } } }
private int CalculateInterfaceSlotOffset(MosaMethod invokeTarget) { return(CalculateInterfaceSlot(invokeTarget.DeclaringType) * NativePointerSize); }
private int CalculateMethodTableOffset(MosaMethod invokeTarget) { int slot = TypeLayout.GetMethodSlot(invokeTarget); return(NativePointerSize * slot); }
private LinkerSymbol CreateMethodDefinition(MosaMethod method) { // Emit method name var methodNameSymbol = EmitStringWithLength(method.FullName + Metadata.NameString, method.FullName); // Emit method table var methodTableSymbol = Linker.CreateSymbol(method.FullName + Metadata.MethodDefinition, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0); var writer1 = new EndianAwareBinaryWriter(methodTableSymbol.Stream, Architecture.Endianness); // 1. Pointer to Name Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, (int)writer1.Position, methodNameSymbol, 0); writer1.WriteZeroBytes(TypeLayout.NativePointerSize); // 2. Pointer to Custom Attributes if (method.CustomAttributes.Count > 0) { var customAttributeListSymbol = CreateCustomAttributesTable(method); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, (int)writer1.Position, customAttributeListSymbol, 0); } writer1.WriteZeroBytes(TypeLayout.NativePointerSize); // 3. Attributes writer1.Write((uint)method.MethodAttributes, TypeLayout.NativePointerSize); // 4. Local Stack Size (16 Bits) && Parameter Stack Size (16 Bits) var methodData = Compiler.CompilerData.GetCompilerMethodData(method); int value = methodData.LocalMethodStackSize | (methodData.ParameterStackSize << 16); writer1.Write(value, TypeLayout.NativePointerSize); // 5. Pointer to Method if (!method.IsAbstract) { Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, (int)writer1.Position, SectionKind.Text, method.FullName, 0); } writer1.WriteZeroBytes(TypeLayout.NativePointerSize); // 6. Pointer to return type Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, (int)writer1.Position, SectionKind.ROData, method.Signature.ReturnType.FullName + Metadata.TypeDefinition, 0); writer1.WriteZeroBytes(TypeLayout.NativePointerSize); // 7. Pointer to Exception Handler Table if (method.ExceptionHandlers.Count != 0) { Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, (int)writer1.Position, SectionKind.ROData, method.FullName + Metadata.ProtectedRegionTable, 0); } writer1.WriteZeroBytes(TypeLayout.NativePointerSize); // 8. Pointer to GC Tracking information // TODO: This has yet to be designed. writer1.WriteZeroBytes(TypeLayout.NativePointerSize); // 9. Number of Parameters writer1.Write((uint)method.Signature.Parameters.Count, TypeLayout.NativePointerSize); // 10. Pointers to Parameter Definitions foreach (var parameter in method.Signature.Parameters) { // Create definition and get the symbol var parameterDefinitionSymbol = CreateParameterDefinition(parameter); // Link Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, (int)writer1.Position, parameterDefinitionSymbol, 0); writer1.WriteZeroBytes(TypeLayout.NativePointerSize); } // Return methodTableSymbol for linker usage return(methodTableSymbol); }