/// <summary> /// Lays out all parameters of the method. /// </summary> /// <param name="compiler">The method compiler providing the parameters.</param> private void LayoutParameters(IMethodCompiler compiler) { List <StackOperand> paramOps = new List <StackOperand>(); int offset = 0; if (compiler.Method.Signature.HasThis || compiler.Method.Signature.HasExplicitThis) { ++offset; } for (int i = 0; i < compiler.Method.Parameters.Count + offset; ++i) { paramOps.Add((StackOperand)compiler.GetParameterOperand(i)); } /*if (compiler.Method.Signature.HasThis || compiler.Method.Signature.HasExplicitThis) * LayoutVariables(paramOps, cc, cc.OffsetOfFirstParameter + 4, -1); * else*/ LayoutVariables(paramOps, callingConvention, callingConvention.OffsetOfFirstParameter, -1); if (TRACING.TraceInfo) { LogOperands(paramOps); } }
/// <summary> /// Decodes the instruction stream of the reader and populates the compiler. /// </summary> /// <param name="compiler">The compiler to populate.</param> /// <param name="header">The method _header.</param> private void Decode(IMethodCompiler compiler, ref MethodHeader header) { // Start of the code stream long codeStart = _codeReader.BaseStream.Position; // End of the code stream long codeEnd = _codeReader.BaseStream.Position + header.codeSize; // Prefix instruction //PrefixInstruction prefix = null; // Setup context Context ctx = new Context(InstructionSet, -1); while (codeEnd != _codeReader.BaseStream.Position) { // Determine the instruction offset int instOffset = (int)(_codeReader.BaseStream.Position - codeStart); // Read the next opcode From the stream OpCode op = (OpCode)_codeReader.ReadByte(); if (OpCode.Extop == op) { op = (OpCode)(0x100 | _codeReader.ReadByte()); } ICILInstruction instruction = Instruction.Get(op); if (instruction == null) { throw new Exception("CIL " + op + " is not yet supported"); } //if (instruction is PrefixInstruction) { // prefix = instruction as PrefixInstruction; // continue; //} // Create and initialize the corresponding instruction ctx.AppendInstruction(instruction); instruction.Decode(ctx, this); ctx.Label = instOffset; //ctx.Prefix = prefix; Debug.Assert(ctx.Instruction != null); // Do we need to patch branch targets? if (instruction is IBranchInstruction && instruction.FlowControl != FlowControl.Return) { int pc = (int)(_codeReader.BaseStream.Position - codeStart); for (int i = 0; i < ctx.Branch.Targets.Length; i++) { ctx.Branch.Targets[i] += pc; } } //prefix = null; } }
/// <summary> /// Validates the instruction operands and creates a matching variable for the result. /// </summary> /// <param name="ctx">The context.</param> /// <param name="compiler">The compiler.</param> public override void Validate(Context ctx, IMethodCompiler compiler) { base.Validate(ctx, compiler); var stackTypeForOperand1 = ctx.Operand1.StackType; var stackTypeForOperand2 = ctx.Operand2.StackType; if (ctx.Operand1.Type is ValueTypeSigType) { var op1Type = compiler.Method.Module.GetType ((ctx.Operand1.Type as ValueTypeSigType).Token); if (op1Type.BaseType.FullName == "System.Enum") stackTypeForOperand1 = this.FromSigType (op1Type.Fields[0].SignatureType.Type); } if (ctx.Operand2.Type is ValueTypeSigType) { var op2Type = compiler.Method.Module.GetType ((ctx.Operand2.Type as ValueTypeSigType).Token); if (op2Type.BaseType.FullName == "System.Enum") stackTypeForOperand2 = this.FromSigType (op2Type.Fields[0].SignatureType.Type); } var result = _opTable[(int)stackTypeForOperand1][(int)stackTypeForOperand2]; if (result == StackTypeCode.Unknown) throw new InvalidOperationException (@"Invalid stack result of instruction: " + result.ToString () + " (" + ctx.Operand1.ToString () + ")"); ctx.Result = compiler.CreateTemporary(Operand.SigTypeFromStackType(result)); }
/// <summary> /// Validates the instruction operands and creates a matching variable for the result. /// </summary> /// <param name="ctx">The context.</param> /// <param name="compiler">The compiler.</param> public override void Validate(Context ctx, IMethodCompiler compiler) { base.Validate(ctx, compiler); // Simple result is the same type as the unary argument ctx.Result = compiler.CreateTemporary(ctx.Operand1.Type); }
/// <summary> /// Validates the specified instruction. /// </summary> /// <param name="ctx">The context.</param> /// <param name="compiler">The compiler.</param> public override void Validate(Context ctx, IMethodCompiler compiler) { base.Validate(ctx, compiler); ctx.Result = ctx.Operand1; ctx.Result2 = ctx.Operand1; }
/// <summary> /// Validates the instruction operands and creates a matching variable for the result. /// </summary> /// <param name="ctx">The context.</param> /// <param name="compiler">The compiler.</param> public override void Validate(Context ctx, IMethodCompiler compiler) { base.Validate(ctx, compiler); int paramCount = ctx.InvokeTarget.Signature.Parameters.Length; if (ctx.InvokeTarget.Signature.HasThis && !ctx.InvokeTarget.Signature.HasExplicitThis) { paramCount++; } // Validate the operands... Debug.Assert(ctx.OperandCount == paramCount, @"Operand count doesn't match parameter count."); //for (int i = 0; i < ctx.OperandCount; i++) //{ /* FIXME: Check implicit conversions * // if (ops[i] != null) { * Debug.Assert(_operands[i].Type == _parameterTypes[i]); * if (_operands[i].Type != _parameterTypes[i]) * { * // FIXME: Determine if we can do an implicit conversion * throw new ExecutionEngineException(@"Invalid operand types."); * } */ //} }
/// <summary> /// Validates the instruction operands and creates a matching variable for the result. /// </summary> /// <param name="ctx">The context.</param> /// <param name="compiler">The compiler.</param> public override void Validate(Context ctx, IMethodCompiler compiler) { base.Validate(ctx, compiler); if (compiler == null) { throw new ArgumentNullException(@"compiler"); } // HACK: Don't validate the base class - it still assumes a method call without the this ptr required // for constructors. //base.Validate(compiler); // Validate the operands... Debug.Assert(ctx.OperandCount == ctx.InvokeTarget.Parameters.Count - 1, @"Operand count doesn't match parameter count."); for (int i = 0; i < ctx.OperandCount; i++) { /* FIXME: Check implicit conversions * if (ops[i] != null) { * Debug.Assert(_operands[i].Type == _parameterTypes[i]); * if (_operands[i].Type != _parameterTypes[i]) * { * // FIXME: Determine if we can do an implicit conversion * throw new ExecutionEngineException(@"Invalid operand types."); * } */ } }
/// <summary> /// Validates the instruction operands and creates a matching variable for the result. /// </summary> /// <param name="ctx">The context.</param> /// <param name="compiler">The compiler.</param> public override void Validate(Context ctx, IMethodCompiler compiler) { base.Validate(ctx, compiler); StackTypeCode result = StackTypeCode.Unknown; switch (_opcode) { case OpCode.Add_ovf_un: result = _addovfunTable[(int)ctx.Operand1.StackType][(int)ctx.Operand2.StackType]; break; case OpCode.Sub_ovf_un: result = _subovfunTable[(int)ctx.Operand1.StackType][(int)ctx.Operand2.StackType]; break; default: result = _operandTable[(int)ctx.Operand1.StackType][(int)ctx.Operand2.StackType]; break; } if (StackTypeCode.Unknown == result) { throw new InvalidOperationException("Invalid operand types passed to " + _opcode); } ctx.Result = compiler.CreateTemporary(Operand.SigTypeFromStackType(result)); }
/// <summary> /// Validates the instruction operands and creates a matching variable for the result. /// </summary> /// <param name="ctx">The context.</param> /// <param name="compiler">The compiler.</param> public override void Validate(Context ctx, IMethodCompiler compiler) { base.Validate(ctx, compiler); StackTypeCode result = StackTypeCode.Unknown; switch (opcode) { case OpCode.Add_ovf_un: result = _addovfunTable[(int)ctx.Operand1.StackType][(int)ctx.Operand2.StackType]; break; case OpCode.Sub_ovf_un: result = _subovfunTable[(int)ctx.Operand1.StackType][(int)ctx.Operand2.StackType]; break; default: result = _operandTable[(int)ctx.Operand1.StackType][(int)ctx.Operand2.StackType]; break; } if (StackTypeCode.Unknown == result) throw new InvalidOperationException(@"Invalid operand types passed to " + opcode); ctx.Result = compiler.CreateVirtualRegister(Operand.SigTypeFromStackType(result)); }
/// <summary> /// Validates the instruction operands and creates a matching variable for the result. /// </summary> /// <param name="ctx"></param> /// <param name="compiler">The compiler.</param> public override void Validate(Context ctx, IMethodCompiler compiler) { base.Validate(ctx, compiler); // Validate the typecode & determine the resulting stack type SigType resultType; switch (_opcode) { case OpCode.Conv_u: goto case OpCode.Conv_i; case OpCode.Conv_i: resultType = compiler.Architecture.NativeType; break; case OpCode.Conv_i1: resultType = new SigType(CilElementType.I1); break; case OpCode.Conv_i2: resultType = new SigType(CilElementType.I2); break; case OpCode.Conv_i4: resultType = new SigType(CilElementType.I4); break; case OpCode.Conv_i8: resultType = new SigType(CilElementType.I8); break; case OpCode.Conv_r4: resultType = new SigType(CilElementType.R4); break; case OpCode.Conv_r8: resultType = new SigType(CilElementType.R8); break; case OpCode.Conv_u1: resultType = new SigType(CilElementType.U1); break; case OpCode.Conv_u2: resultType = new SigType(CilElementType.U2); break; case OpCode.Conv_u4: resultType = new SigType(CilElementType.U4); break; case OpCode.Conv_u8: resultType = new SigType(CilElementType.U8); break; default: throw new NotSupportedException(@"Overflow checking conversions not supported."); } ctx.Result = compiler.CreateTemporary(resultType); }
/// <summary> /// Validates the instruction operands and creates a matching variable for the result. /// </summary> /// <param name="ctx">The context.</param> /// <param name="compiler">The compiler.</param> public override void Validate(Context ctx, IMethodCompiler compiler) { base.Validate(ctx, compiler); Mosa.Runtime.Metadata.Signatures.ArraySigType a = ctx.Operand1.Type as Mosa.Runtime.Metadata.Signatures.ArraySigType; if (null == a || 1 != a.Rank) throw new InvalidProgramException(@"Operand to ldlen is not a vector."); ctx.Result = compiler.CreateTemporary(new SigType(CilElementType.I)); }
/// <summary> /// Validates the instruction operands and creates a matching variable for the result. /// </summary> /// <param name="ctx">The context.</param> /// <param name="compiler">The compiler.</param> public override void Validate(Context ctx, IMethodCompiler compiler) { base.Validate(ctx, compiler); StackTypeCode result = StackTypeCode.Unknown; switch (_opcode) { case OpCode.Add: result = _addTable[(int)ctx.Operand1.StackType][(int)ctx.Operand2.StackType]; break; case OpCode.Sub: result = _subTable[(int)ctx.Operand1.StackType][(int)ctx.Operand2.StackType]; break; default: result = _operandTable[(int)ctx.Operand1.StackType][(int)ctx.Operand2.StackType]; break; } if (StackTypeCode.Unknown == result) { throw new InvalidOperationException("Invalid operand types passed to " + _opcode); } SigType resultType; if (result != StackTypeCode.Ptr) { resultType = Operand.SigTypeFromStackType(result); } else { // Copy the pointer element type PtrSigType op0 = ctx.Operand1.Type as PtrSigType; PtrSigType op1 = ctx.Operand2.Type as PtrSigType; if (op0 != null) { resultType = new PtrSigType(op0.CustomMods, op0.ElementType); } else if (op1 != null) { resultType = new PtrSigType(op1.CustomMods, op1.ElementType); } else { throw new InvalidOperationException(); } } ctx.Result = compiler.CreateTemporary(resultType); }
/// <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; }
public static void Run(IMethodCompiler methodCompiler, IPipelineStage stage) { Run( methodCompiler.InternalTrace, stage, methodCompiler.Method, methodCompiler.InstructionSet, methodCompiler.BasicBlocks ); }
/// <summary> /// Validates the instruction operands and creates a matching variable for the result. /// </summary> /// <param name="ctx">The context.</param> /// <param name="compiler">The compiler.</param> public override void Validate(Context ctx, IMethodCompiler compiler) { base.Validate(ctx, compiler); SZArraySigType arrayType = ctx.Operand1.Type as SZArraySigType; if (arrayType == null) throw new InvalidProgramException(@"Operand to ldlen is not a vector."); ctx.Result = compiler.CreateTemporary(BuiltInSigType.IntPtr); }
/// <summary> /// Validates the instruction operands and creates a matching variable for the result. /// </summary> /// <param name="ctx">The context.</param> /// <param name="compiler">The compiler.</param> public override void Validate(Context ctx, IMethodCompiler compiler) { base.Validate(ctx, compiler); StackTypeCode result = _opTable[(int)ctx.Operand1.StackType][(int)ctx.Operand2.StackType]; if (result == StackTypeCode.Unknown) throw new InvalidOperationException(@"Invalid stack result of instruction."); ctx.Result = compiler.CreateTemporary(Operand.SigTypeFromStackType(result)); }
/// <summary> /// Setup stage specific processing on the compiler context. /// </summary> /// <param name="methodCompiler">The compiler context to perform processing in.</param> void IMethodCompilerStage.Setup(IMethodCompiler methodCompiler) { base.Setup(methodCompiler); IStackLayoutProvider stackLayoutProvider = methodCompiler.Pipeline.FindFirst<IStackLayoutProvider>(); stackSize = (stackLayoutProvider == null) ? 0 : stackLayoutProvider.LocalsSize; Debug.Assert((stackSize % 4) == 0, @"Stack size of method can't be divided by 4!!"); }
/// <summary> /// Validates the instruction operands and creates a matching variable for the result. /// </summary> /// <param name="ctx"></param> /// <param name="compiler">The compiler.</param> public override void Validate(Context ctx, IMethodCompiler compiler) { base.Validate(ctx, compiler); // Validate the operand StackTypeCode result = _opTable[(int)ctx.Operand1.StackType]; if (StackTypeCode.Unknown == result) throw new InvalidOperationException(@"Invalid operand to Not instruction."); ctx.Result = compiler.CreateTemporary(ctx.Operand1.Type); }
/// <summary> /// Validates the instruction operands and creates a matching variable for the result. /// </summary> /// <param name="ctx">The context.</param> /// <param name="compiler">The compiler.</param> public override void Validate(Context ctx, IMethodCompiler compiler) { base.Validate(ctx, compiler); Mosa.Runtime.Metadata.Signatures.ArraySigType a = ctx.Operand1.Type as Mosa.Runtime.Metadata.Signatures.ArraySigType; if (null == a || 1 != a.Rank) { throw new InvalidProgramException(@"Operand to ldlen is not a vector."); } ctx.Result = compiler.CreateTemporary(new SigType(CilElementType.I)); }
/// <summary> /// Validates the instruction operands and creates a matching variable for the result. /// </summary> /// <param name="ctx">The context.</param> /// <param name="compiler">The compiler.</param> public override void Validate(Context ctx, IMethodCompiler compiler) { base.Validate(ctx, compiler); StackTypeCode result = _operandTable[(int)ctx.Operand1.StackType][(int)ctx.Operand2.StackType]; Debug.Assert(StackTypeCode.Unknown != result, @"Can't shift with the given stack operands."); if (StackTypeCode.Unknown == result) throw new InvalidOperationException(@"Invalid stack state for pairing (" + ctx.Operand1.StackType + ", " + ctx.Operand2.StackType + ")"); ctx.Result = compiler.CreateTemporary(Operand.SigTypeFromStackType(result)); }
/// <summary> /// Validates the instruction operands and creates a matching variable for the result. /// </summary> /// <param name="ctx"></param> /// <param name="compiler">The compiler.</param> public override void Validate(Context ctx, IMethodCompiler compiler) { base.Validate(ctx, compiler); // Validate the operand StackTypeCode result = _typeCodes[(int)ctx.Operand1.StackType]; if (StackTypeCode.Unknown == result) throw new InvalidOperationException(@"Invalid operand to Neg instruction [" + result + "]"); ctx.Result = compiler.CreateVirtualRegister(ctx.Operand1.Type); }
/// <summary> /// Validates the instruction operands and creates a matching variable for the result. /// </summary> /// <param name="ctx">The context.</param> /// <param name="compiler">The compiler.</param> public override void Validate(Context ctx, IMethodCompiler compiler) { base.Validate(ctx, compiler); SigType destType = ctx.Operand1.Type; Debug.Assert(destType is PtrSigType || destType is RefSigType, @"Destination operand not a pointer or reference."); if (!(destType is PtrSigType || destType is RefSigType)) { throw new ExecutionEngineException(@"Invalid operand."); } }
/// <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; }
/// <summary> /// Validates the instruction operands and creates a matching variable for the result. /// </summary> /// <param name="ctx">The context.</param> /// <param name="compiler">The compiler.</param> public override void Validate(Context ctx, IMethodCompiler compiler) { base.Validate(ctx, compiler); StackTypeCode result = _opTable[(int)ctx.Operand1.StackType][(int)ctx.Operand2.StackType]; if (result == StackTypeCode.Unknown) { throw new ExecutionEngineException("Invalid stack result of instruction."); } ctx.Result = compiler.CreateTemporary(Operand.SigTypeFromStackType(result)); }
/// <summary> /// Validates the instruction operands and creates a matching variable for the result. /// </summary> /// <param name="ctx">The context.</param> /// <param name="compiler">The compiler.</param> public override void Validate(Context ctx, IMethodCompiler compiler) { base.Validate(ctx, compiler); StackTypeCode result = _operandTable[(int)ctx.Operand1.StackType][(int)ctx.Operand2.StackType]; Debug.Assert(StackTypeCode.Unknown != result, @"Can't shift with the given stack operands."); if (StackTypeCode.Unknown == result) { throw new ExecutionEngineException(@"Invalid stack state."); } ctx.Result = compiler.CreateTemporary(Operand.SigTypeFromStackType(result)); }
/// <summary> /// Validates the instruction operands and creates a matching variable for the result. /// </summary> /// <param name="ctx"></param> /// <param name="compiler">The compiler.</param> public override void Validate(Context ctx, IMethodCompiler compiler) { base.Validate(ctx, compiler); // Validate the operand StackTypeCode result = _typeCodes[(int)ctx.Operand1.StackType]; if (StackTypeCode.Unknown == result) { throw new InvalidOperationException(@"Invalid operand to Neg instruction."); } ctx.Result = compiler.CreateTemporary(ctx.Operand1.Type); }
private static int ComputeTypeSize(TokenTypes token, IMethodCompiler compiler) { IMetadataProvider metadata = compiler.Assembly.Metadata; Metadata.Tables.TypeDefRow typeDefinition; Metadata.Tables.TypeDefRow followingTypeDefinition; metadata.Read(token, out typeDefinition); metadata.Read(token + 1, out followingTypeDefinition); int result = 0; TokenTypes fieldList = typeDefinition.FieldList; while (fieldList != followingTypeDefinition.FieldList) result += FieldSize(fieldList++, compiler); return result; }
/// <summary> /// Lays out all parameters of the method. /// </summary> /// <param name="compiler">The method compiler providing the parameters.</param> /// <param name="cc">The calling convention used to invoke the method, which controls parameter layout.</param> private void LayoutParameters(IMethodCompiler compiler, ICallingConvention cc) { List <StackOperand> paramOps = new List <StackOperand> (); for (int i = 0; i < compiler.Method.Parameters.Count; i++) { paramOps.Add((StackOperand)compiler.GetParameterOperand(i)); } LayoutVariables(paramOps, cc, cc.OffsetOfFirstParameter, -1); if (TRACING.TraceInfo) { LogOperands(paramOps); } }
/// <summary> /// Validates the instruction operands and creates a matching variable for the result. /// </summary> /// <param name="ctx">The context.</param> /// <param name="compiler">The compiler.</param> public override void Validate(Context ctx, IMethodCompiler compiler) { base.Validate(ctx, compiler); // Make sure the base is a typed reference throw new NotImplementedException(); /* if (!Object.ReferenceEquals(_operands[0].Type, MetadataTypeReference.FromName(compiler.Assembly.Metadata, @"System", @"TypedReference"))) { Debug.Assert(false); throw new InvalidProgramException(@"Invalid stack object."); } // Push the loaded value _results[0] = CreateResultOperand(_typeRef); */ }
private static int FieldSize(TokenTypes field, IMethodCompiler compiler) { Metadata.Tables.FieldRow fieldRow; compiler.Assembly.Metadata.Read(field, out fieldRow); FieldSignature signature = Signature.FromMemberRefSignatureToken(compiler.Assembly.Metadata, 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(compiler.Assembly.Metadata, fieldRow.SignatureBlobIdx); return ComputeTypeSize(valueTypeSig, compiler); } int size, alignment; compiler.Architecture.GetTypeRequirements(signature.Type, out size, out alignment); return size; }
/// <summary> /// Validates the instruction operands and creates a matching variable for the result. /// </summary> /// <param name="ctx">The context.</param> /// <param name="compiler">The compiler.</param> public override void Validate(Context ctx, IMethodCompiler compiler) { base.Validate(ctx, compiler); // Make sure the base is a typed reference throw new NotImplementedException(); /* * if (!Object.ReferenceEquals(_operands[0].Type, MetadataTypeReference.FromName(compiler.Assembly.Metadata, @"System", @"TypedReference"))) * { * Debug.Assert(false); * throw new InvalidProgramException(@"Invalid stack object."); * } * * // Push the loaded value * _results[0] = CreateResultOperand(_typeRef); */ }
private static int FieldSize(TokenTypes field, IMethodCompiler compiler) { Metadata.Tables.FieldRow fieldRow; compiler.Assembly.Metadata.Read(field, out fieldRow); FieldSignature signature = Signature.FromMemberRefSignatureToken(compiler.Assembly.Metadata, 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(compiler.Assembly.Metadata, fieldRow.SignatureBlobIdx); return(ComputeTypeSize(valueTypeSig, compiler)); } int size, alignment; compiler.Architecture.GetTypeRequirements(signature.Type, out size, out alignment); return(size); }
/// <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> /// Validates the instruction operands and creates a matching variable for the result. /// </summary> /// <param name="ctx">The context.</param> /// <param name="compiler">The compiler.</param> public override void Validate(Context ctx, IMethodCompiler compiler) { base.Validate(ctx, compiler); // If we're ldind.i8, fix an IL deficiency that the result may be U8 if (opcode == OpCode.Ldind_i8 && this.typeRef.Type == CilElementType.I8) { SigType opType = ctx.Operand1.Type; RefSigType rst = opType as RefSigType; PtrSigType ptr = opType as PtrSigType; if (rst != null && rst.ElementType.Type == CilElementType.U8 || ptr != null && ptr.ElementType.Type == CilElementType.U8) { ctx.Result = compiler.CreateTemporary(BuiltInSigType.UInt64); } } }
private static int ComputeTypeSize(TokenTypes token, IMethodCompiler compiler) { IMetadataProvider metadata = compiler.Assembly.Metadata; Metadata.Tables.TypeDefRow typeDefinition; Metadata.Tables.TypeDefRow followingTypeDefinition; metadata.Read(token, out typeDefinition); metadata.Read(token + 1, out followingTypeDefinition); int result = 0; TokenTypes fieldList = typeDefinition.FieldList; while (fieldList != followingTypeDefinition.FieldList) { result += FieldSize(fieldList++, compiler); } return(result); }
/// <summary> /// Performs stage specific processing on the compiler context. /// </summary> public void Run() { // The size of the code in bytes MethodHeader header = new MethodHeader(); using (Stream code = MethodCompiler.GetInstructionStream()) { // Initalize the instruction, setting the initalize size to 10 times the code stream MethodCompiler.InstructionSet = new InstructionSet((int)code.Length * 10); // update the base class InstructionSet = MethodCompiler.InstructionSet; using (BinaryReader reader = new BinaryReader(code)) { _compiler = MethodCompiler; _method = MethodCompiler.Method; _codeReader = reader; ReadMethodHeader(reader, ref header); //Debug.WriteLine("Decoding " + compiler.Method.ToString()); if (0 != header.localsSignature) { StandAloneSigRow row; IMetadataProvider md = _method.Module.Metadata; md.Read(header.localsSignature, out row); MethodCompiler.SetLocalVariableSignature(LocalVariableSignature.Parse(md, row.SignatureBlobIdx)); } /* Decode the instructions */ Decode(MethodCompiler, ref header); // When we leave, the operand stack must only contain the locals... //Debug.Assert(_operandStack.Count == _method.Locals.Count); _codeReader = null; _compiler = null; } } }
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; //} } }
/// <summary> /// Initializes a new instance of <see cref="MachineCodeEmitter"/>. /// </summary> /// <param name="compiler">The compiler.</param> /// <param name="codeStream">The stream the machine code is written to.</param> /// <param name="linker">The linker used to resolve external addresses.</param> void ICodeEmitter.Initialize(IMethodCompiler compiler, Stream codeStream, IAssemblyLinker linker) { Debug.Assert(null != compiler, @"MachineCodeEmitter needs a method compiler."); if (compiler == null) { throw new ArgumentNullException(@"compiler"); } Debug.Assert(null != codeStream, @"MachineCodeEmitter needs a code stream."); if (codeStream == null) { throw new ArgumentNullException(@"codeStream"); } Debug.Assert(null != linker, @"MachineCodeEmitter needs a linker."); if (linker == null) { throw new ArgumentNullException(@"linker"); } _compiler = compiler; _codeStream = codeStream; _codeStreamBasePosition = codeStream.Position; _linker = linker; }
/// <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> /// Validates the instruction operands and creates a matching variable for the result. /// </summary> /// <param name="ctx">The context.</param> /// <param name="compiler">The compiler.</param> public override void Validate(Context ctx, IMethodCompiler compiler) { if (compiler == null) { throw new ArgumentNullException(@"compiler"); } // Validate the operands... int offset = (ctx.InvokeTarget.Signature.HasExplicitThis ? 1 : 0); Debug.Assert(ctx.OperandCount == ctx.InvokeTarget.Parameters.Count - offset, @"Operand count doesn't match parameter count."); for (int i = 0; i < ctx.OperandCount; i++) { /* FIXME: Check implicit conversions * if (ops[i] != null) { * Debug.Assert(_operands[i].Type == _parameterTypes[i]); * if (_operands[i].Type != _parameterTypes[i]) * { * // FIXME: Determine if we can do an implicit conversion * throw new ExecutionEngineException(@"Invalid operand types."); * } */ } }
/// <summary> /// Processes the instructions. /// </summary> /// <param name="block">The block.</param> /// <param name="currentStack">The current stack.</param> /// <param name="compiler">The compiler.</param> private void ProcessInstructions(BasicBlock block, IList <Operand> currentStack, IMethodCompiler compiler) { for (Context ctx = new Context(InstructionSet, block); !ctx.EndOfInstruction; ctx.GotoNext()) { if (!(ctx.Instruction is CIL.ICILInstruction)) { continue; } AssignOperandsFromCILStack(ctx, currentStack); (ctx.Instruction as ICILInstruction).Validate(ctx, compiler); PushResultOperands(ctx, currentStack); } }
/// <summary> /// Validates the instruction operands and creates a matching variable for the result. /// </summary> /// <param name="ctx">The context.</param> /// <param name="compiler">The compiler.</param> public override void Validate(Context ctx, IMethodCompiler compiler) { if (compiler == null) throw new ArgumentNullException(@"compiler"); // Validate the operands... int offset = (ctx.InvokeTarget.Signature.HasExplicitThis ? 1 : 0); Debug.Assert(ctx.OperandCount == ctx.InvokeTarget.Parameters.Count - offset, @"Operand count doesn't match parameter count."); for (int i = 0; i < ctx.OperandCount; i++) { /* FIXME: Check implicit conversions if (ops[i] != null) { Debug.Assert(_operands[i].Type == _parameterTypes[i]); if (_operands[i].Type != _parameterTypes[i]) { // FIXME: Determine if we can do an implicit conversion throw new ExecutionEngineException(@"Invalid operand types."); } */ } }
/// <summary> /// Validates the specified instruction. /// </summary> /// <param name="ctx">The context.</param> /// <param name="compiler">The compiler.</param> public virtual void Validate(Context ctx, IMethodCompiler compiler) { /* Default implementation is to do nothing */ }
/// <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> /// Validates the instruction operands and creates a matching variable for the result. /// </summary> /// <param name="ctx">The context.</param> /// <param name="compiler">The compiler.</param> public override void Validate(Context ctx, IMethodCompiler compiler) { base.Validate(ctx, compiler); SigType destType = ctx.Operand1.Type; Debug.Assert(destType is PtrSigType || destType is RefSigType, @"Destination operand not a pointer or reference."); if (!(destType is PtrSigType || destType is RefSigType)) throw new ExecutionEngineException(@"Invalid operand."); }
/// <summary> /// Setup stage specific processing on the compiler context. /// </summary> /// <param name="compiler">The compiler context to perform processing in.</param> void IMethodCompilerStage.Setup(IMethodCompiler compiler) { }
protected CompilerBase(IArchitecture arch, IMethodCompiler methodCompiler, IEnumerable <IAssemblyCompilerStage> stages) { this.Architecture = arch; this.MethodCompiler = methodCompiler; this.Stages = new List <IAssemblyCompilerStage>(stages); }
/// <summary> /// Lays out all parameters of the method. /// </summary> /// <param name="compiler">The method compiler providing the parameters.</param> private void LayoutParameters(IMethodCompiler compiler) { List<StackOperand> paramOps = new List<StackOperand>(); int offset = 0; if (compiler.Method.Signature.HasThis || compiler.Method.Signature.HasExplicitThis) ++offset; for (int i = 0; i < compiler.Method.Parameters.Count + offset; ++i) paramOps.Add((StackOperand)compiler.GetParameterOperand(i)); LayoutVariables(paramOps, callingConvention, callingConvention.OffsetOfFirstParameter, -1); }
/// <summary> /// Lays out all parameters of the method. /// </summary> /// <param name="compiler">The method compiler providing the parameters.</param> /// <param name="cc">The calling convention used to invoke the method, which controls parameter layout.</param> private void LayoutParameters(IMethodCompiler compiler, ICallingConvention cc) { List<StackOperand> paramOps = new List<StackOperand>(); int offset = 0; if (compiler.Method.Signature.HasThis || compiler.Method.Signature.HasExplicitThis) ++offset; for (int i = 0; i < compiler.Method.Parameters.Count + offset; ++i) paramOps.Add((StackOperand)compiler.GetParameterOperand(i)); /*if (compiler.Method.Signature.HasThis || compiler.Method.Signature.HasExplicitThis) LayoutVariables(paramOps, cc, cc.OffsetOfFirstParameter + 4, -1); else*/ LayoutVariables(paramOps, cc, cc.OffsetOfFirstParameter, -1); if (TRACING.TraceInfo) LogOperands(paramOps); }
/// <summary> /// Validates the instruction operands and creates a matching variable for the result. /// </summary> /// <param name="ctx">The context.</param> /// <param name="compiler">The compiler.</param> public override void Validate(Context ctx, IMethodCompiler compiler) { // Validate the operands... int offset = (ctx.InvokeTarget.Signature.HasExplicitThis ? 1 : 0); Debug.Assert(ctx.OperandCount == ctx.InvokeTarget.Parameters.Count - offset, @"Operand count doesn't match parameter count."); }
/// <summary> /// Setup stage specific processing on the compiler context. /// </summary> /// <param name="methodCompiler">The compiler context to perform processing in.</param> void IMethodCompilerStage.Setup(IMethodCompiler methodCompiler) { base.Setup(methodCompiler); plugSystem = methodCompiler.AssemblyCompiler.Pipeline.FindFirst<IPlugSystem>(); }
/// <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> /// Decodes the instruction stream of the reader and populates the compiler. /// </summary> /// <param name="compiler">The compiler to populate.</param> /// <param name="header">The method header.</param> private void Decode(IMethodCompiler compiler, MethodHeader header) { // Start of the code stream long codeStart = codeReader.BaseStream.Position; // End of the code stream long codeEnd = codeReader.BaseStream.Position + header.CodeSize; // Prefix instruction bool prefix = false; // Setup context Context ctx = new Context(instructionSet); while (codeEnd != codeReader.BaseStream.Position) { // Determine the instruction offset int instOffset = (int)(codeReader.BaseStream.Position - codeStart); // Read the next opcode from the stream OpCode op = (OpCode)codeReader.ReadByte(); if (OpCode.Extop == op) op = (OpCode)(0x100 | codeReader.ReadByte()); ICILInstruction instruction = CILInstruction.Get(op); if (instruction == null) throw new Exception("CIL " + op + " is not yet supported"); // Create and initialize the corresponding instruction ctx.AppendInstruction(instruction); ctx.Label = instOffset; instruction.Decode(ctx, this); ctx.HasPrefix = prefix; Debug.Assert(ctx.Instruction != null); // Do we need to patch branch targets? if (instruction is IBranchInstruction && instruction.FlowControl != FlowControl.Return) { int pc = (int)(codeReader.BaseStream.Position - codeStart); for (int i = 0; i < ctx.BranchTargets.Length; i++) ctx.BranchTargets[i] += pc; } prefix = (instruction is PrefixInstruction); } }
/// <summary> /// Validates the instruction operands and creates a matching variable for the result. /// </summary> /// <param name="ctx">The context.</param> /// <param name="compiler">The compiler.</param> public override void Validate(Context ctx, IMethodCompiler compiler) { base.Validate(ctx, compiler); int paramCount = ctx.InvokeTarget.Signature.Parameters.Length; if (ctx.InvokeTarget.Signature.HasThis && !ctx.InvokeTarget.Signature.HasExplicitThis) paramCount++; // Validate the operands... Debug.Assert(ctx.OperandCount == paramCount, @"Operand count doesn't match parameter count."); //for (int i = 0; i < ctx.OperandCount; i++) //{ /* FIXME: Check implicit conversions // if (ops[i] != null) { Debug.Assert(_operands[i].Type == _parameterTypes[i]); if (_operands[i].Type != _parameterTypes[i]) { // FIXME: Determine if we can do an implicit conversion throw new ExecutionEngineException(@"Invalid operand types."); } */ //} }
/// <summary> /// Validates the instruction operands and creates a matching variable for the result. /// </summary> /// <param name="ctx">The context.</param> /// <param name="compiler">The compiler.</param> public override void Validate(Context ctx, IMethodCompiler compiler) { base.Validate(ctx, compiler); // If we're ldind.i8, fix an IL deficiency that the result may be U8 if (_opcode == OpCode.Ldind_i8 && this.typeRef.Type == CilElementType.I8) { SigType opType = ctx.Operand1.Type; RefSigType rst = opType as RefSigType; PtrSigType ptr = opType as PtrSigType; if (rst != null && rst.ElementType.Type == CilElementType.U8 || ptr != null && ptr.ElementType.Type == CilElementType.U8) { ctx.Result = compiler.CreateTemporary(BuiltInSigType.UInt64); } } }
/// <summary> /// Initializes a new instance of <see cref="BaseCodeEmitter"/>. /// </summary> /// <param name="compiler">The compiler.</param> /// <param name="codeStream">The stream the machine code is written to.</param> /// <param name="linker">The linker used to resolve external addresses.</param> void ICodeEmitter.Initialize(IMethodCompiler compiler, Stream codeStream, IAssemblyLinker linker) { Debug.Assert(null != compiler, @"MachineCodeEmitter needs a method compiler."); if (compiler == null) throw new ArgumentNullException(@"compiler"); Debug.Assert(null != codeStream, @"MachineCodeEmitter needs a code stream."); if (codeStream == null) throw new ArgumentNullException(@"codeStream"); Debug.Assert(null != linker, @"MachineCodeEmitter needs a linker."); if (linker == null) throw new ArgumentNullException(@"linker"); this.compiler = compiler; this.codeStream = codeStream; this.codeStreamBasePosition = codeStream.Position; this.linker = linker; }
/// <summary> /// Processes the instructions. /// </summary> /// <param name="block">The block.</param> /// <param name="currentStack">The current stack.</param> /// <param name="compiler">The compiler.</param> private void ProcessInstructions(BasicBlock block, IList<Operand> currentStack, IMethodCompiler compiler) { for (Context ctx = new Context (InstructionSet, block); !ctx.EndOfInstruction; ctx.GotoNext ()) { if (!(ctx.Instruction is CIL.ICILInstruction)) continue; AssignOperandsFromCILStack (ctx, currentStack); (ctx.Instruction as ICILInstruction).Validate (ctx, compiler); PushResultOperands (ctx, currentStack); } }