public CilGenericType(RuntimeType type, IMetadataModule referencingModule, GenericInstSigType genericTypeInstanceSignature, ISignatureContext signatureContext) : base(type.Token, type.Module) { this.signature = genericTypeInstanceSignature; this.signatureContext = signatureContext; this.signatureModule = referencingModule; this.Methods = this.GetMethods(); this.Fields = this.GetFields(); }
/// <summary> /// Parses the signature. /// </summary> /// <param name="buffer">The buffer.</param> /// <param name="index">The index.</param> protected override void ParseSignature(ISignatureContext context, byte[] buffer, ref int index) { if (0x0A != buffer[index]) throw new InvalidOperationException(@"Invalid signature."); index++; int genArgCount = Utilities.ReadCompressedInt32(buffer, ref index); this.types = new SigType[genArgCount]; for (int i = 0; i < genArgCount; i++) this.types[i] = SigType.ParseTypeSignature(context, buffer, ref index); }
/// <summary> /// Loads the signature. /// </summary> /// <param name="provider">The provider.</param> /// <param name="token">The token.</param> public void LoadSignature(ISignatureContext context, IMetadataProvider provider, TokenTypes token) { byte[] buffer; provider.Read(token, out buffer); int index = 0; this.ParseSignature(context, buffer, ref index); Debug.Assert(index == buffer.Length, @"Signature parser didn't complete."); this.token = token; }
public CilGenericMethod(CilRuntimeMethod method, MethodSignature signature, ISignatureContext signatureContext) : base(method.Token, method.Module, method.DeclaringType) { this.genericMethod = method; this.signatureContext = signatureContext; this.Signature = signature; this.Attributes = method.Attributes; this.ImplAttributes = method.ImplAttributes; this.Rva = method.Rva; this.Parameters = method.Parameters; }
/// <summary> /// Computes the field offset. /// </summary> /// <param name="token">The token.</param> /// <param name="metadataProvider">The metadata provider.</param> /// <param name="architecture">The architecture.</param> /// <returns></returns> public static int ComputeFieldOffset(ISignatureContext context, TokenTypes token, IMetadataProvider metadataProvider, IArchitecture architecture) { Metadata.Tables.TypeDefRow typeDefinition; Metadata.Tables.TypeDefRow followingTypeDefinition; metadataProvider.Read(token, out typeDefinition); metadataProvider.Read(token + 1, out followingTypeDefinition); int result = 0; TokenTypes fieldList = typeDefinition.FieldList; while (fieldList != token) result += FieldSize(context, fieldList++, metadataProvider, architecture); return result; }
/// <summary> /// Fields the size. /// </summary> /// <param name="field">The field.</param> /// <param name="metadataProvider">The metadata provider.</param> /// <param name="architecture">The architecture.</param> /// <returns></returns> public static int FieldSize(ISignatureContext context, TokenTypes field, IMetadataProvider metadataProvider, IArchitecture architecture) { Metadata.Tables.FieldRow fieldRow; metadataProvider.Read(field, out fieldRow); FieldSignature signature = Signature.FromMemberRefSignatureToken(context, metadataProvider, fieldRow.SignatureBlobIdx) as FieldSignature; // If the field is another struct, we have to dig down and compute its size too. if (signature.Type.Type == CilElementType.ValueType) { TokenTypes valueTypeSig = ValueTokenTypeFromSignature(metadataProvider, fieldRow.SignatureBlobIdx); return ComputeTypeSize(context, valueTypeSig, metadataProvider, architecture); } int size, alignment; architecture.GetTypeRequirements(signature.Type, out size, out alignment); return size; }
/// <summary> /// Froms the member ref signature token. /// </summary> /// <param name="provider">The provider.</param> /// <param name="token">The token.</param> /// <returns></returns> public static Signature FromMemberRefSignatureToken(ISignatureContext context, IMetadataProvider provider, TokenTypes token) { Signature result; int index = 0; byte[] buffer; provider.Read(token, out buffer); if (0x06 == buffer[0]) { result = new FieldSignature(); result.ParseSignature(context, buffer, ref index); } else { result = new MethodSignature(); result.ParseSignature(context, buffer, ref index); } Debug.Assert(index == buffer.Length, @"Not all signature bytes read."); return result; }
/// <summary> /// Computes the size of the type. /// </summary> /// <param name="token">The token.</param> /// <param name="metadataProvider">The metadata provider.</param> /// <param name="architecture">The architecture.</param> /// <returns></returns> public static int ComputeTypeSize(ISignatureContext context, TokenTypes token, IMetadataProvider metadataProvider, IArchitecture architecture) { Metadata.Tables.TypeDefRow typeDefinition; Metadata.Tables.TypeDefRow followingTypeDefinition = new Mosa.Runtime.Metadata.Tables.TypeDefRow(); metadataProvider.Read(token, out typeDefinition); try { metadataProvider.Read(token + 1, out followingTypeDefinition); } catch (System.Exception) { } int result = 0; TokenTypes fieldList = typeDefinition.FieldList; TokenTypes last = metadataProvider.GetMaxTokenValue(TokenTypes.Field); while (fieldList != followingTypeDefinition.FieldList && fieldList != last) result += FieldSize(context, fieldList++, metadataProvider, architecture); return result; }
/// <summary> /// Parses the specified provider. /// </summary> /// <param name="provider">The provider.</param> /// <param name="token">The token.</param> /// <returns></returns> public static LocalVariableSignature Parse(ISignatureContext context, IMetadataProvider provider, TokenTypes token) { var signature = new LocalVariableSignature(); signature.LoadSignature(context, provider, token); return signature; }
private SigType ApplySpecification(ISignatureContext context, MethodSpecSignature specification, SigType sigType) { SigType result = sigType; if (sigType is VarSigType) { result = context.GetGenericTypeArgument(((VarSigType)sigType).Index); } else if (sigType is MVarSigType) { result = specification.Types[((MVarSigType)sigType).Index]; } Debug.WriteLine(String.Format(@"Replaced {0} by {1}.", sigType, result)); return result; }
/// <summary> /// Parses the signature. /// </summary> /// <param name="buffer">The buffer.</param> /// <param name="index">The index.</param> protected override sealed void ParseSignature(ISignatureContext context, byte[] buffer, ref int index) { // Check for instance signature if (HAS_THIS == (buffer[index] & HAS_THIS)) { _hasThis = true; } if (HAS_EXPLICIT_THIS == (buffer[index] & HAS_EXPLICIT_THIS)) _hasExplicitThis = true; if (GENERIC == (buffer[index] & GENERIC)) { _callingConvention = CallingConvention.Generic; _genericParameterCount = Utilities.ReadCompressedInt32(buffer, ref index); } else if (VARARG == (buffer[index] & VARARG)) { _callingConvention = CallingConvention.Vararg; } else if (0x00 != (buffer[index] & 0x1F)) { throw new InvalidOperationException(@"Invalid method definition signature."); } index++; // Number of parameters int paramCount = Utilities.ReadCompressedInt32(buffer, ref index); _parameters = new SigType[paramCount]; // Read the return type _returnType = SigType.ParseTypeSignature(context, buffer, ref index); // Read all parameters for (int i = 0; i < paramCount; i++) _parameters[i] = SigType.ParseTypeSignature(context, buffer, ref index); }
/// <summary> /// Initializes a new instance of the <see cref="MethodSignature"/> class. /// </summary> /// <param name="context">The context of the generic method spec signature.</param> /// <param name="signature">The signature of the generic method.</param> /// <param name="specification">The signature specifying replacements for the generic signature.</param> public MethodSignature(ISignatureContext context, MethodSignature signature, MethodSpecSignature specification) { if (context == null) throw new ArgumentNullException(@"context"); if (signature == null) throw new ArgumentNullException(@"signature"); if (specification == null) throw new ArgumentNullException(@"specification"); this._callingConvention = signature.CallingConvention; this._hasExplicitThis = signature.HasExplicitThis; this._hasThis = signature.HasThis; this._genericParameterCount = 0; int length = signature.Parameters.Length; this._parameters = new SigType[length]; for (int index = 0; index < length; index++) { this._parameters[index] = this.ApplySpecification(context, specification, signature.Parameters[index]); } this._returnType = this.ApplySpecification(context, specification, signature.ReturnType); }
private int ReserveStackSizeForCall(Context ctx, IMetadataProvider metadata, ISignatureContext signatureContext, IEnumerable<Operand> operands) { int stackSize = CalculateStackSizeForParameters(signatureContext, operands, metadata); if (stackSize != 0) { RegisterOperand esp = new RegisterOperand(BuiltInSigType.IntPtr, GeneralPurposeRegister.ESP); ctx.AppendInstruction(CPUx86.Instruction.SubInstruction, esp, new ConstantOperand(esp.Type, stackSize)); ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, new RegisterOperand(architecture.NativeType, GeneralPurposeRegister.EDX), esp); } return stackSize; }
/// <summary> /// Calculates the remaining space. /// </summary> /// <param name="ctx">The context.</param> /// <param name="operandStack">The operand stack.</param> /// <param name="space">The space.</param> private void PushOperands(ISignatureContext context, Context ctx, Stack<Operand> operandStack, int space, IMetadataProvider metadata) { while (operandStack.Count != 0) { Operand operand = operandStack.Pop(); int size, alignment; architecture.GetTypeRequirements(operand.Type, out size, out alignment); if (operand.Type.Type == CilElementType.ValueType) size = ObjectModelUtility.ComputeTypeSize(context, (operand.Type as ValueTypeSigType).Token, metadata, architecture); space -= size; Push(ctx, operand, space, size); } }
/// <summary> /// Calculates the stack size for parameters. /// </summary> /// <param name="operands">The operands.</param> /// <param name="metadata">The metadata.</param> /// <returns></returns> private int CalculateStackSizeForParameters(ISignatureContext context, IEnumerable<Operand> operands, IMetadataProvider metadata) { int result = 0; int size, alignment; foreach (Operand op in operands) { this.architecture.GetTypeRequirements(op.Type, out size, out alignment); if (op.Type.Type == CilElementType.ValueType) { size = ObjectModelUtility.ComputeTypeSize(context, (op.Type as Runtime.Metadata.Signatures.ValueTypeSigType).Token, metadata, architecture); } result += size; } return result; }
/// <summary> /// Parses the signature. /// </summary> /// <param name="buffer">The buffer.</param> /// <param name="index">The index.</param> protected abstract void ParseSignature(ISignatureContext context, byte[] buffer, ref int index);
/// <summary> /// Initializes a new instance of the <see cref="MethodSpecSignature"/> class. /// </summary> public MethodSpecSignature(ISignatureContext outerContext) { this.outerContext = outerContext; }
/// <summary> /// Parses the signature. /// </summary> /// <param name="buffer">The buffer.</param> /// <param name="index">The index.</param> protected override void ParseSignature(ISignatureContext context, byte[] buffer, ref int index) { // Check signature identifier if (buffer[index++] != 0x07) throw new ArgumentException(@"Token doesn't represent a local variable signature.", @"token"); // Retrieve the number of locals int count = Utilities.ReadCompressedInt32(buffer, ref index); if (0 != count) { this.types = new SigType[count]; for (int i = 0; i < count; i++) { this.types[i] = SigType.ParseTypeSignature(context, buffer, ref index); } } }
/// <summary> /// Calculates the stack size for parameters. /// </summary> /// <param name="ctx">The context.</param> /// <returns></returns> private int CalculateStackSizeForParameters(ISignatureContext context, Context ctx, IMetadataProvider metadata) { return CalculateStackSizeForParameters(context, ctx.Operands, ctx.InvokeTarget.Signature.HasThis, metadata); }
/// <summary> /// Expands the given invoke instruction to perform the method call. /// </summary> /// <param name="ctx">The context.</param> /// <returns> /// A single instruction or an array of instructions, which appropriately represent the method call. /// </returns> void ICallingConvention.Expand(ISignatureContext context, Context ctx, IMetadataProvider metadata) { /* * 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. * */ Mosa.Runtime.Vm.RuntimeMethod invokeTarget = ctx.InvokeTarget; Operand result = ctx.Result; Operand operand1 = ctx.Operand1; List<Operand> operands = new List<Operand>(); operands.AddRange(ctx.Operands); int resultCount = ctx.ResultCount; int operandCount = ctx.OperandCount; SigType I = new SigType(CilElementType.I); RegisterOperand esp = new RegisterOperand(I, GeneralPurposeRegister.ESP); int stackSize = CalculateStackSizeForParameters(context, operands, invokeTarget.Signature.HasThis, metadata); ctx.SetInstruction(CPUx86.Instruction.NopInstruction); if (stackSize != 0) { ctx.AppendInstruction(CPUx86.Instruction.SubInstruction, esp, new ConstantOperand(I, stackSize)); ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, new RegisterOperand(architecture.NativeType, GeneralPurposeRegister.EDX), esp); Stack<Operand> operandStack = GetOperandStackFromInstruction(operands, operandCount, invokeTarget.Signature.HasThis); int space = stackSize; CalculateRemainingSpace(context, ctx, operandStack, ref space, metadata); } if (invokeTarget.Signature.HasThis) { RegisterOperand ecx = new RegisterOperand(I, GeneralPurposeRegister.ECX); RegisterOperand eax = new RegisterOperand(I, GeneralPurposeRegister.EAX); //ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, eax, operand1); //ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, new MemoryOperand (new SigType(CilElementType.Ptr), GeneralPurposeRegister.EDX, new IntPtr(0)), eax); } ctx.AppendInstruction(IR.Instruction.CallInstruction, invokeTarget); if (stackSize != 0) ctx.AppendInstruction(CPUx86.Instruction.AddInstruction, esp, new ConstantOperand(I, stackSize)); if (resultCount > 0) if (result.StackType == StackTypeCode.Int64) MoveReturnValueTo64Bit(result, ctx); else MoveReturnValueTo32Bit(result, ctx); //ctx.Remove(); }
/// <summary> /// Expands the given invoke instruction to perform the method call. /// </summary> /// <param name="ctx">The context.</param> /// <returns> /// A single instruction or an array of instructions, which appropriately represent the method call. /// </returns> public void MakeCall(Context ctx, ISignatureContext context, IMetadataProvider metadata) { /* * 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. * */ Operand invokeTarget = ctx.Operand1; Operand result = ctx.Result; Stack<Operand> operands = this.BuildOperandStack(ctx); ctx.ReplaceInstructionOnly(CPUx86.Instruction.NopInstruction); ctx.OperandCount = 0; ctx.Result = null; int stackSize = this.ReserveStackSizeForCall(ctx, metadata, context, operands); if (stackSize != 0) { this.PushOperands(context, ctx, operands, stackSize, metadata); } ctx.AppendInstruction(CPUx86.Instruction.CallInstruction, null, invokeTarget); if (stackSize != 0) { this.FreeStackAfterCall(ctx, stackSize); } this.CleanupReturnValue(ctx, result); }
/// <summary> /// Parses the signature. /// </summary> /// <param name="buffer">The buffer.</param> /// <param name="index">The index.</param> protected override void ParseSignature(ISignatureContext context, byte[] buffer, ref int index) { throw new Exception("The method or operation is not implemented."); }