Skip to content

Commit

Permalink
Initial population of crossgen2 sources from CoreRT repo as of commit d…
Browse files Browse the repository at this point in the history
  • Loading branch information
dotnet-bot authored and MichalStrehovsky committed Sep 9, 2019
1 parent 6cadaf4 commit ac857a2
Show file tree
Hide file tree
Showing 371 changed files with 65,660 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;

namespace Internal.CommandLine
{
internal class CommandLineException : Exception
{
public CommandLineException(string message)
: base(message)
{
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.IO;

namespace Internal.CommandLine
{
//
// Helpers for command line processing
//
internal class Helpers
{
// Helper to create a collection of paths unique in their simple names.
public static void AppendExpandedPaths(Dictionary<string, string> dictionary, string pattern, bool strict)
{
bool empty = true;

string directoryName = Path.GetDirectoryName(pattern);
string searchPattern = Path.GetFileName(pattern);

if (directoryName == "")
directoryName = ".";

if (Directory.Exists(directoryName))
{
foreach (string fileName in Directory.EnumerateFiles(directoryName, searchPattern))
{
string fullFileName = Path.GetFullPath(fileName);

string simpleName = Path.GetFileNameWithoutExtension(fileName);

if (dictionary.ContainsKey(simpleName))
{
if (strict)
{
throw new CommandLineException("Multiple input files matching same simple name " +
fullFileName + " " + dictionary[simpleName]);
}
}
else
{
dictionary.Add(simpleName, fullFileName);
}

empty = false;
}
}

if (empty)
{
if (strict)
{
throw new CommandLineException("No files matching " + pattern);
}
else
{
Console.WriteLine("Warning: No files matching " + pattern);
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;

using Internal.TypeSystem;

namespace ILCompiler
{
public class CodeGenerationFailedException : InternalCompilerErrorException
{
private const string MessageText = "Code generation failed for method '{0}'";

public MethodDesc Method { get; }

public CodeGenerationFailedException(MethodDesc method)
: this(method, null)
{
}

public CodeGenerationFailedException(MethodDesc method, Exception inner)
: base(String.Format(MessageText, method), inner)
{
Method = method;
}
}
}
108 changes: 108 additions & 0 deletions src/coreclr/src/tools/crossgen2/Common/Compiler/CompilationBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;

using ILCompiler.DependencyAnalysis;
using ILCompiler.DependencyAnalysisFramework;

using Internal.IL;

namespace ILCompiler
{
public abstract partial class CompilationBuilder
{
protected readonly CompilerTypeSystemContext _context;
protected readonly CompilationModuleGroup _compilationGroup;
protected readonly NameMangler _nameMangler;

// These need to provide reasonable defaults so that the user can optionally skip
// calling the Use/Configure methods and still get something reasonable back.
protected Logger _logger = Logger.Null;
private DependencyTrackingLevel _dependencyTrackingLevel = DependencyTrackingLevel.None;
protected IEnumerable<ICompilationRootProvider> _compilationRoots = Array.Empty<ICompilationRootProvider>();
protected OptimizationMode _optimizationMode = OptimizationMode.None;

public CompilationBuilder(CompilerTypeSystemContext context, CompilationModuleGroup compilationGroup, NameMangler nameMangler)
{
_context = context;
_compilationGroup = compilationGroup;
_nameMangler = nameMangler;
InitializePartial();
}

// Partial class specific initialization
partial void InitializePartial();

public CompilationBuilder UseLogger(Logger logger)
{
_logger = logger;
return this;
}

public CompilationBuilder UseCompilationUnitPrefix(string prefix)
{
_nameMangler.CompilationUnitPrefix = prefix;
return this;
}

public CompilationBuilder UseDependencyTracking(DependencyTrackingLevel trackingLevel)
{
_dependencyTrackingLevel = trackingLevel;
return this;
}

public CompilationBuilder UseCompilationRoots(IEnumerable<ICompilationRootProvider> compilationRoots)
{
_compilationRoots = compilationRoots;
return this;
}

public CompilationBuilder UseOptimizationMode(OptimizationMode mode)
{
_optimizationMode = mode;
return this;
}

public abstract CompilationBuilder UseBackendOptions(IEnumerable<string> options);

public abstract CompilationBuilder UseILProvider(ILProvider ilProvider);

protected abstract ILProvider GetILProvider();

protected DependencyAnalyzerBase<NodeFactory> CreateDependencyGraph(NodeFactory factory, IComparer<DependencyNodeCore<NodeFactory>> comparer = null)
{
return _dependencyTrackingLevel.CreateDependencyGraph(factory, comparer);
}

public abstract ICompilation ToCompilation();
}

/// <summary>
/// Represents the level of optimizations performed by the compiler.
/// </summary>
public enum OptimizationMode
{
/// <summary>
/// Do not optimize.
/// </summary>
None,

/// <summary>
/// Minimize code space.
/// </summary>
PreferSize,

/// <summary>
/// Generate blended code. (E.g. favor size for rarely executed code such as class constructors.)
/// </summary>
Blended,

/// <summary>
/// Maximize execution speed.
/// </summary>
PreferSpeed,
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Internal.TypeSystem;

namespace ILCompiler
{
public abstract partial class CompilationModuleGroup
{
/// <summary>
/// If true, "type" is in the set of input assemblies being compiled
/// </summary>
public abstract bool ContainsType(TypeDesc type);
/// <summary>
/// If true, "method" is in the set of input assemblies being compiled
/// </summary>
public abstract bool ContainsMethodBody(MethodDesc method, bool unboxingStub);
/// <summary>
/// Decide whether a given call may get inlined by JIT.
/// </summary>
/// <param name="callerMethod">Calling method the assembly code of is about to receive the callee code</param>
/// <param name="calleeMethod">The called method to be inlined into the caller</param>
public virtual bool CanInline(MethodDesc callerMethod, MethodDesc calleeMethod) => true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Internal.TypeSystem;

using Debug = System.Diagnostics.Debug;

namespace ILCompiler
{
// Validates types to the extent that is required to make sure the compilation won't fail
// in unpredictable spots.
partial class CompilerTypeSystemContext
{
/// <summary>
/// Ensures that the type can be fully loaded. The method will throw one of the type system
/// exceptions if the type is not loadable.
/// </summary>
public void EnsureLoadableType(TypeDesc type)
{
_validTypes.GetOrCreateValue(type);
}

class ValidTypeHashTable : LockFreeReaderHashtable<TypeDesc, TypeDesc>
{
protected override bool CompareKeyToValue(TypeDesc key, TypeDesc value) => key == value;
protected override bool CompareValueToValue(TypeDesc value1, TypeDesc value2) => value1 == value2;
protected override TypeDesc CreateValueFromKey(TypeDesc key) => EnsureLoadableTypeUncached(key);
protected override int GetKeyHashCode(TypeDesc key) => key.GetHashCode();
protected override int GetValueHashCode(TypeDesc value) => value.GetHashCode();
}
private readonly ValidTypeHashTable _validTypes = new ValidTypeHashTable();

private static TypeDesc EnsureLoadableTypeUncached(TypeDesc type)
{
if (type.IsParameterizedType)
{
// Validate parameterized types
var parameterizedType = (ParameterizedType)type;

TypeDesc parameterType = parameterizedType.ParameterType;

// Make sure type of the parameter is loadable.
((CompilerTypeSystemContext)type.Context).EnsureLoadableType(parameterType);

// Validate we're not constructing a type over a ByRef
if (parameterType.IsByRef)
{
// CLR compat note: "ldtoken int32&&" will actually fail with a message about int32&; "ldtoken int32&[]"
// will fail with a message about being unable to create an array of int32&. This is a middle ground.
ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadGeneral, type);
}

// Validate the parameter is not an uninstantiated generic.
if (parameterType.IsGenericDefinition)
{
ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadGeneral, type);
}

if (parameterizedType.IsArray)
{
if (parameterType.IsFunctionPointer)
{
// Arrays of function pointers are not currently supported
ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadGeneral, type);
}

LayoutInt elementSize = parameterType.GetElementSize();
if (!elementSize.IsIndeterminate && elementSize.AsInt >= ushort.MaxValue)
{
// Element size over 64k can't be encoded in the GCDesc
ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadValueClassTooLarge, parameterType);
}

if (((ArrayType)parameterizedType).Rank > 32)
{
ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadRankTooLarge, type);
}

if (parameterType.IsByRefLike)
{
// Arrays of byref-like types are not allowed
ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadGeneral, type);
}

// It might seem reasonable to disallow array of void, but the CLR doesn't prevent that too hard.
// E.g. "newarr void" will fail, but "newarr void[]" or "ldtoken void[]" will succeed.
}
}
else if (type.IsFunctionPointer)
{
ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadGeneral, type);
}
else
{
// Validate classes, structs, enums, interfaces, and delegates
Debug.Assert(type.IsDefType);

// Don't validate generic definitons
if (type.IsGenericDefinition)
{
return type;
}

// System.__Canon or System.__UniversalCanon
if (type.IsCanonicalDefinitionType(CanonicalFormKind.Any))
{
return type;
}

// We need to be able to load interfaces
foreach (var intf in type.RuntimeInterfaces)
{
((CompilerTypeSystemContext)type.Context).EnsureLoadableType(intf.NormalizeInstantiation());
}

var defType = (DefType)type;

// Ensure we can compute the type layout
defType.ComputeInstanceLayout(InstanceLayoutKind.TypeAndFields);
defType.ComputeStaticFieldLayout(StaticLayoutKind.StaticRegionSizesAndFields);

// Make sure instantiation length matches the expectation
if (defType.Instantiation.Length != defType.GetTypeDefinition().Instantiation.Length)
{
ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadGeneral, type);
}

foreach (TypeDesc typeArg in defType.Instantiation)
{
// ByRefs, pointers, function pointers, and System.Void are never valid instantiation arguments
if (typeArg.IsByRef
|| typeArg.IsPointer
|| typeArg.IsFunctionPointer
|| typeArg.IsVoid
|| typeArg.IsByRefLike)
{
ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadGeneral, type);
}

// TODO: validate constraints
}

// Check the type doesn't have bogus MethodImpls or overrides and we can get the finalizer.
defType.GetFinalizer();
}

return type;
}
}
}
Loading

0 comments on commit ac857a2

Please sign in to comment.