protected void CompileMethod(string source, INamingConventionResolver namingConvention = null, IRuntimeLibrary runtimeLibrary = null, IErrorReporter errorReporter = null, string methodName = "M", bool addSkeleton = true, bool referenceSystemCore = false) { Compile(new[] { addSkeleton ? "using System; class C { " + source + "}" : source }, namingConvention, runtimeLibrary, errorReporter, (m, res, mc) => { if (m.Name == methodName) { Method = m; MethodCompiler = mc; CompiledMethod = res; } }, referenceSystemCore: referenceSystemCore); Assert.That(Method, Is.Not.Null, "Method " + methodName + " was not compiled"); }
protected void CompileMethod(string source, IMetadataImporter metadataImporter = null, INamer namer = null, IRuntimeLibrary runtimeLibrary = null, IErrorReporter errorReporter = null, string methodName = "M", bool addSkeleton = true, bool referenceSystemCore = false, bool allowUserDefinedStructs = false) { Compile(new[] { addSkeleton ? "using System; class C { " + source + "}" : source }, metadataImporter: metadataImporter, namer: namer, runtimeLibrary: runtimeLibrary, errorReporter: errorReporter, methodCompiled: (m, res, mc) => { if (m.Name == methodName) { Method = m; MethodCompiler = mc; CompiledMethod = res; } }, referenceSystemCore: referenceSystemCore, allowUserDefinedStructs: allowUserDefinedStructs); Assert.That(Method, Is.Not.Null, "Method " + methodName + " was not compiled"); }
public static void OrderLoadOperands(InstructionNode node, MethodCompiler methodCompiler) { if (node.Operand1.IsResolvedConstant && node.Operand2.IsResolvedConstant) { node.Operand1 = methodCompiler.CreateConstant(node.Operand1.ConstantUnsignedLongInteger + node.Operand2.ConstantUnsignedLongInteger); node.Operand2 = methodCompiler.ConstantZero; } if (node.Operand1.IsConstant && !node.Operand2.IsConstant) { var operand1 = node.Operand1; var operand2 = node.Operand2; node.Operand2 = operand1; node.Operand1 = operand2; } }
public static void OrderStoreOperands(Context context, MethodCompiler methodCompiler) { if (context.Operand1.IsResolvedConstant && context.Operand2.IsResolvedConstant) { context.Operand1 = methodCompiler.CreateConstant(context.Operand1.ConstantUnsignedLongInteger + context.Operand2.ConstantUnsignedLongInteger); context.Operand2 = methodCompiler.ConstantZero; } if (context.Operand1.IsConstant && !context.Operand2.IsConstant) { var operand1 = context.Operand1; var operand2 = context.Operand2; context.Operand2 = operand1; context.Operand1 = operand2; } }
/// <summary> /// Replaces the intrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="methodCompiler">The method compiler.</param> /// <exception cref="CompilerException"></exception> void IIntrinsicInternalMethod.ReplaceIntrinsicCall(Context context, MethodCompiler methodCompiler) { if (context.OperandCount == 2) { context.SetInstruction(IRInstruction.StoreInt64, null, context.Operand1, methodCompiler.ConstantZero, context.Operand2); } else if (context.OperandCount == 3) { context.SetInstruction(IRInstruction.StoreInt64, null, context.Operand1, context.Operand2, context.Operand3); } else { throw new CompilerException(); } LoadStore.OrderStoreOperands(context.Node, methodCompiler); }
private static void Load64(Context context, MethodCompiler methodCompiler) { if (context.OperandCount == 1) { context.SetInstruction(IRInstruction.LoadInt64, context.Result, context.Operand1, methodCompiler.ConstantZero); } else if (context.OperandCount == 2) { context.SetInstruction(IRInstruction.LoadInt64, context.Result, context.Operand1, context.Operand2); } else { throw new CompilerException(); } LoadStore.OrderLoadOperands(context.Node, methodCompiler); }
private static void Store32(Context context, MethodCompiler methodCompiler) { if (context.OperandCount == 2) { context.SetInstruction(IRInstruction.StoreInt32, null, context.Operand1, methodCompiler.ConstantZero, context.Operand2); } else if (context.OperandCount == 3) { context.SetInstruction(IRInstruction.StoreInt32, null, context.Operand1, context.Operand2, context.Operand3); } else { throw new CompilerException(); } LoadStore.OrderStoreOperands(context.Node, methodCompiler); }
void IIRVisitor.CompoundStore(Context context) { var type = context.Operand3.Type; int typeSize = TypeLayout.GetTypeSize(type); int alignedTypeSize = typeSize - (typeSize % NativeAlignment); Debug.Assert(typeSize > 0, MethodCompiler.Method.FullName); int offset = 0; if (context.Operand2.IsConstant) { offset = (int)context.Operand2.ConstantSignedLongInteger; } var offsetop = context.Operand2; var src = context.Operand3; var dest = context.Operand1; Debug.Assert(src.IsMemoryAddress); var srcReg = MethodCompiler.CreateVirtualRegister(dest.Type.TypeSystem.BuiltIn.I4); var dstReg = MethodCompiler.CreateVirtualRegister(dest.Type.TypeSystem.BuiltIn.I4); var tmp = MethodCompiler.CreateVirtualRegister(dest.Type.TypeSystem.BuiltIn.I4); context.SetInstruction(X86.Nop); context.AppendInstruction(X86.Lea, srcReg, src); context.AppendInstruction(X86.Mov, dstReg, dest); if (!offsetop.IsConstant) { context.AppendInstruction(X86.Add, dstReg, dstReg, offsetop); } for (int i = 0; i < alignedTypeSize; i += NativeAlignment) { context.AppendInstruction(X86.Mov, InstructionSize.Size32, tmp, Operand.CreateMemoryAddress(TypeSystem.BuiltIn.I4, srcReg, i)); context.AppendInstruction(X86.Mov, InstructionSize.Size32, Operand.CreateMemoryAddress(TypeSystem.BuiltIn.I4, dstReg, i + offset), tmp); } for (int i = alignedTypeSize; i < typeSize; i++) { context.AppendInstruction(X86.Mov, InstructionSize.Size8, tmp, Operand.CreateMemoryAddress(TypeSystem.BuiltIn.I4, srcReg, i)); context.AppendInstruction(X86.Mov, InstructionSize.Size8, Operand.CreateMemoryAddress(TypeSystem.BuiltIn.I4, dstReg, i + offset), tmp); } }
private void LoadParam64(Context context) { Debug.Assert(!context.Result.IsR4); Debug.Assert(!context.Result.IsR8); Debug.Assert(context.Result.Is64BitInteger); var result = context.Result; var operand1 = context.Operand1; var resultLow = AllocateVirtualRegister(TypeSystem.BuiltIn.I4); var resultHigh = AllocateVirtualRegister(TypeSystem.BuiltIn.I4); MethodCompiler.SplitLongOperand(operand1, out Operand op1Low, out Operand op1High); context.SetInstruction(IRInstruction.LoadParam32, resultLow, op1Low); context.AppendInstruction(IRInstruction.LoadParam32, resultHigh, op1High); context.AppendInstruction(IRInstruction.To64, result, resultLow, resultHigh); }
private void LoadParamSignExtend8x64(Context context) { Debug.Assert(!context.Result.IsR4); Debug.Assert(!context.Result.IsR8); Debug.Assert(context.Result.Is64BitInteger); var result = context.Result; var operand1 = context.Operand1; MethodCompiler.SplitLongOperand(operand1, out Operand op0Low, out Operand _); var resultLow = AllocateVirtualRegister(TypeSystem.BuiltIn.I4); var resultHigh = AllocateVirtualRegister(TypeSystem.BuiltIn.I4); context.SetInstruction(IRInstruction.LoadParamSignExtend8x32, resultLow, op0Low); context.AppendInstruction(IRInstruction.ArithShiftRight32, resultHigh, resultLow, CreateConstant((byte)31)); context.AppendInstruction(IRInstruction.To64, result, resultLow, resultHigh); }
public static void Unsafe_SizeOf(Context context, MethodCompiler methodCompiler) { var type = methodCompiler.Method.GenericArguments[0]; var size = methodCompiler.TypeLayout.GetTypeSize(type); var opReturn = methodCompiler.AllocateVirtualRegisterOrStackSlot(methodCompiler.Method.Signature.ReturnType); // Move constant into return operand var move = methodCompiler.Is32BitPlatform ? (BaseInstruction)IRInstruction.Move32 : IRInstruction.Move64; context.AppendInstruction(move, opReturn, methodCompiler.CreateConstant(size)); // Set return var setReturn = BaseMethodCompilerStage.GetSetReturnInstruction(opReturn.Type, methodCompiler.Is32BitPlatform); context.AppendInstruction(setReturn, null, opReturn); context.AppendInstruction(IRInstruction.Jmp, methodCompiler.BasicBlocks.EpilogueBlock); }
private IntPtr CreateMethodStub(MethodCompiler methodCompiler) { if (methodCompiler == null) throw new ArgumentNullException("methodCompiler"); _unmanagedDelegates.Add(methodCompiler); IntPtr methodPtr = Marshal.GetFunctionPointerForDelegate(methodCompiler); Assembler assembler = new Assembler(); Label label = assembler.DefineLabel(); assembler.Call(label); assembler.MarkLabel(label); assembler.Sub(Mem.sysint_ptr(Register.nsp), 5); assembler.Call(methodPtr); assembler.Add(Register.nsp, IntPtr.Size); assembler.Jmp(Register.nax); return assembler.Make(); }
/// <summary> /// Validates the instruction operands and creates a matching variable for the result. /// </summary> /// <param name="context">The context.</param> /// <param name="compiler">The compiler.</param> public override void Resolve(Context context, MethodCompiler compiler) { base.Resolve(context, compiler); // Make sure the base is a typed reference throw new NotImplementCompilerException(); /* * 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 void LoadPointer(Context context, MethodCompiler methodCompiler) { var instruction = methodCompiler.Is32BitPlatform ? (BaseInstruction)IRInstruction.Load32 : IRInstruction.LoadZeroExtend32x64; if (context.OperandCount == 1) { context.SetInstruction(instruction, context.Result, context.Operand1, methodCompiler.ConstantZero); } else if (context.OperandCount == 2) { context.SetInstruction(instruction, context.Result, context.Operand1, context.Operand2); } else { throw new CompilerException(); } LoadStore.OrderOperands(context, methodCompiler); }
internal static BoundStatement ParseAndBindMethodBody(string program, bool lower, string typeName = DefaultTypeName, string methodName = DefaultMethodName) { var compilation = CreateCompilationWithMscorlib(program); var method = (MethodSymbol)compilation.GlobalNamespace.GetTypeMembers(typeName).Single().GetMembers(methodName).Single(); var diagnostics = DiagnosticBag.GetInstance(); try { // Provide an Emit.Module so that the lowering passes will be run var module = new PEAssemblyBuilder( (SourceAssemblySymbol)compilation.Assembly, null, OutputKind.ConsoleApplication, GetDefaultModulePropertiesForSerialization(), Enumerable.Empty <ResourceDescription>(), assemblySymbolMapper: null); TypeCompilationState compilationState = new TypeCompilationState(method.ContainingType, compilation, module); var block = MethodCompiler.BindMethodBody(method, compilationState, diagnostics); if ((block == null) || !lower) { return(block); } NamedTypeSymbol stateMachineTypeOpt; VariableSlotAllocator variableSlotAllocatorOpt; var body = MethodCompiler.LowerBodyOrInitializer( method: method, body: block, previousSubmissionFields: null, compilationState: compilationState, diagnostics: diagnostics, stateMachineTypeOpt: out stateMachineTypeOpt, variableSlotAllocatorOpt: out variableSlotAllocatorOpt); return(body); } finally { diagnostics.Free(); } }
/// <summary> /// Replaces the intrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="methodCompiler">The method compiler.</param> /// <exception cref="CompilerException"></exception> void IIntrinsicInternalMethod.ReplaceIntrinsicCall(Context context, MethodCompiler methodCompiler) { var instruction = methodCompiler.Architecture.Is32BitPlatform ? (BaseInstruction)IRInstruction.LoadZeroExtend16x32 : IRInstruction.LoadZeroExtend16x64; if (context.OperandCount == 1) { context.SetInstruction(instruction, context.Result, context.Operand1, methodCompiler.ConstantZero); } else if (context.OperandCount == 2) { context.SetInstruction(instruction, context.Result, context.Operand1, context.Operand2); } else { throw new CompilerException(); } LoadStore.OrderLoadOperands(context.Node, methodCompiler); }
private static void StorePointer(Context context, MethodCompiler methodCompiler) { var instruction = methodCompiler.Architecture.Is32BitPlatform ? (BaseInstruction)IRInstruction.Store32 : IRInstruction.Store64; if (context.OperandCount == 2) { context.SetInstruction(instruction, null, context.Operand1, methodCompiler.ConstantZero, context.Operand2); } else if (context.OperandCount == 3) { context.SetInstruction(instruction, null, context.Operand1, context.Operand2, context.Operand3); } else { throw new CompilerException(); } LoadStore.OrderOperands(context, methodCompiler); }
private static void FrameCallRetR8(Context context, MethodCompiler methodCompiler) { var result = context.Result; var methodAddress = context.Operand1; var eax = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I8, GeneralPurposeRegister.EAX); var edx = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I8, GeneralPurposeRegister.EDX); var xmm0 = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I8, SSE2Register.XMM0); methodCompiler.SplitLongOperand(result, out Operand op0L, out Operand op0H); context.SetInstruction(X64.Call, null, methodAddress); context.AppendInstruction(IRInstruction.Gen, xmm0); //context.AppendInstruction(X64.Movdi64ss, eax, xmm0); // FIXME: X64 context.AppendInstruction(X64.Pextrd64, edx, xmm0, methodCompiler.CreateConstant((byte)1)); context.AppendInstruction(X64.Mov64, op0L, eax); context.AppendInstruction(X64.Mov64, op0H, edx); }
private static void SetSegments(Context context, MethodCompiler methodCompiler) { var operand1 = context.Operand1; var operand2 = context.Operand2; var operand3 = context.Operand3; var operand4 = context.GetOperand(3); var operand5 = context.GetOperand(4); var ds = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I2, SegmentRegister.DS); var es = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I2, SegmentRegister.ES); var fs = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I2, SegmentRegister.FS); var gs = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I2, SegmentRegister.GS); var ss = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I2, SegmentRegister.SS); context.SetInstruction(X64.MovStoreSeg64, ds, operand1); context.AppendInstruction(X64.MovStoreSeg64, es, operand2); context.AppendInstruction(X64.MovStoreSeg64, fs, operand3); context.AppendInstruction(X64.MovStoreSeg64, gs, operand4); context.AppendInstruction(X64.MovStoreSeg64, ss, operand5); }
private Operand GetFinalVirtualRegister(Operand operand) { Operand final; if (!finalVirtualRegisters.TryGetValue(operand, out final)) { if (operand.SSAVersion == 0) { final = operand.SSAParent; } else { final = MethodCompiler.CreateVirtualRegister(operand.Type); } finalVirtualRegisters.Add(operand, final); } return(final); }
/// <summary> /// Validates the instruction operands and creates a matching variable for the result. /// </summary> /// <param name="context">The context.</param> /// <param name="compiler">The compiler.</param> /// <exception cref="ArgumentNullException">context</exception> /// <exception cref="InvalidOperationException">Invalid virtualLocal state for pairing (" + context.Operand1.Type.GetStackType() + ", " + context.Operand2.Type.GetStackType() + ")</exception> public override void Resolve(Context context, MethodCompiler compiler) { if (context == null) { throw new ArgumentNullException(nameof(context)); } base.Resolve(context, compiler); var result = operandTable[(int)context.Operand1.Type.GetStackTypeCode()][(int)context.Operand2.Type.GetStackTypeCode()]; Debug.Assert(StackTypeCode.Unknown != result, "Can't shift with the given virtualLocal operands."); if (StackTypeCode.Unknown == result) { throw new InvalidOperationException("Invalid virtualLocal state for pairing (" + context.Operand1.Type.GetStackType() + ", " + context.Operand2.Type.GetStackType() + ")"); } context.Result = compiler.CreateVirtualRegister(compiler.TypeSystem.GetStackTypeFromCode(result)); }
/// <summary> /// Create platform compound move. /// </summary> /// <param name="methodCompiler">The compiler.</param> /// <param name="context">The context.</param> /// <param name="destinationBase">The destination base.</param> /// <param name="destination">The destination.</param> /// <param name="sourceBase">The source base.</param> /// <param name="source">The source.</param> /// <param name="size">The size.</param> public override void InsertCompoundCopy(MethodCompiler methodCompiler, Context context, Operand destinationBase, Operand destination, Operand sourceBase, Operand source, int size) { const int LargeAlignment = 16; int alignedSize = size - (size % NativeAlignment); int largeAlignedTypeSize = size - (size % LargeAlignment); Debug.Assert(size > 0); var srcReg = methodCompiler.CreateVirtualRegister(destinationBase.Type.TypeSystem.BuiltIn.I4); var dstReg = methodCompiler.CreateVirtualRegister(destinationBase.Type.TypeSystem.BuiltIn.I4); context.AppendInstruction(IRInstruction.UnstableObjectTracking); context.AppendInstruction(X86.Lea32, srcReg, sourceBase, source); context.AppendInstruction(X86.Lea32, dstReg, destinationBase, destination); var tmp = methodCompiler.CreateVirtualRegister(destinationBase.Type.TypeSystem.BuiltIn.I4); var tmpLarge = methodCompiler.CreateVirtualRegister(destinationBase.Type.TypeSystem.BuiltIn.R8); for (int i = 0; i < largeAlignedTypeSize; i += LargeAlignment) { // Large aligned moves allow 128bits to be copied at a time var index = methodCompiler.CreateConstant((int)i); context.AppendInstruction(X86.MovupsLoad, tmpLarge, srcReg, index); context.AppendInstruction(X86.MovupsStore, null, dstReg, index, tmpLarge); } for (int i = largeAlignedTypeSize; i < alignedSize; i += 4) { var index = methodCompiler.CreateConstant(i); context.AppendInstruction(X86.MovLoad32, tmp, srcReg, index); context.AppendInstruction(X86.MovStore32, null, dstReg, index, tmp); } for (int i = alignedSize; i < size; i++) { var index = methodCompiler.CreateConstant(i); context.AppendInstruction(X86.MovLoad8, tmp, srcReg, index); context.AppendInstruction(X86.MovStore8, null, dstReg, index, tmp); } context.AppendInstruction(IRInstruction.StableObjectTracking); }
private void InsertExceptionStartInstructions() { var objectType = TypeSystem.GetTypeByName("System", "Object"); foreach (var clause in MethodCompiler.Method.ExceptionHandlers) { if (clause.ExceptionHandlerType == ExceptionHandlerType.Exception) { var handler = BasicBlocks.GetByLabel(clause.HandlerStart); var exceptionObject = MethodCompiler.CreateVirtualRegister(clause.Type); var context = new Context(handler); context.AppendInstruction(IRInstruction.ExceptionStart, exceptionObject); } if (clause.ExceptionHandlerType == ExceptionHandlerType.Filter) { { var handler = BasicBlocks.GetByLabel(clause.HandlerStart); var exceptionObject = MethodCompiler.CreateVirtualRegister(objectType); var context = new Context(handler); context.AppendInstruction(IRInstruction.ExceptionStart, exceptionObject); } { var handler = BasicBlocks.GetByLabel(clause.FilterStart.Value); var exceptionObject = MethodCompiler.CreateVirtualRegister(objectType); var context = new Context(handler); context.AppendInstruction(IRInstruction.FilterStart, exceptionObject); } } } }
/// <summary> /// Allows quick internal call replacements /// </summary> /// <param name="context">The context.</param> /// <param name="methodCompiler">The method compiler.</param> /// <param name="internalMethod">The internal method to replace with.</param> /// <param name="internalClass">The internal class that has the internal method.</param> /// <exception cref="ArgumentNullException"></exception> public static void MapToRunTime(Context context, MethodCompiler methodCompiler, string internalMethod, string internalClass = "Internal") { if (context == null || methodCompiler == null || internalMethod == null || internalClass == null) { throw new ArgumentNullException(); } var type = methodCompiler.TypeSystem.GetTypeByName("Mosa.Runtime", internalClass); Debug.Assert(type != null, "Cannot find Mosa.Runtime." + internalClass); var method = type.FindMethodByName(internalMethod); Debug.Assert(method != null, "Cannot find " + internalMethod + " in " + type.Name); var symbol = Operand.CreateSymbolFromMethod(method, methodCompiler.TypeSystem); var result = context.Result; var operands = new List <Operand>(context.Operands); context.SetInstruction(IRInstruction.CallStatic, result, symbol, operands); }
internal ImmutableArray <Diagnostic> FlowDiagnostics(CSharpCompilation compilation) { var flowDiagnostics = DiagnosticBag.GetInstance(); foreach (var method in AllMethods(compilation.SourceModule.GlobalNamespace)) { var sourceSymbol = method as SourceMemberMethodSymbol; if (sourceSymbol == null) { continue; } var boundBody = MethodCompiler.BindMethodBody(sourceSymbol, new TypeCompilationState(sourceSymbol.ContainingType, compilation, null), new DiagnosticBag()); if (boundBody != null) { FlowAnalysisPass.Rewrite(sourceSymbol, boundBody, flowDiagnostics, hasTrailingExpression: false, originalBodyNested: false); } } return(flowDiagnostics.ToReadOnlyAndFree <Diagnostic>()); }
private static void FrameCallRetR8(Context context, MethodCompiler methodCompiler) { var result = context.Result; var methodAddress = context.Operand1; var newESP = context.Operand2; var eax = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EAX); var edx = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EDX); var mmx1 = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, SSE2Register.XMM0); methodCompiler.SplitLongOperand(result, out Operand op0L, out Operand op0H); context.SetInstruction(X86.Call, null, methodAddress); context.AppendInstruction(IRInstruction.Gen, mmx1); context.AppendInstruction(X86.Movdi32ss, eax, mmx1); // CHECK context.AppendInstruction(X86.Pextrd32, edx, mmx1, methodCompiler.CreateConstant((byte)1)); context.AppendInstruction(X86.Mov32, op0L, eax); context.AppendInstruction(X86.Mov32, op0H, edx); }
void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, MethodCompiler methodCompiler) { var result = context.Result; var methodAddress = context.Operand1; var newESP = context.Operand2; var eax = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EAX); var edx = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EDX); var mmx1 = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, SSE2Register.XMM0); methodCompiler.SplitLongOperand(result, out Operand op0L, out Operand op0H); context.SetInstruction(X86.CallReg, null, methodAddress); context.AppendInstruction(IRInstruction.Gen, mmx1); context.AppendInstruction(X86.Movd, eax, mmx1); context.AppendInstruction(X86.Pextrd, edx, mmx1, methodCompiler.CreateConstant((byte)1)); context.AppendInstruction(X86.Mov32, op0L, eax); context.AppendInstruction(X86.Mov32, op0H, edx); }
internal ImmutableArray <Diagnostic> FlowDiagnostics(CSharpCompilation compilation) { var flowDiagnostics = DiagnosticBag.GetInstance(); foreach (var method in AllMethods(compilation.SourceModule.GlobalNamespace)) { var sourceSymbol = method as SourceMethodSymbol; if (sourceSymbol == null) { continue; } var boundBody = MethodCompiler.BindMethodBody(sourceSymbol, new DiagnosticBag()); if (boundBody != null) { FlowAnalysisPass.Rewrite(sourceSymbol, boundBody, flowDiagnostics); } } return(flowDiagnostics.ToReadOnlyAndFree <Diagnostic>()); }
internal static BoundBlock ParseAndBindMethodBody(string program, string typeName = DefaultTypeName, string methodName = DefaultMethodName) { var compilation = CreateCompilation(program); var method = (MethodSymbol)compilation.GlobalNamespace.GetTypeMembers(typeName).Single().GetMembers(methodName).Single(); // Provide an Emit.Module so that the lowering passes will be run var module = new PEAssemblyBuilder( (SourceAssemblySymbol)compilation.Assembly, emitOptions: EmitOptions.Default, outputKind: OutputKind.ConsoleApplication, serializationProperties: GetDefaultModulePropertiesForSerialization(), manifestResources: Enumerable.Empty <ResourceDescription>()); TypeCompilationState compilationState = new TypeCompilationState(method.ContainingType, compilation, module); var diagnostics = DiagnosticBag.GetInstance(); var block = MethodCompiler.BindMethodBody(method, compilationState, diagnostics); diagnostics.Free(); return(block); }
/// <summary> /// Validates the instruction operands and creates a matching variable for the result. /// </summary> /// <param name="context">The context.</param> /// <param name="methodCompiler">The compiler.</param> /// <exception cref="ArgumentNullException">context</exception> /// <exception cref="InvalidOperationException">Invalid virtualLocal state for pairing (" + context.Operand1.Type.GetStackType() + ", " + context.Operand2.Type.GetStackType() + ")</exception> public override void Resolve(Context context, MethodCompiler methodCompiler) { if (context == null) { throw new ArgumentNullException(nameof(context)); } base.Resolve(context, methodCompiler); var op1 = methodCompiler.Compiler.GetStackTypeCode(context.Operand1.Type); var op2 = methodCompiler.Compiler.GetStackTypeCode(context.Operand2.Type); var result = operandTable[(int)op1][(int)op2]; if (StackTypeCode.Unknown == result) { throw new CompilerException($"Invalid pairing ({context.Operand1.Type}, {context.Operand2.Type})"); } context.Result = methodCompiler.CreateVirtualRegister(methodCompiler.Compiler.GetStackTypeFromCode(result)); }
protected void GenerateMethodBodyCore( TypeCompilationState compilationState, BindingDiagnosticBag diagnostics ) { var factory = new SyntheticBoundNodeFactory( this, this.GetNonNullSyntaxNode(), compilationState, diagnostics ); factory.CurrentFunction = this; if (ContainingType.BaseTypeNoUseSiteDiagnostics is MissingMetadataTypeSymbol) { // System_Attribute was not found or was inaccessible factory.CloseMethod(factory.Block()); return; } var baseConstructorCall = MethodCompiler.GenerateBaseParameterlessConstructorInitializer(this, diagnostics); if (baseConstructorCall == null) { // Attribute..ctor was not found or was inaccessible factory.CloseMethod(factory.Block()); return; } var statements = ArrayBuilder <BoundStatement> .GetInstance(); statements.Add(factory.ExpressionStatement(baseConstructorCall)); GenerateMethodBodyStatements(factory, statements, diagnostics); statements.Add(factory.Return()); var block = factory.Block(statements.ToImmutableAndFree()); factory.CloseMethod(block); }
/// <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 static void Store(Context context, MethodCompiler methodCompiler) { if (context.OperandCount == 2) { var instruction = !context.Operand2.Is64BitInteger ? (BaseInstruction)IRInstruction.StoreInt32 : IRInstruction.StoreInt64; if (context.Operand2.IsR4) { instruction = IRInstruction.StoreFloatR4; } else if (context.Operand2.IsR8) { instruction = IRInstruction.StoreFloatR8; } context.SetInstruction(instruction, null, context.Operand1, methodCompiler.ConstantZero, context.Operand2); } else if (context.OperandCount == 3) { var instruction = !context.Operand3.Is64BitInteger ? (BaseInstruction)IRInstruction.StoreInt32 : IRInstruction.StoreInt64; if (context.Operand3.IsR4) { instruction = IRInstruction.StoreFloatR4; } else if (context.Operand3.IsR8) { instruction = IRInstruction.StoreFloatR8; } context.SetInstruction(instruction, null, context.Operand1, context.Operand2, context.Operand3); } else { throw new CompilerException(); } LoadStore.OrderStoreOperands(context, methodCompiler); }
protected void Compile(string source, IMetadataImporter metadataImporter = null, IRuntimeLibrary runtimeLibrary = null, IErrorReporter errorReporter = null, bool useFirstConstructor = false) { Compile(new[] { source }, metadataImporter: metadataImporter, runtimeLibrary: runtimeLibrary, errorReporter: errorReporter, methodCompiled: (m, res, mc) => { if (m.IsConstructor && (m.Attributes.Any() || useFirstConstructor)) { Constructor = m; MethodCompiler = mc; CompiledConstructor = res; } }); Assert.That(Constructor, Is.Not.Null, "No constructors with attributes were compiled."); }
public CilToX86CodeVisitor(MethodCompiler methodCompiler) { this.MethodCompiler = methodCompiler; }
public void Setup() { Method = null; MethodCompiler = null; CompiledMethod = null; }
protected void Compile(string source, INamingConventionResolver namingConvention = null, IRuntimeLibrary runtimeLibrary = null, IErrorReporter errorReporter = null, bool useFirstConstructor = false) { Compile(new[] { source }, namingConvention, runtimeLibrary, errorReporter, (m, res, mc) => { if (m.IsConstructor && (m.Attributes.Any() || useFirstConstructor)) { Constructor = m; MethodCompiler = mc; CompiledConstructor = res; } }); Assert.That(Constructor, Is.Not.Null, "No constructors with attributes were compiled."); }
private void OnMethodCompiled(IMethod method, JsFunctionDefinitionExpression result, MethodCompiler mc) { if (MethodCompiled != null) MethodCompiled(method, result, mc); }
public void IgnoreOtherDiagnosticsCompilingSynthesizedMethods() { var source = @"class C { static object F = new object(); // generate .cctor static System.Action M() { return () => { }; // generate lambda } }"; var compilation = CreateCompilationWithMscorlib(source, options: TestOptions.ReleaseDll.WithConcurrentBuild(false)); var options = compilation.Options; var diagnostics = DiagnosticBag.GetInstance(); var assembly = (SourceAssemblySymbol)compilation.Assembly; var module = new PEAssemblyBuilder( assembly, EmitOptions.Default, options.OutputKind, GetDefaultModulePropertiesForSerialization(), new ResourceDescription[0]); var methodBodyCompiler = new MethodCompiler( compilation: compilation, moduleBeingBuiltOpt: module, emittingPdb: false, hasDeclarationErrors: false, diagnostics: diagnostics, filterOpt: null, cancellationToken: CancellationToken.None); // Add diagnostic to MethodBodyCompiler bag, as if // code gen for an earlier method had generated an error. diagnostics.Add(new CSDiagnostic(new CSDiagnosticInfo(ErrorCode.ERR_IntDivByZero), NoLocation.Singleton)); // Compile all methods for type including synthesized methods. var type = compilation.GlobalNamespace.GetMember<NamedTypeSymbol>("C"); methodBodyCompiler.Visit(type); Assert.Equal(1, diagnostics.AsEnumerable().Count()); diagnostics.Free(); }