using System.Collections.Generic;
using System.IO;
using System.Reflection.PortableExecutable;
+using System.Reflection.Metadata.Ecma335;
+using System.Text;
using Internal.IL;
using Internal.JitInterface;
/// </summary>
private readonly CorInfoImpl _corInfo;
+ private bool _doNotFailOnCodegenCompilationExceptions;
+
public new ReadyToRunCodegenNodeFactory NodeFactory { get; }
public ReadyToRunSymbolNodeFactory SymbolNodeFactory { get; }
DevirtualizationManager devirtualizationManager,
JitConfigProvider configProvider,
string inputFilePath,
- IEnumerable<ModuleDesc> modulesBeingInstrumented)
+ IEnumerable<ModuleDesc> modulesBeingInstrumented,
+ bool doNotFailOnCodegenCompilationExceptions)
: base(dependencyGraph, nodeFactory, roots, ilProvider, devirtualizationManager, modulesBeingInstrumented, logger)
{
+ _doNotFailOnCodegenCompilationExceptions = doNotFailOnCodegenCompilationExceptions;
NodeFactory = nodeFactory;
SymbolNodeFactory = new ReadyToRunSymbolNodeFactory(nodeFactory);
_jitConfigProvider = configProvider;
if (Logger.IsVerbose)
{
- string methodName = method.ToString();
+ string methodName = ResilientNameComputation(method);
Logger.Writer.WriteLine("Compiling " + methodName);
}
catch (TypeSystemException ex)
{
// If compilation fails, don't emit code for this method. It will be Jitted at runtime
- Logger.Writer.WriteLine($"Warning: Method `{method}` was not compiled because: {ex.Message}");
+ Logger.Writer.WriteLine($"Warning: Method `{ResilientNameComputation(method)}` was not compiled because: {ex.Message}");
}
catch (RequiresRuntimeJitException ex)
{
- Logger.Writer.WriteLine($"Info: Method `{method}` was not compiled because `{ex.Message}` requires runtime JIT");
+ Logger.Writer.WriteLine($"Info: Method `{ResilientNameComputation(method)}` was not compiled because `{ex.Message}` requires runtime JIT");
+ }
+ catch (CodeGenerationFailedException ex) when (_doNotFailOnCodegenCompilationExceptions)
+ {
+ Logger.Writer.WriteLine($"Warning: Method `{ResilientNameComputation(method)}` was not compiled because `{ex.Message}` requires runtime JIT");
}
finally
{
}
}
+ private string ResilientNameComputation(MethodDesc method)
+ {
+ try
+ {
+ return method.ToString();
+ }
+ catch (TypeSystemException)
+ {
+ string typeName = ResilientNameComputation((MetadataType)method.OwningType);
+ if (typeName == null)
+ {
+ if (method is EcmaMethod)
+ {
+ typeName = "";
+ }
+ else
+ {
+ return "Unknown";
+ }
+ }
+
+ return $"{typeName}.{ResilientNameComputationMethodNameWorker(method)}";
+ }
+ }
+
+ private string ResilientNameComputationMethodNameWorker(MethodDesc method)
+ {
+ if (method is EcmaMethod ecmaMethod)
+ {
+ return $"MethodDef({ecmaMethod.MetadataReader.GetToken(ecmaMethod.Handle):x8})";
+ }
+ else if (method is InstantiatedMethod instMethod)
+ {
+ StringBuilder nameBuilder = new StringBuilder();
+ nameBuilder.Append(ResilientNameComputationMethodNameWorker(instMethod.GetMethodDefinition()));
+ AppendInstantiation(nameBuilder, instMethod.Instantiation);
+ return nameBuilder.ToString();
+ }
+ return "Unknown";
+ }
+
+ private void AppendInstantiation(StringBuilder nameBuilder, Instantiation instantiation)
+ {
+ nameBuilder.Append('<');
+ bool printedFirst = false;
+ foreach (TypeDesc type in instantiation)
+ {
+ if (printedFirst)
+ nameBuilder.Append(',');
+ else
+ printedFirst = true;
+ nameBuilder.Append(ResilientNameComputation(type));
+ }
+ nameBuilder.Append('>');
+ }
+
+ private string ResilientNameComputation(TypeDesc type)
+ {
+ string typeName = null;
+ try
+ {
+ try
+ {
+ typeName = type.ToString();
+ }
+ catch (TypeSystemException)
+ {
+ if (type is InstantiatedType instType)
+ {
+ StringBuilder nameBuilder = new StringBuilder();
+ nameBuilder.Append(ResilientNameComputation(instType.UnderlyingType));
+ AppendInstantiation(nameBuilder, instType.Instantiation);
+ typeName = nameBuilder.ToString();
+ }
+ else if (type is EcmaType ecmaType)
+ {
+ typeName = $"[{ecmaType.EcmaModule.Assembly.GetName().Name.ToString()}]TypeDef({ecmaType.MetadataReader.GetToken(ecmaType.Handle):x8})";
+ }
+ else if (type is ArrayType arrayType)
+ {
+ StringBuilder nameBuilder = new StringBuilder();
+ nameBuilder.Append(ResilientNameComputation(arrayType));
+ nameBuilder.Append('[');
+ for (int i = 1; i < arrayType.Rank; i++)
+ {
+ nameBuilder.Append(i);
+ }
+ if ((arrayType.Rank == 1) && arrayType.IsMdArray)
+ nameBuilder.Append('*');
+
+ nameBuilder.Append(']');
+ }
+ }
+ }
+ catch (TypeSystemException)
+ {
+ }
+
+ return typeName;
+ }
+
public ISymbolNode GetFieldRvaData(FieldDesc field) => NodeFactory.CopiedFieldRva(field);
}
}
private readonly string _inputFilePath;
private readonly EcmaModule _inputModule;
private readonly bool _ibcTuning;
+ private readonly bool _doNotFailOnCodegenCompilationExceptions;
// These need to provide reasonable defaults so that the user can optionally skip
// calling the Use/Configure methods and still get something reasonable back.
private KeyValuePair<string, string>[] _ryujitOptions = Array.Empty<KeyValuePair<string, string>>();
private ILProvider _ilProvider = new ReadyToRunILProvider();
- public ReadyToRunCodegenCompilationBuilder(CompilerTypeSystemContext context, CompilationModuleGroup group, string inputFilePath, bool ibcTuning)
+ public ReadyToRunCodegenCompilationBuilder(CompilerTypeSystemContext context, CompilationModuleGroup group, string inputFilePath, bool ibcTuning, bool doNotFailOnCodegenCompilationExceptions)
: base(context, group, new CoreRTNameMangler())
{
_ibcTuning = ibcTuning;
+ _doNotFailOnCodegenCompilationExceptions = doNotFailOnCodegenCompilationExceptions;
_inputFilePath = inputFilePath;
_inputModule = context.GetModuleFromPath(_inputFilePath);
new DependencyAnalysis.ReadyToRun.DevirtualizationManager(_compilationGroup),
jitConfig,
_inputFilePath,
- new ModuleDesc[] { _inputModule });
+ new ModuleDesc[] { _inputModule },
+ _doNotFailOnCodegenCompilationExceptions);
}
}
}
private string _systemModuleName = DefaultSystemModule;
private bool _tuning;
private bool _partial;
+ private bool _doNotFailOnCodegenCompilationExceptions;
private string _singleMethodTypeName;
private string _singleMethodName;
syntax.DefineOption("systemmodule", ref _systemModuleName, "System module name (default: System.Private.CoreLib)");
syntax.DefineOption("waitfordebugger", ref waitForDebugger, "Pause to give opportunity to attach debugger");
syntax.DefineOptionList("codegenopt", ref _codegenOptions, "Define a codegen option");
+ syntax.DefineOption("doNotFailOnCodegenCompilationExceptions", ref _doNotFailOnCodegenCompilationExceptions, "Disable behavior where unexpected compilation failures cause overall compilation failure");
syntax.DefineOption("targetarch", ref _targetArchitectureStr, "Target architecture for cross compilation");
syntax.DefineOption("targetos", ref _targetOSStr, "Target OS for cross compilation");
inputFilePath = input.Value;
break;
}
- CompilationBuilder builder = new ReadyToRunCodegenCompilationBuilder(typeSystemContext, compilationGroup, inputFilePath, _tuning);
+ CompilationBuilder builder = new ReadyToRunCodegenCompilationBuilder(typeSystemContext, compilationGroup, inputFilePath,
+ ibcTuning: _tuning,
+ doNotFailOnCodegenCompilationExceptions: _doNotFailOnCodegenCompilationExceptions);
string compilationUnitPrefix = "";
builder.UseCompilationUnitPrefix(compilationUnitPrefix);