/// <summary> /// Initializes a new instance of the <see cref="RuntimeAttribute"/> class. /// </summary> /// <param name="typeModule">The type module.</param> /// <param name="ctor">The ctor.</param> /// <param name="ctorMethod">The ctor method.</param> /// <param name="blobIndex">Index of the blob.</param> public RuntimeAttribute(ITypeModule typeModule, Token ctor, RuntimeMethod ctorMethod, HeapIndexToken blobIndex) { this.typeModule = typeModule; this.ctorMethod = ctorMethod; this.ctor = ctor; this.blobIndex = blobIndex; }
protected string FormatRuntimeMember(RuntimeMethod method) { if (!showTokenValues.Checked) return method.Name; return "[" + TokenToString(method.Token) + "] " + method.ToString(); }
/// <summary> /// Parses the specified attribute blob and instantiates the attribute. /// </summary> /// <param name="blob">The BLOB.</param> /// <param name="attributeCtor">The constructor of the attribute.</param> /// <returns> /// The fully instantiated and initialized attribute. /// </returns> public static object[] Parse(byte[] blob, RuntimeMethod attributeCtor) { if (blob == null) { throw new ArgumentException(@"Invalid attribute blob token.", @"attributeBlob"); } if (blob.Length == 0) return null; // Create a binary reader for the blob using (BinaryReader reader = new BinaryReader(new MemoryStream(blob), Encoding.UTF8)) { ushort prologue = reader.ReadUInt16(); Debug.Assert(prologue == ATTRIBUTE_BLOB_PROLOGUE, @"Attribute prologue doesn't match."); if (prologue != ATTRIBUTE_BLOB_PROLOGUE) throw new ArgumentException(@"Invalid custom attribute blob.", "attributeBlob"); int parameters = attributeCtor.Parameters.Count; object[] args = new object[parameters]; for (int idx = 0; idx < parameters; idx++) args[idx] = ParseFixedArg(reader, attributeCtor.Signature.Parameters[idx]); // Create the attribute instance return args; } }
/// <summary> /// Parses the specified attribute blob and instantiates the attribute. /// </summary> /// <param name="blob">The BLOB.</param> /// <param name="attributeCtor">The constructor of the attribute.</param> /// <returns> /// The fully instantiated and initialized attribute. /// </returns> public static object[] Parse(byte[] blob, RuntimeMethod attributeCtor) { if (blob == null) { throw new ArgumentException(@"Invalid attribute blob token.", @"attributeBlob"); } if (blob.Length == 0) { return(null); } // Create a binary reader for the blob using (BinaryReader reader = new BinaryReader(new MemoryStream(blob), Encoding.UTF8)) { ushort prologue = reader.ReadUInt16(); Debug.Assert(prologue == ATTRIBUTE_BLOB_PROLOGUE, @"Attribute prologue doesn't match."); if (prologue != ATTRIBUTE_BLOB_PROLOGUE) { throw new ArgumentException(@"Invalid custom attribute blob.", "attributeBlob"); } int parameters = attributeCtor.Parameters.Count; object[] args = new object[parameters]; for (int idx = 0; idx < parameters; idx++) { args[idx] = ParseFixedArg(reader, attributeCtor.Signature.Parameters[idx]); } // Create the attribute instance return(args); } }
/// <summary> /// Initializes a new instance of the <see cref="MemberOperand"/> class. /// </summary> /// <param name="method">The method to reference.</param> /// <exception cref="System.ArgumentNullException"><paramref name="method"/> is null.</exception> public MemberOperand(RuntimeMethod method) : base(new SigType(CilElementType.I), null, IntPtr.Zero) { if (method == null) throw new ArgumentNullException(@"method"); this.member = method; }
/// <summary> /// Loads the parameters. /// </summary> /// <param name="method">The method.</param> /// <param name="first">The first.</param> /// <param name="max">The max.</param> private void LoadParameters(RuntimeMethod method, Token first, Token max) { foreach (Token token in first.Upto(max.PreviousRow)) //for (TokenTypes token = first; token < max; token++) { ParamRow paramDef = metadataProvider.ReadParamRow(token); method.Parameters.Add(new RuntimeParameter(GetString(paramDef.NameIdx), paramDef.Sequence, paramDef.Flags)); } }
/// <summary> /// Creates a method compiler /// </summary> /// <param name="type">The type.</param> /// <param name="method">The method to compile.</param> /// <returns> /// An instance of a MethodCompilerBase for the given type/method pair. /// </returns> public override IMethodCompiler CreateMethodCompiler(ICompilationSchedulerStage compilationScheduler, RuntimeType type, RuntimeMethod method) { IMethodCompiler mc = new AotMethodCompiler( this, compilationScheduler, type, method ); this.Architecture.ExtendMethodCompilerPipeline(mc.Pipeline); return mc; }
private int FindOverrideSlot(IList <RuntimeMethod> methodTable, RuntimeMethod method) { foreach (RuntimeMethod baseMethod in methodTable) { if (baseMethod.Name.Equals(method.Name) && baseMethod.Signature.Matches(method.Signature)) { return(methodTableOffsets[baseMethod]); } } throw new InvalidOperationException(@"Failed to find override method slot."); }
/// <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> /// <exception cref="System.ArgumentNullException"><paramref name="compiler"/>, <paramref name="method"/> or <paramref name="instructionSet"/> is null.</exception> public LinkerMethodCompiler(AssemblyCompiler compiler, ICompilationSchedulerStage compilationScheduler, RuntimeMethod method, InstructionSet instructionSet) : base(compiler.Pipeline.FindFirst<IAssemblyLinker>(), compiler.Architecture, compilationScheduler, method.DeclaringType, method, compiler.TypeSystem, compiler.TypeLayout) { this.InstructionSet = instructionSet; this.CreateBlock(-1, 0); this.Pipeline.AddRange(new IMethodCompilerStage[] { new SimpleTraceBlockOrderStage(), new PlatformStubStage(), new CodeGenerationStage(), }); compiler.Architecture.ExtendMethodCompilerPipeline(this.Pipeline); }
/// <summary> /// Determines if the given method is a method /// of a generic class that uses a generic parameter. /// </summary> /// <param name="method">The method to check</param> /// <returns>True if the method relies upon generic parameters</returns> public static bool HasGenericParameters(RuntimeMethod method) { // Check return type if (IsGenericParameter(method.Signature.ReturnType)) return true; // Check parameters foreach (SigType parameter in method.Signature.Parameters) { if (IsGenericParameter(parameter)) return true; } return false; }
/// <summary> /// Gets the method. /// </summary> /// <param name="token">The token.</param> /// <param name="callingType">Type of the calling.</param> /// <returns></returns> RuntimeMethod ITypeModule.GetMethod(Token token, RuntimeType callingType) { RuntimeMethod calledMethod = (this as ITypeModule).GetMethod(token); if (callingType == null) { return(calledMethod); } if (calledMethod.DeclaringType.Namespace != callingType.Namespace) { return(calledMethod); } string declaringTypeName = calledMethod.DeclaringType.Name; if (declaringTypeName.Contains("<")) { declaringTypeName = declaringTypeName.Substring(0, declaringTypeName.IndexOf('<')); } string callingTypeName = callingType.Name; if (callingTypeName.Contains("<")) { callingTypeName = callingTypeName.Substring(0, callingTypeName.IndexOf('<')); } if (declaringTypeName != callingTypeName) { return(calledMethod); } foreach (RuntimeMethod m in callingType.Methods) { if (calledMethod.Name == m.Name) { return(m); } } return(calledMethod); }
/// <summary> /// Initializes a new instance of the <see cref="AotMethodCompiler"/> class. /// </summary> public AotMethodCompiler(AssemblyCompiler compiler, ICompilationSchedulerStage compilationScheduler, RuntimeType type, RuntimeMethod method) : base(compiler.Pipeline.FindFirst<IAssemblyLinker>(), compiler.Architecture, compilationScheduler, type, method, compiler.TypeSystem, compiler.TypeLayout) { this.assemblyCompiler = compiler; this.Pipeline.AddRange( new IMethodCompilerStage[] { new DecodingStage(), //InstructionLogger.Instance, new BasicBlockBuilderStage(), InstructionLogger.Instance, new OperandDeterminationStage(), InstructionLogger.Instance, StaticAllocationResolutionStageWrapper.Instance, //InstructionLogger.Instance, new CILTransformationStage(), InstructionLogger.Instance, //InstructionStatisticsStage.Instance, //new DominanceCalculationStage(), //InstructionLogger.Instance, //new EnterSSA(), //InstructionLogger.Instance, //new ConstantPropagationStage(), //InstructionLogger.Instance, //new ConstantFoldingStage(), //new StrengthReductionStage(), //InstructionLogger.Instance, //new LeaveSSA(), //InstructionLogger.Instance, new StackLayoutStage(), //InstructionLogger.Instance, new PlatformStubStage(), InstructionLogger.Instance, //new BlockReductionStage(), new LoopAwareBlockOrderStage(), InstructionLogger.Instance, //new SimpleTraceBlockOrderStage(), //new ReverseBlockOrderStage(), //new LocalCSE(), new CodeGenerationStage(), }); }
/// <summary> /// Gets the interface table. /// </summary> /// <param name="type">The type.</param> /// <param name="interfaceType">Type of the interface.</param> /// <returns></returns> RuntimeMethod[] ITypeLayout.GetInterfaceTable(RuntimeType type, RuntimeType interfaceType) { if (type.Interfaces.Count == 0) { return(null); } ResolveType(type); RuntimeMethod[] methodTable = new RuntimeMethod[interfaceType.Methods.Count]; // Implicit Interface Methods for (int slot = 0; slot < interfaceType.Methods.Count; slot++) { methodTable[slot] = FindInterfaceMethod(type, interfaceType.Methods[slot]); } // Explicit Interface Methods ScanExplicitInterfaceImplementations(type, interfaceType, methodTable); return(methodTable); }
public TestCaseMethodCompiler(TestCaseAssemblyCompiler compiler, IArchitecture architecture, ICompilationSchedulerStage compilationScheduler, RuntimeType type, RuntimeMethod method) : base(compiler.Pipeline.FindFirst<IAssemblyLinker>(), architecture, compilationScheduler, type, method, compiler.TypeSystem, compiler.TypeLayout) { this.assemblyCompiler = compiler; // Populate the pipeline this.Pipeline.AddRange(new IMethodCompilerStage[] { new DecodingStage(), //new InstructionLogger(), new BasicBlockBuilderStage(), //new InstructionLogger(), new OperandDeterminationStage(), //new InstructionLogger(), new StaticAllocationResolutionStage(), //new InstructionLogger(), //new ConstantFoldingStage(), new CILTransformationStage(), //new InstructionLogger(), new CILLeakGuardStage() { MustThrowCompilationException = true }, //new InstructionLogger(), //InstructionStatisticsStage.Instance, //new DominanceCalculationStage(), //new EnterSSA(), //new ConstantPropagationStage(), //new ConstantFoldingStage(), //new LeaveSSA(), new StackLayoutStage(), new PlatformStubStage(), //new InstructionLogger(), //new BlockReductionStage(), new LoopAwareBlockOrderStage(), //new SimpleTraceBlockOrderStage(), //new ReverseBlockOrderStage(), // reverse all the basic blocks and see if it breaks anything //new BasicBlockOrderStage() new CodeGenerationStage(), //new InstructionLogger(), }); }
private RuntimeMethod FindInterfaceMethod(RuntimeType type, RuntimeMethod interfaceMethod) { string cleanInterfaceMethodName = GetCleanMethodName(interfaceMethod.Name); foreach (RuntimeMethod method in type.Methods) { string cleanMethodName = GetCleanMethodName(method.Name); if (cleanInterfaceMethodName.Equals(cleanMethodName)) { if (interfaceMethod.Signature.Matches(method.Signature)) { return(method); } } } if (type.BaseType != null) { System.Console.WriteLine("Descending from " + type + " to " + type.BaseType); return(FindInterfaceMethod(type.BaseType, interfaceMethod)); } throw new InvalidOperationException(@"Failed to find implicit interface implementation for type " + type + " and interface method " + interfaceMethod); }
/// <summary> /// Issues a linker request for the given runtime method. /// </summary> /// <param name="linkType">The type of link required.</param> /// <param name="method">The method the patched code belongs to.</param> /// <param name="methodOffset">The offset inside the method where the patch is placed.</param> /// <param name="methodRelativeBase">The base address, if a relative link is required.</param> /// <param name="symbol">The linker symbol to link against.</param> /// <returns> /// The return value is the preliminary address to place in the generated machine /// code. On 32-bit systems, only the lower 32 bits are valid. The above are not used. An implementation of /// IAssemblyLinker may not rely on 64-bits being stored in the memory defined by position. /// </returns> public virtual long Link(LinkType linkType, RuntimeMethod method, int methodOffset, int methodRelativeBase, string symbol) { return 0; }
private bool ReplaceWithInternalCall(Context context, RuntimeMethod method) { bool internalCall = ((method.ImplAttributes & MethodImplAttributes.InternalCall) == MethodImplAttributes.InternalCall); if (internalCall) { string replacementMethod = this.BuildInternalCallName(method); method = method.DeclaringType.FindMethod(replacementMethod); context.InvokeTarget = method; Operand result = context.Result; List<Operand> operands = new List<Operand>(context.Operands); ProcessInvokeInstruction(context, SymbolOperand.FromMethod(method), result, operands); } return internalCall; }
public void AddMethod(RuntimeMethod method) { this.methods.Add(method); }
private void Compile(RuntimeMethod method) { LinkerMethodCompiler methodCompiler = new LinkerMethodCompiler(this.compiler, this.compiler.Pipeline.FindFirst<ICompilationSchedulerStage>(), method, this.InstructionSet); methodCompiler.Compile(); }
/// <summary> /// Creates a method compiler /// </summary> /// <param name="type">The type.</param> /// <param name="method">The method to compile.</param> /// <returns>An instance of a MethodCompilerBase for the given type/method pair.</returns> public abstract IMethodCompiler CreateMethodCompiler(ICompilationSchedulerStage schedulerStage, RuntimeType type, RuntimeMethod method);
/// <summary> /// Sets the instruction. /// </summary> /// <param name="instruction">The instruction.</param> /// <param name="target">The target.</param> public void SetInstruction(IInstruction instruction, RuntimeMethod target) { SetInstruction(instruction); InvokeTarget = target; }
/// <summary> /// Sets the instruction. /// </summary> /// <param name="instruction">The instruction.</param> /// <param name="target">The target.</param> public void AppendInstruction(IInstruction instruction, RuntimeMethod target) { AppendInstruction(instruction); InvokeTarget = target; }
/// <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 (null != d) d.Dispose(); } pipeline.Clear(); pipeline = null; architecture = null; linker = null; method = null; type = null; instructionSet = null; basicBlocks = null; }
/// <summary> /// Issues a linker request for the given runtime method. /// </summary> /// <param name="method">The method the patched code belongs to.</param> /// <param name="methodOffset">The offset inside the method where the patch is placed.</param> /// <param name="linkType">The type of link required.</param> /// <param name="methodRelativeBase">The base address, if a relative link is required.</param> /// <param name="target">The method or static field to link against.</param> /// <returns> /// The return value is the preliminary address to place in the generated machine /// code. On 32-bit systems, only the lower 32 bits are valid. The above are not used. An implementation of /// IAssemblyLinker may not rely on 64-bits being stored in the memory defined by position. /// </returns> public virtual long Link(LinkType linkType, RuntimeMethod method, int methodOffset, int methodRelativeBase, RuntimeMember target) { return 0; }
private int FindOverrideSlot(IList<RuntimeMethod> methodTable, RuntimeMethod method) { foreach (RuntimeMethod baseMethod in methodTable) { if (baseMethod.Name.Equals(method.Name) && baseMethod.Signature.Matches(method.Signature)) { return methodTableOffsets[baseMethod]; } } throw new InvalidOperationException(@"Failed to find override method slot."); }
/// <summary> /// Gets the method table offset. /// </summary> /// <param name="method">The method.</param> /// <returns></returns> int ITypeLayout.GetMethodTableOffset(RuntimeMethod method) { ResolveType(method.DeclaringType); return methodTableOffsets[method]; }
/// <summary> /// Creates a symbol operand for the given method. /// </summary> /// <param name="method">The method to create a symbol operand for.</param> /// <returns>The created symbol operand.</returns> public static SymbolOperand FromMethod(RuntimeMethod method) { string symbolName = method.ToString(); return new SymbolOperand(BuiltInSigType.IntPtr, symbolName); }
/// <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); }
private void CompileMethod(RuntimeMethod method) { Console.ForegroundColor = ConsoleColor.Yellow; Console.Write(@"[Compiling] "); Console.ForegroundColor = ConsoleColor.White; Console.WriteLine(method.ToString()); Debug.WriteLine(@"Compiling " + method.ToString()); using (IMethodCompiler mc = compiler.CreateMethodCompiler(this, method.DeclaringType, method)) { mc.Compile(); //try //{ // mc.Compile(); //} //catch (Exception e) //{ // HandleCompilationException(e); // throw; //} } }
protected void ScheduleMethodForCompilation(RuntimeMethod method) { if (method == null) throw new ArgumentNullException(@"method"); if (!method.IsGeneric) { Console.ForegroundColor = ConsoleColor.Blue; Console.Write(@"[Scheduling] "); Console.ForegroundColor = ConsoleColor.White; Console.WriteLine("{1}.{0}", method.Name, method.DeclaringType.FullName); Debug.WriteLine(String.Format(@"Scheduling {1}.{0}", method.Name, method.DeclaringType.FullName)); methodQueue.Enqueue(method); } }
/// <summary> /// Sets the invoke target. /// </summary> /// <param name="ctx">The context.</param> /// <param name="compiler">The compiler.</param> /// <param name="method">The method.</param> private static void SetInvokeTarget(Context ctx, IMethodCompiler compiler, RuntimeMethod method) { if (method == null) throw new ArgumentNullException(@"method"); // Signature of the call target // Number of parameters required for the call ctx.InvokeTarget = method; // Retrieve the target signature MethodSignature signature = ctx.InvokeTarget.Signature; // Fix the parameter list byte paramCount = (byte)signature.Parameters.Length; if (signature.HasThis && !signature.HasExplicitThis) paramCount++; // Setup operands for parameters and the return value if (signature.ReturnType.Type != CilElementType.Void) { ctx.ResultCount = 1; ctx.Result = compiler.CreateTemporary(signature.ReturnType); } else ctx.ResultCount = 0; ctx.OperandCount = paramCount; }
/// <summary> /// Gets the interface table. /// </summary> /// <param name="type">The type.</param> /// <param name="interfaceType">Type of the interface.</param> /// <returns></returns> RuntimeMethod[] ITypeLayout.GetInterfaceTable(RuntimeType type, RuntimeType interfaceType) { if (type.Interfaces.Count == 0) return null; ResolveType(type); RuntimeMethod[] methodTable = new RuntimeMethod[interfaceType.Methods.Count]; // Implicit Interface Methods for (int slot = 0; slot < interfaceType.Methods.Count; slot++) methodTable[slot] = FindInterfaceMethod(type, interfaceType.Methods[slot]); // Explicit Interface Methods ScanExplicitInterfaceImplementations(type, interfaceType, methodTable); return methodTable; }
/// <summary> /// Initializes a new instance of the <see cref="RuntimeMethodData"/> class. /// </summary> /// <param name="runtimeMethod">The runtime method.</param> public RuntimeMethodData(RuntimeMethod runtimeMethod) { RuntimeMethod = runtimeMethod; }
private RuntimeMethod FindInterfaceMethod(RuntimeType type, RuntimeMethod interfaceMethod) { string cleanInterfaceMethodName = GetCleanMethodName(interfaceMethod.Name); foreach (RuntimeMethod method in type.Methods) { string cleanMethodName = GetCleanMethodName(method.Name); if (cleanInterfaceMethodName.Equals(cleanMethodName)) { if (interfaceMethod.Signature.Matches(method.Signature)) { return method; } } } if (type.BaseType != null) { System.Console.WriteLine("Descending from " + type + " to " + type.BaseType); return FindInterfaceMethod(type.BaseType, interfaceMethod); } throw new InvalidOperationException(@"Failed to find implicit interface implementation for type " + type + " and interface method " + interfaceMethod); }
/// <summary> /// Initializes a new instance of the <see cref="BaseMethodCompiler"/> class. /// </summary> /// <param name="linker">The _linker.</param> /// <param name="architecture">The target compilation Architecture.</param> /// <param name="type">The type, which owns the method to compile.</param> /// <param name="method">The method to compile by this instance.</param> protected BaseMethodCompiler( IAssemblyLinker linker, IArchitecture architecture, ICompilationSchedulerStage compilationScheduler, RuntimeType type, RuntimeMethod method, ITypeSystem typeSystem, ITypeLayout typeLayout) { if (architecture == null) throw new ArgumentNullException(@"architecture"); if (linker == null) throw new ArgumentNullException(@"linker"); if (compilationScheduler == null) throw new ArgumentNullException(@"compilationScheduler"); this.linker = linker; this.architecture = architecture; this.method = method; this.type = type; parameters = new List<Operand>(new Operand[method.Parameters.Count]); nextStackSlot = 0; basicBlocks = new List<BasicBlock>(); instructionSet = null; // this will be set later pipeline = new CompilerPipeline(); this.compilationScheduler = compilationScheduler; this.moduleTypeSystem = method.Module; this.typeSystem = typeSystem; this.typeLayout = typeLayout; }
private void ScanExplicitInterfaceImplementations(RuntimeType type, RuntimeType interfaceType, RuntimeMethod[] methodTable) { //TODO: rewrite so that access directly to metadata is not required, type system should assist instead IMetadataProvider metadata = type.Module.MetadataModule.Metadata; Token maxToken = metadata.GetMaxTokenValue(TableType.MethodImpl); foreach (Token token in new Token(TableType.MethodImpl, 1).Upto(maxToken)) { MethodImplRow row = metadata.ReadMethodImplRow(token); if (row.@Class == type.Token) { int slot = 0; foreach (RuntimeMethod interfaceMethod in interfaceType.Methods) { if (interfaceMethod.Token == row.MethodDeclaration) { methodTable[slot] = FindMethodByToken(type, row.MethodBody); } slot++; } } } }
/// <summary> /// Gets the method table offset. /// </summary> /// <param name="method">The method.</param> /// <returns></returns> int ITypeLayout.GetMethodTableOffset(RuntimeMethod method) { ResolveType(method.DeclaringType); return(methodTableOffsets[method]); }