public void CompileMethod(MethodDesc method) { _compilation.Log.WriteLine("Compiling " + method.ToString()); SpecialMethodKind kind = method.DetectSpecialMethodKind(); if (kind != SpecialMethodKind.Unknown) { string specialMethodCode = CompileSpecialMethod(method, kind); _compilation.GetRegisteredMethod(method).MethodCode = specialMethodCode; return; } var methodIL = _compilation.GetMethodIL(method); if (methodIL == null) { return; } string methodCode; try { var ilImporter = new ILImporter(_compilation, this, method, methodIL); CompilerTypeSystemContext typeSystemContext = _compilation.TypeSystemContext; if (!_compilation.Options.NoLineNumbers) { IEnumerable <ILSequencePoint> sequencePoints = typeSystemContext.GetSequencePointsForMethod(method); if (sequencePoints != null) { ilImporter.SetSequencePoints(sequencePoints); } } IEnumerable <LocalVariable> localVariables = typeSystemContext.GetLocalVariableNamesForMethod(method); if (localVariables != null) { ilImporter.SetLocalVariables(localVariables); } IEnumerable <string> parameters = typeSystemContext.GetParameterNamesForMethod(method); if (parameters != null) { ilImporter.SetParameterNames(parameters); } methodCode = ilImporter.Compile(); } catch (Exception e) { _compilation.Log.WriteLine(e.Message + " (" + method + ")"); methodCode = GetCppMethodDeclaration(method, true) + " { throw 0xC000C000; }" + Environment.NewLine; } _compilation.GetRegisteredMethod(method).MethodCode = methodCode; }
protected override void ComputeDependencyNodeDependencies(List <DependencyNodeCore <NodeFactory> > obj) { foreach (DependencyNodeCore <NodeFactory> dependency in obj) { var methodCodeNodeNeedingCode = dependency as ScannedMethodNode; if (methodCodeNodeNeedingCode == null) { // To compute dependencies of the shadow method that tracks dictionary // dependencies we need to ensure there is code for the canonical method body. var dependencyMethod = (ShadowConcreteMethodNode)dependency; methodCodeNodeNeedingCode = (ScannedMethodNode)dependencyMethod.CanonicalMethodNode; } // We might have already compiled this method. if (methodCodeNodeNeedingCode.StaticDependenciesAreComputed) { continue; } MethodDesc method = methodCodeNodeNeedingCode.Method; try { var importer = new ILImporter(this, method); methodCodeNodeNeedingCode.InitializeDependencies(_nodeFactory, importer.Import()); } catch (TypeSystemException ex) { // Try to compile the method again, but with a throwing method body this time. MethodIL throwingIL = TypeSystemThrowingILEmitter.EmitIL(method, ex); var importer = new ILImporter(this, method, throwingIL); methodCodeNodeNeedingCode.InitializeDependencies(_nodeFactory, importer.Import()); } } }
void TestMethodsWithInvalidIL(InvalidILTestCase invalidILTestCase) { ILImporter importer = ConstructILImporter(invalidILTestCase); var verifierErrors = new List <VerifierError>(); importer.ReportVerificationError = new Action <VerificationErrorArgs>((err) => { verifierErrors.Add(err.Code); }); try { importer.Verify(); } catch { //in some cases ILVerify throws exceptions when things look too wrong to continue //currently these are not caught. In tests we just catch these and do the asserts. //Once these exceptions are better handled and ILVerify instead of crashing aborts the verification //gracefully we can remove this empty catch block. } finally { Assert.Equal(invalidILTestCase.ExpectedVerifierErrors.Count, verifierErrors.Count); foreach (var item in invalidILTestCase.ExpectedVerifierErrors) { Assert.True(verifierErrors.Contains(item)); } } }
private void CompileSingleMethod(ScannedMethodNode methodCodeNodeNeedingCode) { MethodDesc method = methodCodeNodeNeedingCode.Method; try { var importer = new ILImporter(this, method); methodCodeNodeNeedingCode.InitializeDependencies(_nodeFactory, importer.Import()); } catch (TypeSystemException ex) { // Try to compile the method again, but with a throwing method body this time. MethodIL throwingIL = TypeSystemThrowingILEmitter.EmitIL(method, ex); var importer = new ILImporter(this, method, throwingIL); methodCodeNodeNeedingCode.InitializeDependencies(_nodeFactory, importer.Import(), ex); } catch (Exception ex) { throw new CodeGenerationFailedException(method, ex); } finally { if (_compilationCountdown != null) { _compilationCountdown.Signal(); } } }
public void InterpretMethod(ref CallInterceptorArgs callInterceptorArgs) { _callInterceptorArgs = callInterceptorArgs; ILImporter importer = new ILImporter(this, _method, _methodIL); importer.Interpret(); }
protected override void ComputeDependencyNodeDependencies(List <DependencyNodeCore <NodeFactory> > obj) { foreach (WebAssemblyMethodCodeNode methodCodeNodeNeedingCode in obj) { ILImporter.CompileMethod(this, methodCodeNodeNeedingCode); } }
void TestMethodsWithValidIL(ValidILTestCase validIL) { ILImporter importer = ConstructILImporter(validIL); var verifierErrors = new List <VerifierError>(); importer.ReportVerificationError = new Action <VerificationErrorArgs>((err) => { verifierErrors.Add(err.Code); }); importer.Verify(); Assert.Equal(0, verifierErrors.Count); }
protected override void ComputeDependencyNodeDependencies(List <DependencyNodeCore <NodeFactory> > obj) { foreach (var dependency in obj) { var methodCodeNodeNeedingCode = dependency as WebAssemblyMethodCodeNode; if (methodCodeNodeNeedingCode == null) { // To compute dependencies of the shadow method that tracks dictionary // dependencies we need to ensure there is code for the canonical method body. var dependencyMethod = (ShadowConcreteMethodNode)dependency; methodCodeNodeNeedingCode = (WebAssemblyMethodCodeNode)dependencyMethod.CanonicalMethodNode; } // We might have already compiled this method. if (methodCodeNodeNeedingCode.StaticDependenciesAreComputed) { continue; } ILImporter.CompileMethod(this, methodCodeNodeNeedingCode); } }
public void CompileMethod(CppMethodCodeNode methodCodeNodeNeedingCode) { MethodDesc method = methodCodeNodeNeedingCode.Method; _compilation.Log.WriteLine("Compiling " + method.ToString()); SpecialMethodKind kind = method.DetectSpecialMethodKind(); if (kind != SpecialMethodKind.Unknown) { string specialMethodCode = CompileSpecialMethod(method, kind); methodCodeNodeNeedingCode.SetCode(specialMethodCode, Array.Empty <Object>()); return; } var methodIL = _compilation.GetMethodIL(method); if (methodIL == null) { return; } try { var ilImporter = new ILImporter(_compilation, this, method, methodIL); CompilerTypeSystemContext typeSystemContext = _compilation.TypeSystemContext; if (!_compilation.Options.NoLineNumbers) { IEnumerable <ILSequencePoint> sequencePoints = typeSystemContext.GetSequencePointsForMethod(method); if (sequencePoints != null) { ilImporter.SetSequencePoints(sequencePoints); } } IEnumerable <ILLocalVariable> localVariables = typeSystemContext.GetLocalVariableNamesForMethod(method); if (localVariables != null) { ilImporter.SetLocalVariables(localVariables); } IEnumerable <string> parameters = typeSystemContext.GetParameterNamesForMethod(method); if (parameters != null) { ilImporter.SetParameterNames(parameters); } ilImporter.Compile(methodCodeNodeNeedingCode); } catch (Exception e) { _compilation.Log.WriteLine(e.Message + " (" + method + ")"); var builder = new CppGenerationBuffer(); builder.AppendLine(); builder.Append(GetCppMethodDeclaration(method, true)); builder.AppendLine(); builder.Append("{"); builder.Indent(); builder.AppendLine(); builder.Append("throw 0xC000C000;"); builder.Exdent(); builder.AppendLine(); builder.Append("}"); methodCodeNodeNeedingCode.SetCode(builder.ToString(), Array.Empty <Object>()); } }
private IEnumerable <VerificationResult> VerifyMethod(EcmaModule module, MethodIL methodIL, MethodDefinitionHandle methodHandle) { var builder = new ArrayBuilder <VerificationResult>(); MethodDesc method = methodIL.OwningMethod; try { var importer = new ILImporter(method, methodIL); importer.ReportVerificationError = (args) => { var codeResource = _stringResourceManager.Value.GetString(args.Code.ToString(), CultureInfo.InvariantCulture); builder.Add(new VerificationResult() { Method = methodHandle, Error = args, Message = string.IsNullOrEmpty(codeResource) ? args.Code.ToString() : codeResource }); }; importer.Verify(); } catch (VerificationException) { // a result was reported already (before aborting) } catch (BadImageFormatException) { builder.Add(new VerificationResult() { Method = methodHandle, Message = "Unable to resolve token" }); } catch (NotImplementedException e) { reportException(e); } catch (InvalidProgramException e) { reportException(e); } catch (PlatformNotSupportedException e) { reportException(e); } catch (VerifierException e) { reportException(e); } catch (TypeSystemException e) { reportException(e); } return(builder.ToArray()); void reportException(Exception e) { builder.Add(new VerificationResult() { Method = methodHandle, Message = e.Message }); } }
public void CompileMethod(CppMethodCodeNode methodCodeNodeNeedingCode) { MethodDesc method = methodCodeNodeNeedingCode.Method; _compilation.Logger.Writer.WriteLine("Compiling " + method.ToString()); if (method.HasCustomAttribute("System.Runtime", "RuntimeImportAttribute")) { CompileExternMethod(methodCodeNodeNeedingCode, ((EcmaMethod)method).GetRuntimeImportName()); return; } if (method.IsRawPInvoke()) { CompileExternMethod(methodCodeNodeNeedingCode, method.GetPInvokeMethodMetadata().Name ?? method.Name); return; } var methodIL = _compilation.GetMethodIL(method); if (methodIL == null) { return; } try { // TODO: hacky special-case if (method.Name == "_ecvt_s") { throw new NotImplementedException(); } var ilImporter = new ILImporter(_compilation, this, method, methodIL); CompilerTypeSystemContext typeSystemContext = _compilation.TypeSystemContext; MethodDebugInformation debugInfo = _compilation.GetDebugInfo(methodIL); if (!_compilation.Options.HasOption(CppCodegenConfigProvider.NoLineNumbersString)) { IEnumerable <ILSequencePoint> sequencePoints = debugInfo.GetSequencePoints(); if (sequencePoints != null) { ilImporter.SetSequencePoints(sequencePoints); } } IEnumerable <ILLocalVariable> localVariables = debugInfo.GetLocalVariables(); if (localVariables != null) { ilImporter.SetLocalVariables(localVariables); } IEnumerable <string> parameters = GetParameterNamesForMethod(method); if (parameters != null) { ilImporter.SetParameterNames(parameters); } ilImporter.Compile(methodCodeNodeNeedingCode); } catch (Exception e) { _compilation.Logger.Writer.WriteLine(e.Message + " (" + method + ")"); var sb = new CppGenerationBuffer(); sb.AppendLine(); AppendCppMethodDeclaration(sb, method, true); sb.AppendLine(); sb.Append("{"); sb.Indent(); sb.AppendLine(); sb.Append("throw 0xC000C000;"); sb.Exdent(); sb.AppendLine(); sb.Append("}"); methodCodeNodeNeedingCode.SetCode(sb.ToString(), Array.Empty <Object>()); } }
private void GetCodeForReadyToRunGenericHelper(WebAssemblyCodegenCompilation compilation, ReadyToRunGenericHelperNode node, NodeFactory factory) { LLVMBuilderRef builder = compilation.Module.Context.CreateBuilder(); var args = new List <LLVMTypeRef>(); MethodDesc delegateCtor = null; if (node.Id == ReadyToRunHelperId.DelegateCtor) { DelegateCreationInfo target = (DelegateCreationInfo)node.Target; delegateCtor = target.Constructor.Method; bool isStatic = delegateCtor.Signature.IsStatic; int argCount = delegateCtor.Signature.Length; if (!isStatic) { argCount++; } for (int i = 0; i < argCount; i++) { TypeDesc argType; if (i == 0 && !isStatic) { argType = delegateCtor.OwningType; } else { argType = delegateCtor.Signature[i - (isStatic ? 0 : 1)]; } args.Add(ILImporter.GetLLVMTypeForTypeDesc(argType)); } } LLVMValueRef helperFunc = Module.GetNamedFunction(node.GetMangledName(factory.NameMangler)); if (helperFunc.Handle == IntPtr.Zero) { throw new Exception("if the function is requested here, it should have been created earlier"); } var helperBlock = helperFunc.AppendBasicBlock("genericHelper"); builder.PositionAtEnd(helperBlock); var importer = new ILImporter(builder, compilation, Module, helperFunc, delegateCtor); LLVMValueRef ctx; string gepName; if (node is ReadyToRunGenericLookupFromTypeNode) { // Locate the VTable slot that points to the dictionary int vtableSlot = VirtualMethodSlotHelper.GetGenericDictionarySlot(factory, (TypeDesc)node.DictionaryOwner); int pointerSize = factory.Target.PointerSize; // Load the dictionary pointer from the VTable int slotOffset = EETypeNode.GetVTableOffset(pointerSize) + (vtableSlot * pointerSize); var slotGep = builder.BuildGEP(helperFunc.GetParam(1), new[] { LLVMValueRef.CreateConstInt(LLVMTypeRef.Int32, (ulong)slotOffset, false) }, "slotGep"); var slotGepPtrPtr = builder.BuildPointerCast(slotGep, LLVMTypeRef.CreatePointer(LLVMTypeRef.CreatePointer(LLVMTypeRef.Int8, 0), 0), "slotGepPtrPtr"); ctx = builder.BuildLoad(slotGepPtrPtr, "dictGep"); gepName = "typeNodeGep"; } else { ctx = helperFunc.GetParam(1); gepName = "paramGep"; } LLVMValueRef resVar = OutputCodeForDictionaryLookup(builder, factory, node, node.LookupSignature, ctx, gepName); switch (node.Id) { case ReadyToRunHelperId.GetNonGCStaticBase: { MetadataType target = (MetadataType)node.Target; if (compilation.TypeSystemContext.HasLazyStaticConstructor(target)) { importer.OutputCodeForTriggerCctor(target, resVar); } } break; case ReadyToRunHelperId.GetGCStaticBase: { MetadataType target = (MetadataType)node.Target; var ptrPtrPtr = builder.BuildBitCast(resVar, LLVMTypeRef.CreatePointer(LLVMTypeRef.CreatePointer(LLVMTypeRef.CreatePointer(LLVMTypeRef.Int8, 0), 0), 0), "ptrPtrPtr"); resVar = builder.BuildLoad(builder.BuildLoad(ptrPtrPtr, "ind1"), "ind2"); if (compilation.TypeSystemContext.HasLazyStaticConstructor(target)) { GenericLookupResult nonGcRegionLookup = factory.GenericLookup.TypeNonGCStaticBase(target); var nonGcStaticsBase = OutputCodeForDictionaryLookup(builder, factory, node, nonGcRegionLookup, ctx, "lazyGep"); importer.OutputCodeForTriggerCctor(target, nonGcStaticsBase); } } break; case ReadyToRunHelperId.GetThreadStaticBase: { MetadataType target = (MetadataType)node.Target; if (compilation.TypeSystemContext.HasLazyStaticConstructor(target)) { GenericLookupResult nonGcRegionLookup = factory.GenericLookup.TypeNonGCStaticBase(target); var threadStaticBase = OutputCodeForDictionaryLookup(builder, factory, node, nonGcRegionLookup, ctx, "tsGep"); importer.OutputCodeForTriggerCctor(target, threadStaticBase); } resVar = importer.OutputCodeForGetThreadStaticBaseForType(resVar).ValueAsType(LLVMTypeRef.CreatePointer(LLVMTypeRef.Int8, 0), builder); } break; case ReadyToRunHelperId.DelegateCtor: { DelegateCreationInfo target = (DelegateCreationInfo)node.Target; MethodDesc constructor = target.Constructor.Method; var fatPtr = ILImporter.MakeFatPointer(builder, resVar, compilation); importer.OutputCodeForDelegateCtorInit(builder, helperFunc, constructor, fatPtr); } break; // These are all simple: just get the thing from the dictionary and we're done case ReadyToRunHelperId.TypeHandle: case ReadyToRunHelperId.MethodHandle: case ReadyToRunHelperId.FieldHandle: case ReadyToRunHelperId.MethodDictionary: case ReadyToRunHelperId.MethodEntry: case ReadyToRunHelperId.VirtualDispatchCell: case ReadyToRunHelperId.DefaultConstructor: break; default: throw new NotImplementedException(); } if (node.Id != ReadyToRunHelperId.DelegateCtor) { builder.BuildRet(resVar); } else { builder.BuildRetVoid(); } }
public void CompileMethod(CppMethodCodeNode methodCodeNodeNeedingCode) { MethodDesc method = methodCodeNodeNeedingCode.Method; _compilation.Logger.Writer.WriteLine("Compiling " + method.ToString()); if (method.HasCustomAttribute("System.Runtime", "RuntimeImportAttribute")) { CompileExternMethod(methodCodeNodeNeedingCode, ((EcmaMethod)method).GetRuntimeImportName()); return; } if (method.IsRawPInvoke()) { CompileExternMethod(methodCodeNodeNeedingCode, method.GetPInvokeMethodMetadata().Name ?? method.Name); return; } var methodIL = _compilation.GetMethodIL(method); if (methodIL == null) { return; } // TODO: Remove this code once CppCodegen is able to generate code for the reflection startup path. // The startup path runs before any user code is executed. // For now we replace the startup path with a simple "ret". Reflection won't work, but // programs not using reflection will. if (method.Name == ".cctor") { MetadataType owningType = method.OwningType as MetadataType; if (owningType != null && owningType.Name == "ReflectionExecution" && owningType.Namespace == "Internal.Reflection.Execution") { methodIL = new Internal.IL.Stubs.ILStubMethodIL(method, new byte[] { (byte)ILOpcode.ret }, Array.Empty <LocalVariableDefinition>(), null); } } try { // TODO: hacky special-case if (method.Name == "_ecvt_s") { throw new NotImplementedException(); } var ilImporter = new ILImporter(_compilation, this, method, methodIL); CompilerTypeSystemContext typeSystemContext = _compilation.TypeSystemContext; MethodDebugInformation debugInfo = _compilation.GetDebugInfo(methodIL); if (!_compilation.Options.HasOption(CppCodegenConfigProvider.NoLineNumbersString)) { IEnumerable <ILSequencePoint> sequencePoints = debugInfo.GetSequencePoints(); if (sequencePoints != null) { ilImporter.SetSequencePoints(sequencePoints); } } IEnumerable <ILLocalVariable> localVariables = debugInfo.GetLocalVariables(); if (localVariables != null) { ilImporter.SetLocalVariables(localVariables); } IEnumerable <string> parameters = GetParameterNamesForMethod(method); if (parameters != null) { ilImporter.SetParameterNames(parameters); } ilImporter.Compile(methodCodeNodeNeedingCode); } catch (Exception e) { _compilation.Logger.Writer.WriteLine(e.Message + " (" + method + ")"); var sb = new CppGenerationBuffer(); sb.AppendLine(); AppendCppMethodDeclaration(sb, method, true); sb.AppendLine(); sb.Append("{"); sb.Indent(); sb.AppendLine(); sb.Append("throw 0xC000C000;"); sb.Exdent(); sb.AppendLine(); sb.Append("}"); methodCodeNodeNeedingCode.SetCode(sb.ToString(), Array.Empty <Object>()); } }
private void VerifyMethod(MethodDesc method, MethodIL methodIL) { // Console.WriteLine("Verifying: " + method.ToString()); try { var importer = new ILImporter(method, methodIL); importer.ReportVerificationError = (args) => { var message = new StringBuilder(); message.Append("[IL]: Error: "); message.Append("["); message.Append(_typeSystemContext.GetModulePath(((EcmaMethod)method).Module)); message.Append(" : "); message.Append(((EcmaType)method.OwningType).Name); message.Append("::"); message.Append(method.Name); message.Append("]"); message.Append("[offset 0x"); message.Append(args.Offset.ToString("X8")); message.Append("]"); if (args.Found != null) { message.Append("[found "); message.Append(args.Found); message.Append("]"); } if (args.Expected != null) { message.Append("[expected "); message.Append(args.Expected); message.Append("]"); } if (args.Token != 0) { message.Append("[token 0x"); message.Append(args.Token.ToString("X8")); message.Append("]"); } message.Append(" "); if (_stringResourceManager == null) { _stringResourceManager = new ResourceManager("ILVerify.Resources.Strings", Assembly.GetExecutingAssembly()); } var str = _stringResourceManager.GetString(args.Code.ToString(), CultureInfo.InvariantCulture); message.Append(string.IsNullOrEmpty(str) ? args.Code.ToString() : str); Console.WriteLine(message); _numErrors++; }; importer.Verify(); } catch (NotImplementedException e) { Console.Error.WriteLine($"Error in {method}: {e.Message}"); } catch (InvalidProgramException e) { Console.Error.WriteLine($"Error in {method}: {e.Message}"); } catch (VerificationException) { } catch (BadImageFormatException) { Console.WriteLine("Unable to resolve token"); } catch (PlatformNotSupportedException e) { Console.WriteLine(e.Message); } }
private void VerifyMethod(MethodDesc method, MethodIL methodIL) { // Console.WriteLine("Verifying: " + method.ToString()); try { var importer = new ILImporter(method, methodIL); importer.ReportVerificationError = (args) => { var message = new StringBuilder(); message.Append("[IL]: Error: "); message.Append("["); message.Append(_typeSystemContext.GetModulePath(((EcmaMethod)method).Module)); message.Append(" : "); message.Append(((EcmaType)method.OwningType).Name); message.Append("::"); message.Append(method.Name); message.Append("]"); message.Append("[offset 0x"); message.Append(args.Offset.ToString("X8")); message.Append("]"); if (args.Found != null) { message.Append("[found "); message.Append(args.Found); message.Append("]"); } if (args.Expected != null) { message.Append("[expected "); message.Append(args.Expected); message.Append("]"); } if (args.Token != 0) { message.Append("[token 0x"); message.Append(args.Token.ToString("X8")); message.Append("]"); } message.Append(" "); message.Append(SR.GetResourceString(args.Code.ToString(), null) ?? args.Code.ToString()); Console.WriteLine(message); _numErrors++; }; importer.Verify(); } catch (VerificationException) { } catch (BadImageFormatException) { Console.WriteLine("Unable to resolve token"); } catch (PlatformNotSupportedException e) { Console.WriteLine(e.Message); } }