diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/NoMethodsCompilationModuleGroup.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/NoMethodsCompilationModuleGroup.cs
new file mode 100644
index 00000000000000..cc97f72a952613
--- /dev/null
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/NoMethodsCompilationModuleGroup.cs
@@ -0,0 +1,51 @@
+// 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.Collections.Generic;
+using Internal.ReadyToRunConstants;
+using Internal.TypeSystem;
+using Internal.TypeSystem.Ecma;
+
+namespace ILCompiler
+{
+ ///
+ /// A compilation group that only contains no methods. Used for creating an R2R image without
+ /// any method compiled into it. Needed for handling inputbubble scenarios where a dependent
+ /// assembly should not be R2R'd.
+ ///
+ public class NoMethodsCompilationModuleGroup : ReadyToRunCompilationModuleGroupBase
+ {
+ public NoMethodsCompilationModuleGroup(
+ TypeSystemContext context,
+ bool isCompositeBuildMode,
+ bool isInputBubble,
+ IEnumerable compilationModuleSet,
+ IEnumerable versionBubbleModuleSet,
+ bool compileGenericDependenciesFromVersionBubbleModuleSet) :
+ base(context,
+ isCompositeBuildMode,
+ isInputBubble,
+ compilationModuleSet,
+ versionBubbleModuleSet,
+ compileGenericDependenciesFromVersionBubbleModuleSet)
+ {
+ }
+
+ public override bool ContainsMethodBody(MethodDesc method, bool unboxingStub)
+ {
+ return false;
+ }
+
+ public override void ApplyProfilerGuidedCompilationRestriction(ProfileDataManager profileGuidedCompileRestriction)
+ {
+ return;
+ }
+
+ public override ReadyToRunFlags GetReadyToRunFlags()
+ {
+ // Partial by definition.
+ return ReadyToRunFlags.READYTORUN_FLAG_Partial;
+ }
+ }
+}
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs
index 5baf77fe2a38e1..a03c94d68f4997 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.IO;
using System.Reflection.PortableExecutable;
using System.Runtime.CompilerServices;
@@ -227,6 +228,7 @@ public sealed class ReadyToRunCodegenCompilation : Compilation
private bool _generateMapFile;
public ReadyToRunSymbolNodeFactory SymbolNodeFactory { get; }
+ public ReadyToRunCompilationModuleGroupBase CompilationModuleGroup { get; }
internal ReadyToRunCodegenCompilation(
DependencyAnalyzerBase dependencyGraph,
@@ -256,6 +258,7 @@ internal ReadyToRunCodegenCompilation(
SymbolNodeFactory = new ReadyToRunSymbolNodeFactory(nodeFactory);
_corInfoImpls = new ConditionalWeakTable();
_inputFiles = inputFiles;
+ CompilationModuleGroup = (ReadyToRunCompilationModuleGroupBase)nodeFactory.CompilationModuleGroup;
// Generate baseline support specification for InstructionSetSupport. This will prevent usage of the generated
// code if the runtime environment doesn't support the specified instruction set
@@ -333,9 +336,86 @@ public override void WriteDependencyLog(string outputFileName)
}
}
- internal bool IsInheritanceChainLayoutFixedInCurrentVersionBubble(TypeDesc type)
+ public bool IsLayoutFixedInCurrentVersionBubble(TypeDesc type)
{
- // TODO: implement
+ // Primitive types and enums have fixed layout
+ if (type.IsPrimitive || type.IsEnum)
+ {
+ return true;
+ }
+
+ if (!(type is MetadataType defType))
+ {
+ // Non metadata backed types have layout defined in all version bubbles
+ return true;
+ }
+
+ if (!NodeFactory.CompilationModuleGroup.VersionsWithModule(defType.Module))
+ {
+ if (!type.IsValueType)
+ {
+ // Eventually, we may respect the non-versionable attribute for reference types too. For now, we are going
+ // to play it safe and ignore it.
+ return false;
+ }
+
+ // Valuetypes with non-versionable attribute are candidates for fixed layout. Reject the rest.
+ return type is MetadataType metadataType && metadataType.IsNonVersionable();
+ }
+
+ // If the above condition passed, check that all instance fields have fixed layout as well. In particular,
+ // it is important for generic types with non-versionable layout (e.g. Nullable)
+ foreach (var field in type.GetFields())
+ {
+ // Only instance fields matter here
+ if (field.IsStatic)
+ continue;
+
+ var fieldType = field.FieldType;
+ if (!fieldType.IsValueType)
+ continue;
+
+ if (!IsLayoutFixedInCurrentVersionBubble(fieldType))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public bool IsInheritanceChainLayoutFixedInCurrentVersionBubble(TypeDesc type)
+ {
+ // This method is not expected to be called for value types
+ Debug.Assert(!type.IsValueType);
+
+ if (type.IsObject)
+ return true;
+
+ if (!IsLayoutFixedInCurrentVersionBubble(type))
+ {
+ return false;
+ }
+
+ type = type.BaseType;
+
+ if (type != null)
+ {
+ // If there are multiple inexact compilation units in the layout of the type, then the exact offset
+ // of a derived given field is unknown as there may or may not be alignment inserted between a type and its base
+ if (CompilationModuleGroup.TypeLayoutCompilationUnits(type).HasMultipleInexactCompilationUnits)
+ return false;
+
+ while (!type.IsObject && type != null)
+ {
+ if (!IsLayoutFixedInCurrentVersionBubble(type))
+ {
+ return false;
+ }
+ type = type.BaseType;
+ }
+ }
+
return true;
}
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs
index 72ce7fae981048..a889d469051b09 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs
@@ -34,7 +34,7 @@ public sealed class ReadyToRunCodegenCompilationBuilder : CompilationBuilder
private KeyValuePair[] _ryujitOptions = Array.Empty>();
private ILProvider _ilProvider = new ReadyToRunILProvider();
- public ReadyToRunCodegenCompilationBuilder(CompilerTypeSystemContext context, CompilationModuleGroup group, IEnumerable inputFiles)
+ public ReadyToRunCodegenCompilationBuilder(CompilerTypeSystemContext context, ReadyToRunCompilationModuleGroupBase group, IEnumerable inputFiles)
: base(context, group, new CoreRTNameMangler())
{
_inputFiles = inputFiles;
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCompilationModuleGroupBase.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCompilationModuleGroupBase.cs
index 7d55bc55e32b47..7524c5089523b5 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCompilationModuleGroupBase.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCompilationModuleGroupBase.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System;
+using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using Internal.TypeSystem;
@@ -21,9 +22,11 @@ public abstract class ReadyToRunCompilationModuleGroupBase : CompilationModuleGr
private readonly bool _compileGenericDependenciesFromVersionBubbleModuleSet;
private readonly bool _isCompositeBuildMode;
private readonly bool _isInputBubble;
- private readonly ConcurrentDictionary _containsTypeLayoutCache = new ConcurrentDictionary();
+ private readonly ConcurrentDictionary _layoutCompilationUnits = new ConcurrentDictionary();
private readonly ConcurrentDictionary _versionsWithTypeCache = new ConcurrentDictionary();
private readonly ConcurrentDictionary _versionsWithMethodCache = new ConcurrentDictionary();
+ private readonly Dictionary _moduleCompilationUnits = new Dictionary();
+ private CompilationUnitIndex _nextCompilationUnit = CompilationUnitIndex.FirstDynamicallyAssigned;
public ReadyToRunCompilationModuleGroupBase(
TypeSystemContext context,
@@ -69,15 +72,160 @@ protected bool CompileVersionBubbleGenericsIntoCurrentModule(MethodDesc method)
return true;
}
- ///
- /// If true, the type is fully contained in the current compilation group.
- ///
- public override bool ContainsTypeLayout(TypeDesc type)
+ public CompilationUnitSet TypeLayoutCompilationUnits(TypeDesc type)
{
- return _containsTypeLayoutCache.GetOrAdd(type, ContainsTypeLayoutUncached);
+ return _layoutCompilationUnits.GetOrAdd(type, TypeLayoutCompilationUnitsUncached);
}
- private bool ContainsTypeLayoutUncached(TypeDesc type)
+ private enum CompilationUnitIndex
+ {
+ RESERVEDForHasMultipleInexactCompilationUnits = 0,
+ RESERVEDForHasMultipleCompilationUnits = 1,
+ First = 2,
+ Current = 2,
+ OutsideOfVersionBubble = 3,
+ FirstDynamicallyAssigned = 4,
+ }
+
+ // Compilation Unit Index is the compilation unit of a given module. If the compilation unit
+ // is unknown the module will be given an independent index from other modules, but
+ // IsCompilationUnitIndexExact will return false for that index. All compilation unit indices
+ // are >= 2, to allow for 0 and 1 to be sentinel values.
+ private CompilationUnitIndex ModuleToCompilationUnitIndex(ModuleDesc nonEcmaModule)
+ {
+ EcmaModule module = (EcmaModule)nonEcmaModule;
+ if (IsModuleInCompilationGroup(module))
+ return CompilationUnitIndex.Current;
+
+ if (!VersionsWithModule(module))
+ return CompilationUnitIndex.OutsideOfVersionBubble;
+
+ // Assemblies within the version bubble, but not compiled as part of this compilation unit are given
+ // unique seperate compilation units. The practical effect of this is that the compiler can assume that
+ // types which are entirely defined in one module can be laid out in an optimal fashion, but types
+ // which are laid out relying on multiple modules cannot have their type layout precisely known as
+ // it is unknown if the modules are bounding into a single composite image or into individual assemblies.
+ lock (_moduleCompilationUnits)
+ {
+ if (!_moduleCompilationUnits.TryGetValue(module, out CompilationUnitIndex compilationUnit))
+ {
+ compilationUnit = _nextCompilationUnit;
+ _nextCompilationUnit = (CompilationUnitIndex)(((int)_nextCompilationUnit) + 1);
+ _moduleCompilationUnits.Add(module, compilationUnit);
+ }
+
+ return compilationUnit;
+ }
+ }
+
+ // Indicate whether or not the compiler can take a hard dependency on the meaning of
+ // the compilation unit index.
+ private bool IsCompilationUnitIndexExact(CompilationUnitIndex compilationUnitIndex)
+ {
+ // Currently the implementation is only allowed to assume 2 details.
+ // 1. That any assembly which is compiled with inputbubble set shall have its entire set of dependencies compiled as R2R
+ // 2. That any assembly which is compiled in the current process may be considered to be part of a single unit.
+ //
+ // At some point, the compiler could take new parameters to allow the compiler to know that assemblies not in the current compilation
+ // unit are to be compiled into composite images or into seperate binaries, and this helper function could return true for these other
+ // compilation unit shapes.
+ if (compilationUnitIndex != CompilationUnitIndex.Current)
+ return false;
+ else
+ return true;
+ }
+
+ public struct CompilationUnitSet
+ {
+ private BitArray _bits;
+
+ public CompilationUnitSet(ReadyToRunCompilationModuleGroupBase compilationGroup, ModuleDesc module)
+ {
+ CompilationUnitIndex compilationIndex = compilationGroup.ModuleToCompilationUnitIndex(module);
+ _bits = new BitArray(((int)compilationIndex) + 1);
+ _bits.Set((int)compilationIndex, true);
+ }
+
+ public bool HasMultipleInexactCompilationUnits
+ {
+ get
+ {
+ if (_bits == null)
+ return false;
+
+ return _bits[(int)CompilationUnitIndex.RESERVEDForHasMultipleInexactCompilationUnits];
+ }
+ }
+
+ public bool HasMultipleCompilationUnits
+ {
+ get
+ {
+ if (_bits == null)
+ return false;
+
+ return _bits[(int)CompilationUnitIndex.RESERVEDForHasMultipleCompilationUnits];
+ }
+ }
+
+ public void UnionWith(ReadyToRunCompilationModuleGroupBase compilationGroup, CompilationUnitSet other)
+ {
+ if (other._bits == null)
+ return;
+
+ if (HasMultipleInexactCompilationUnits)
+ return;
+
+ if (other.HasMultipleInexactCompilationUnits)
+ {
+ _bits[(int)CompilationUnitIndex.RESERVEDForHasMultipleCompilationUnits] = true;
+ _bits[(int)CompilationUnitIndex.RESERVEDForHasMultipleInexactCompilationUnits] = true;
+ return;
+ }
+
+ if (other._bits.Length > _bits.Length)
+ _bits.Length = other._bits.Length;
+
+ if (other._bits.Length < _bits.Length)
+ {
+ for (int i = 0; i < other._bits.Length; i++)
+ {
+ if (other._bits[i])
+ _bits[i] = true;
+ }
+ }
+ else
+ {
+ _bits.Or(other._bits);
+ }
+
+ int inexactCompilationUnitCount = 0;
+ int compilationUnitCount = 0;
+ for (int i = (int)CompilationUnitIndex.First; i < _bits.Length; i++)
+ {
+ if (_bits[i])
+ {
+ if (!compilationGroup.IsCompilationUnitIndexExact((CompilationUnitIndex)i))
+ inexactCompilationUnitCount++;
+
+ compilationUnitCount++;
+ }
+ if (compilationUnitCount == 2)
+ {
+ // Multiple compilation units found
+ _bits[(int)CompilationUnitIndex.RESERVEDForHasMultipleCompilationUnits] = true;
+ }
+ if (inexactCompilationUnitCount == 2)
+ {
+ // Multiple inexact compilation units involved
+ _bits[(int)CompilationUnitIndex.RESERVEDForHasMultipleInexactCompilationUnits] = true;
+ break;
+ }
+ }
+ }
+ }
+
+ private CompilationUnitSet TypeLayoutCompilationUnitsUncached(TypeDesc type)
{
if (type.IsObject ||
type.IsPrimitive ||
@@ -86,17 +234,18 @@ private bool ContainsTypeLayoutUncached(TypeDesc type)
type.IsFunctionPointer ||
type.IsCanonicalDefinitionType(CanonicalFormKind.Any))
{
- return true;
+ return default(CompilationUnitSet);
}
+
var defType = (MetadataType)type;
- if (!ContainsType(defType))
- {
- return false;
- }
- if (!defType.IsValueType && !ContainsTypeLayout(defType.BaseType))
+
+ CompilationUnitSet moduleDependencySet = new CompilationUnitSet(this, defType.Module);
+
+ if ((type.BaseType != null) && !type.BaseType.IsObject && !type.IsValueType)
{
- return false;
+ moduleDependencySet.UnionWith(this, TypeLayoutCompilationUnits(type.BaseType));
}
+
foreach (FieldDesc field in defType.GetFields())
{
if (field.IsStatic)
@@ -105,13 +254,29 @@ private bool ContainsTypeLayoutUncached(TypeDesc type)
TypeDesc fieldType = field.FieldType;
if (fieldType.IsValueType &&
- !ContainsTypeLayout(fieldType))
+ !fieldType.IsPrimitive)
{
- return false;
+ moduleDependencySet.UnionWith(this, TypeLayoutCompilationUnits((MetadataType)fieldType));
}
}
- return true;
+ return moduleDependencySet;
+ }
+
+ private bool ModuleMatchesCompilationUnitIndex(ModuleDesc module1, ModuleDesc module2)
+ {
+ return ModuleToCompilationUnitIndex(module1) == ModuleToCompilationUnitIndex(module2);
+ }
+
+ public bool NeedsAlignmentBetweenBaseTypeAndDerived(MetadataType baseType, MetadataType derivedType)
+ {
+ if (!ModuleMatchesCompilationUnitIndex(derivedType.Module, baseType.Module) ||
+ TypeLayoutCompilationUnits(baseType).HasMultipleCompilationUnits)
+ {
+ return true;
+ }
+
+ return false;
}
public sealed override bool VersionsWithModule(ModuleDesc module)
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCompilerContext.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCompilerContext.cs
index 8a443acefbdf54..5f2d1663ff5cdd 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCompilerContext.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCompilerContext.cs
@@ -67,7 +67,7 @@ public override FieldLayoutAlgorithm GetLayoutAlgorithmForType(DefType type)
}
}
- public void SetCompilationGroup(CompilationModuleGroup compilationModuleGroup)
+ public void SetCompilationGroup(ReadyToRunCompilationModuleGroupBase compilationModuleGroup)
{
_r2rFieldLayoutAlgorithm.SetCompilationGroup(compilationModuleGroup);
}
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunMetadataFieldLayoutAlgorithm.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunMetadataFieldLayoutAlgorithm.cs
index 5079e20cd04560..f19140fde558a3 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunMetadataFieldLayoutAlgorithm.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunMetadataFieldLayoutAlgorithm.cs
@@ -27,7 +27,7 @@ internal class ReadyToRunMetadataFieldLayoutAlgorithm : MetadataFieldLayoutAlgor
///
/// Compilation module group is used to identify which types extend beyond the current version bubble.
///
- private CompilationModuleGroup _compilationGroup;
+ private ReadyToRunCompilationModuleGroupBase _compilationGroup;
public ReadyToRunMetadataFieldLayoutAlgorithm()
{
@@ -38,7 +38,7 @@ public ReadyToRunMetadataFieldLayoutAlgorithm()
/// Set up compilation group needed for proper calculation of base class alignment in auto layout.
///
///
- public void SetCompilationGroup(CompilationModuleGroup compilationGroup)
+ public void SetCompilationGroup(ReadyToRunCompilationModuleGroupBase compilationGroup)
{
_compilationGroup = compilationGroup;
}
@@ -822,17 +822,9 @@ protected override void AlignBaseOffsetIfNecessary(MetadataType type, ref Layout
return;
}
- if (_compilationGroup.ContainsType(baseType))
+ if (!_compilationGroup.NeedsAlignmentBetweenBaseTypeAndDerived(baseType: (MetadataType)baseType, derivedType: type))
{
- if (_compilationGroup.ContainsTypeLayout(baseType))
- {
- // The type is defined in the module that's currently being compiled and the type layout doesn't depend on other modules
- return;
- }
- }
- else if (_compilationGroup.VersionsWithType(baseType))
- {
- // The baseType is in the current version bubble, but in a module different from the one that's currently being compiled
+ // The type is defined in the module that's currently being compiled and the type layout doesn't depend on other modules
return;
}
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj
index f36eb5fd382cdf..8d78625a2beaba 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj
@@ -198,6 +198,7 @@
+
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs
index 433b69a0d56156..d976b8e7ce110f 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs
@@ -1914,30 +1914,6 @@ private void embedGenericHandle(ref CORINFO_RESOLVED_TOKEN pResolvedToken, bool
throw new RequiresRuntimeJitException("embedMethodHandle: " + methodDesc.ToString());
}
- private bool IsLayoutFixedInCurrentVersionBubble(TypeDesc type)
- {
- // Primitive types and enums have fixed layout
- if (type.IsPrimitive || type.IsEnum)
- {
- return true;
- }
-
- if (!_compilation.NodeFactory.CompilationModuleGroup.VersionsWithType(type))
- {
- if (!type.IsValueType)
- {
- // Eventually, we may respect the non-versionable attribute for reference types too. For now, we are going
- // to play it safe and ignore it.
- return false;
- }
-
- // Valuetypes with non-versionable attribute are candidates for fixed layout. Reject the rest.
- return type is MetadataType metadataType && metadataType.IsNonVersionable();
- }
-
- return true;
- }
-
private bool NeedsTypeLayoutCheck(TypeDesc type)
{
if (!type.IsDefType)
@@ -1946,27 +1922,7 @@ private bool NeedsTypeLayoutCheck(TypeDesc type)
if (!type.IsValueType)
return false;
- return !IsLayoutFixedInCurrentVersionBubble(type);
- }
-
- ///
- /// Is field layout of the inheritance chain fixed within the current version bubble?
- ///
- private bool IsInheritanceChainLayoutFixedInCurrentVersionBubble(TypeDesc type)
- {
- // This method is not expected to be called for value types
- Debug.Assert(!type.IsValueType);
-
- while (!type.IsObject && type != null)
- {
- if (!IsLayoutFixedInCurrentVersionBubble(type))
- {
- return false;
- }
- type = type.BaseType;
- }
-
- return true;
+ return !_compilation.IsLayoutFixedInCurrentVersionBubble(type);
}
private bool HasLayoutMetadata(TypeDesc type)
@@ -2002,14 +1958,13 @@ private void EncodeFieldBaseOffset(FieldDesc field, CORINFO_FIELD_INFO* pResult,
{
// No-op except for instance fields
}
- else if (!IsLayoutFixedInCurrentVersionBubble(pMT))
+ else if (!_compilation.IsLayoutFixedInCurrentVersionBubble(pMT))
{
if (pMT.IsValueType)
{
// ENCODE_CHECK_FIELD_OFFSET
- pResult->offset = 0;
- pResult->fieldAccessor = CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_INSTANCE_WITH_BASE;
- pResult->fieldLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.CheckFieldOffset(field));
+ _methodCodeNode.Fixups.Add(_compilation.SymbolNodeFactory.CheckFieldOffset(field));
+ // No-op other than generating the check field offset fixup
}
else
{
@@ -2025,7 +1980,7 @@ private void EncodeFieldBaseOffset(FieldDesc field, CORINFO_FIELD_INFO* pResult,
{
// ENCODE_NONE
}
- else if (IsInheritanceChainLayoutFixedInCurrentVersionBubble(pMT.BaseType))
+ else if (_compilation.IsInheritanceChainLayoutFixedInCurrentVersionBubble(pMT.BaseType))
{
// ENCODE_NONE
}
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/ReadyToRunReader.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/ReadyToRunReader.cs
index 3683fe906f9d44..651c0cc36ac591 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/ReadyToRunReader.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/ReadyToRunReader.cs
@@ -72,6 +72,7 @@ public sealed class ReadyToRunReader
private OperatingSystem _operatingSystem;
private Machine _machine;
private Architecture _architecture;
+ private int _pointerSize;
private bool _composite;
private ulong _imageBase;
private int _readyToRunHeaderRVA;
@@ -174,6 +175,18 @@ public Architecture Architecture
}
}
+ ///
+ /// Size of a pointer on the architecture
+ ///
+ public int TargetPointerSize
+ {
+ get
+ {
+ EnsureHeader();
+ return _pointerSize;
+ }
+ }
+
///
/// Return true when the executable is a composite R2R image.
///
@@ -476,20 +489,24 @@ private unsafe void EnsureHeader()
{
case Machine.I386:
_architecture = Architecture.X86;
+ _pointerSize = 4;
break;
case Machine.Amd64:
_architecture = Architecture.X64;
+ _pointerSize = 8;
break;
case Machine.Arm:
case Machine.Thumb:
case Machine.ArmThumb2:
_architecture = Architecture.Arm;
+ _pointerSize = 4;
break;
case Machine.Arm64:
_architecture = Architecture.Arm64;
+ _pointerSize = 8;
break;
default:
@@ -712,7 +729,7 @@ private void ParseInstanceMethodEntrypoints(bool[] isEntryPoint)
if ((methodFlags & (uint)ReadyToRunMethodSigFlags.READYTORUN_METHOD_SIG_OwnerType) != 0)
{
mdReader = decoder.GetMetadataReaderFromModuleOverride() ?? mdReader;
- if (_composite)
+ if ((_composite) && mdReader == null)
{
// The only types that don't have module overrides on them in composite images are primitive types within the system module
mdReader = GetSystemModuleMetadataReader();
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/ReadyToRunSignature.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/ReadyToRunSignature.cs
index 8da2119e58fbb3..355af566a46b86 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/ReadyToRunSignature.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/ReadyToRunSignature.cs
@@ -831,12 +831,44 @@ private void ParseSignature(ReadyToRunFixupKind fixupType, StringBuilder builder
case ReadyToRunFixupKind.Check_TypeLayout:
ParseType(builder);
+ ReadyToRunTypeLayoutFlags layoutFlags = (ReadyToRunTypeLayoutFlags)ReadUInt();
+ builder.Append($" Flags {layoutFlags}");
+ int actualSize = (int)ReadUInt();
+ builder.Append($" Size {actualSize}");
+
+ if (layoutFlags.HasFlag(ReadyToRunTypeLayoutFlags.READYTORUN_LAYOUT_HFA))
+ {
+ builder.Append($" HFAType {ReadUInt()}");
+ }
+
+ if (layoutFlags.HasFlag(ReadyToRunTypeLayoutFlags.READYTORUN_LAYOUT_Alignment))
+ {
+ if (!layoutFlags.HasFlag(ReadyToRunTypeLayoutFlags.READYTORUN_LAYOUT_Alignment_Native))
+ {
+ builder.Append($" Align {ReadUInt()}");
+ }
+ }
+
+ if (layoutFlags.HasFlag(ReadyToRunTypeLayoutFlags.READYTORUN_LAYOUT_GCLayout))
+ {
+ if (!layoutFlags.HasFlag(ReadyToRunTypeLayoutFlags.READYTORUN_LAYOUT_GCLayout_Empty))
+ {
+ int cbGCRefMap = (actualSize / _contextReader.TargetPointerSize + 7) / 8;
+ builder.Append(" GCLayout ");
+ for (int i = 0; i < cbGCRefMap; i++)
+ {
+ builder.Append(ReadByte().ToString("X"));
+ }
+ }
+ }
+
builder.Append(" (CHECK_TYPE_LAYOUT)");
break;
case ReadyToRunFixupKind.Check_FieldOffset:
- builder.Append("CHECK_FIELD_OFFSET");
- // TODO
+ builder.Append($"{ReadUInt()} ");
+ ParseField(builder);
+ builder.Append(" (CHECK_FIELD_OFFSET)");
break;
case ReadyToRunFixupKind.Check_InstructionSetSupport:
diff --git a/src/coreclr/src/tools/crossgen2/crossgen2/CommandLineOptions.cs b/src/coreclr/src/tools/crossgen2/crossgen2/CommandLineOptions.cs
index 4fa9271d1c20cc..534bec5b6970f9 100644
--- a/src/coreclr/src/tools/crossgen2/crossgen2/CommandLineOptions.cs
+++ b/src/coreclr/src/tools/crossgen2/crossgen2/CommandLineOptions.cs
@@ -23,6 +23,7 @@ public class CommandLineOptions
public bool CompileBubbleGenerics { get; set; }
public bool Verbose { get; set; }
public bool Composite { get; set; }
+ public bool CompileNoMethods { get; set; }
public FileInfo DgmlLogFileName { get; set; }
public bool GenerateFullDgmlLog { get; set; }
@@ -100,6 +101,7 @@ public static Command RootCommand()
new Option(new[] { "--optimize-time", "--Ot" }, SR.OptimizeSpeedOption),
new Option(new[] { "--inputbubble" }, SR.InputBubbleOption),
new Option(new[] { "--composite" }, SR.CompositeBuildMode),
+ new Option(new[] { "--compile-no-methods" }, SR.CompileNoMethodsOption),
new Option(new[] { "--tuning" }, SR.TuningImageOption)
{
Argument = new Argument()
diff --git a/src/coreclr/src/tools/crossgen2/crossgen2/Program.cs b/src/coreclr/src/tools/crossgen2/crossgen2/Program.cs
index d6f98eb7d905b7..72843451e10e26 100644
--- a/src/coreclr/src/tools/crossgen2/crossgen2/Program.cs
+++ b/src/coreclr/src/tools/crossgen2/crossgen2/Program.cs
@@ -400,6 +400,16 @@ private int Run()
singleMethod);
compilationRoots.Add(new SingleMethodRootProvider(singleMethod));
}
+ else if (_commandLineOptions.CompileNoMethods)
+ {
+ compilationGroup = new NoMethodsCompilationModuleGroup(
+ typeSystemContext,
+ _commandLineOptions.Composite,
+ _commandLineOptions.InputBubble,
+ inputModules,
+ versionBubbleModules,
+ _commandLineOptions.CompileBubbleGenerics);
+ }
else
{
// Single assembly compilation.
@@ -428,9 +438,9 @@ private int Run()
else
compilationGroup.ApplyProfilerGuidedCompilationRestriction(null);
- if (singleMethod == null)
+ if ((singleMethod == null) && !_commandLineOptions.CompileNoMethods)
{
- // For non-single-method compilations add compilation roots.
+ // For normal compilations add compilation roots.
foreach (var module in rootingModules)
{
compilationRoots.Add(new ReadyToRunRootProvider(
diff --git a/src/coreclr/src/tools/crossgen2/crossgen2/Properties/Resources.resx b/src/coreclr/src/tools/crossgen2/crossgen2/Properties/Resources.resx
index f809bfa1a8879b..3bd33829741079 100644
--- a/src/coreclr/src/tools/crossgen2/crossgen2/Properties/Resources.resx
+++ b/src/coreclr/src/tools/crossgen2/crossgen2/Properties/Resources.resx
@@ -138,6 +138,9 @@
True when the entire input forms a version bubble (default = per-assembly bubble)
+
+ True to skip compiling methods into the R2R image (default = false)
+
Emit a composite R2R image comprising a number of input assemblies
diff --git a/src/coreclr/src/vm/ceeload.cpp b/src/coreclr/src/vm/ceeload.cpp
index dc76c751edc34a..9b9c59449c954d 100644
--- a/src/coreclr/src/vm/ceeload.cpp
+++ b/src/coreclr/src/vm/ceeload.cpp
@@ -3374,15 +3374,29 @@ BOOL Module::IsInSameVersionBubble(Module *target)
return FALSE;
}
- // Check if the current module's image has native manifest metadata, otherwise the current->GetNativeAssemblyImport() asserts.
- COUNT_T cMeta=0;
- const void* pMeta = GetFile()->GetOpenedILimage()->GetNativeManifestMetadata(&cMeta);
- if (pMeta == NULL)
+ NativeImage *nativeImage = this->GetCompositeNativeImage();
+ IMDInternalImport* pMdImport = NULL;
+
+ if (nativeImage != NULL)
{
- return FALSE;
+ if (nativeImage == target->GetCompositeNativeImage())
+ {
+ // Fast path for modules contained within the same native image
+ return TRUE;
+ }
+ pMdImport = nativeImage->GetManifestMetadata();
+ }
+ else
+ {
+ // Check if the current module's image has native manifest metadata, otherwise the current->GetNativeAssemblyImport() asserts.
+ COUNT_T cMeta=0;
+ const void* pMeta = GetFile()->GetOpenedILimage()->GetNativeManifestMetadata(&cMeta);
+ if (pMeta == NULL)
+ {
+ return FALSE;
+ }
+ pMdImport = GetNativeAssemblyImport();
}
-
- IMDInternalImport* pMdImport = GetNativeAssemblyImport();
LPCUTF8 targetName = target->GetAssembly()->GetSimpleName();
diff --git a/src/coreclr/src/vm/methodtablebuilder.cpp b/src/coreclr/src/vm/methodtablebuilder.cpp
index 14ccfd4371061d..5f389b12865fce 100644
--- a/src/coreclr/src/vm/methodtablebuilder.cpp
+++ b/src/coreclr/src/vm/methodtablebuilder.cpp
@@ -11226,6 +11226,21 @@ VOID MethodTableBuilder::CheckForSpecialTypes()
}
#ifdef FEATURE_READYTORUN
+
+bool ModulesAreDistributedAsAnIndivisibleUnit(Module* module1, Module* module2)
+{
+ if (module1 == module2)
+ return true;
+
+ bool nativeImagesIdentical = false;
+ if (module1->GetCompositeNativeImage() != NULL)
+ {
+ return module1->GetCompositeNativeImage() == module2->GetCompositeNativeImage();
+ }
+
+ return false;
+}
+
//*******************************************************************************
VOID MethodTableBuilder::CheckLayoutDependsOnOtherModules(MethodTable * pDependencyMT)
{
@@ -11237,20 +11252,18 @@ VOID MethodTableBuilder::CheckLayoutDependsOnOtherModules(MethodTable * pDepende
//
// WARNING: Changes in this algorithm are potential ReadyToRun breaking changes !!!
//
- // Track whether field layout of this type depend on information outside its containing module
+ // Track whether field layout of this type depend on information outside its containing module and compilation unit
//
// It is a stronger condition than MethodTable::IsInheritanceChainLayoutFixedInCurrentVersionBubble().
// It has to remain fixed accross versioning changes in the module dependencies. In particular, it does
// not take into account NonVersionable attribute. Otherwise, adding NonVersionable attribute to existing
// type would be ReadyToRun incompatible change.
//
- if (pDependencyMT->GetModule() == GetModule())
- {
- if (!pDependencyMT->GetClass()->HasLayoutDependsOnOtherModules())
- return;
- }
+ bool modulesDefinedInSameDistributionUnit = ModulesAreDistributedAsAnIndivisibleUnit(pDependencyMT->GetModule(), GetModule());
+ bool dependsOnOtherModules = !modulesDefinedInSameDistributionUnit || pDependencyMT->GetClass()->HasLayoutDependsOnOtherModules();
- GetHalfBakedClass()->SetHasLayoutDependsOnOtherModules();
+ if (dependsOnOtherModules)
+ GetHalfBakedClass()->SetHasLayoutDependsOnOtherModules();
}
BOOL MethodTableBuilder::NeedsAlignedBaseOffset()
@@ -11274,7 +11287,7 @@ BOOL MethodTableBuilder::NeedsAlignedBaseOffset()
// Always use the ReadyToRun field layout algorithm if the source IL image was ReadyToRun, independent on
// whether ReadyToRun is actually enabled for the module. It is required to allow mixing and matching
- // ReadyToRun images with NGen.
+ // ReadyToRun images with and without input bubble enabled.
if (!GetModule()->GetFile()->IsILImageReadyToRun())
{
// Always use ReadyToRun field layout algorithm to produce ReadyToRun images
@@ -11282,33 +11295,13 @@ BOOL MethodTableBuilder::NeedsAlignedBaseOffset()
return FALSE;
}
- if (pParentMT->GetModule() == GetModule())
- {
- if (!pParentMT->GetClass()->HasLayoutDependsOnOtherModules())
- return FALSE;
- }
- else
+ if (!ModulesAreDistributedAsAnIndivisibleUnit(GetModule(), pParentMT->GetModule()) ||
+ pParentMT->GetClass()->HasLayoutDependsOnOtherModules())
{
-#ifdef FEATURE_READYTORUN_COMPILER
- if (IsReadyToRunCompilation())
- {
- if (pParentMT->GetModule()->IsInCurrentVersionBubble())
- {
- return FALSE;
- }
- }
-#else // FEATURE_READYTORUN_COMPILER
- if (GetModule()->GetFile()->IsILImageReadyToRun())
- {
- if (GetModule()->IsInSameVersionBubble(pParentMT->GetModule()))
- {
- return FALSE;
- }
- }
-#endif // FEATURE_READYTORUN_COMPILER
+ return TRUE;
}
- return TRUE;
+ return FALSE;
}
#endif // FEATURE_READYTORUN
diff --git a/src/coreclr/tests/src/readytorun/crossboundarylayout/a/a.cs b/src/coreclr/tests/src/readytorun/crossboundarylayout/a/a.cs
new file mode 100644
index 00000000000000..271a8f6e15ee21
--- /dev/null
+++ b/src/coreclr/tests/src/readytorun/crossboundarylayout/a/a.cs
@@ -0,0 +1,87 @@
+// 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.Threading;
+
+namespace CrossBoundaryLayout
+{
+ public class A
+ {
+ public byte _aVal;
+ }
+
+ public class AGeneric
+ {
+ public T _aVal;
+ }
+
+ public class ABoringGeneric
+ {
+ public byte _aVal;
+ }
+
+ public class ATest
+ {
+ public static volatile object s_testFailObj;
+ public static void ReportTestFailure(string test, object o, ref int failCount)
+ {
+ Console.WriteLine(test);
+ s_testFailObj = o;
+ failCount++;
+ }
+
+ public static int Test()
+ {
+ int failure = 0;
+ {
+ var a = (A)Activator.CreateInstance(typeof(A));
+ a._aVal = 1;
+ if (1 != (byte)typeof(A).GetField("_aVal").GetValue(a))
+ {
+ ATest.ReportTestFailure("A a._aVal", a, ref failure);
+ }
+ }
+
+ {
+ var a2 = (AGeneric)Activator.CreateInstance(typeof(AGeneric));
+ a2._aVal = 1;
+ if (1 != (byte)typeof(AGeneric).GetField("_aVal").GetValue(a2))
+ {
+ failure++;
+ ATest.ReportTestFailure("A a2_aVal", a2, ref failure);
+ }
+ }
+
+ {
+ var a3 = (AGeneric)Activator.CreateInstance(typeof(AGeneric));
+ a3._aVal._dVal = 1;
+ if (1 != ((ByteStruct)typeof(AGeneric).GetField("_aVal").GetValue(a3))._dVal)
+ {
+ ATest.ReportTestFailure("A a3_aVal", a3, ref failure);
+ }
+ }
+
+ {
+ var a4 = (ABoringGeneric)Activator.CreateInstance(typeof(ABoringGeneric));
+ a4._aVal = 1;
+ if (1 != (byte)typeof(ABoringGeneric).GetField("_aVal").GetValue(a4))
+ {
+ ATest.ReportTestFailure("A a4_aVal", a4, ref failure);
+ }
+ }
+
+ {
+ var a5 = (ABoringGeneric)Activator.CreateInstance(typeof(ABoringGeneric));
+ a5._aVal = 1;
+ if (1 != (byte)typeof(ABoringGeneric).GetField("_aVal").GetValue(a5))
+ {
+ ATest.ReportTestFailure("A a5_aVal", a5, ref failure);
+ }
+ }
+
+ return failure;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/coreclr/tests/src/readytorun/crossboundarylayout/a/a.csproj b/src/coreclr/tests/src/readytorun/crossboundarylayout/a/a.csproj
new file mode 100644
index 00000000000000..6e3c26249fc0e7
--- /dev/null
+++ b/src/coreclr/tests/src/readytorun/crossboundarylayout/a/a.csproj
@@ -0,0 +1,14 @@
+
+
+ library
+ SharedLibrary
+
+
+
+
+
+
+
+
+
+
diff --git a/src/coreclr/tests/src/readytorun/crossboundarylayout/b/b.cs b/src/coreclr/tests/src/readytorun/crossboundarylayout/b/b.cs
new file mode 100644
index 00000000000000..6a7187c1f43ad1
--- /dev/null
+++ b/src/coreclr/tests/src/readytorun/crossboundarylayout/b/b.cs
@@ -0,0 +1,273 @@
+// 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 CrossBoundaryLayout
+{
+ public struct ByteStructB
+ {
+ public byte _bsVal;
+ }
+
+ public class B_A : A
+ {
+ public byte _bVal;
+ }
+
+ public class B_A_byte : AGeneric
+ {
+ public byte _bVal;
+ }
+
+ public class B_A_D : AGeneric
+ {
+ public byte _bVal;
+ }
+
+ public class B_A_BS : AGeneric
+ {
+ public byte _bVal;
+ }
+
+ public class B_A_E : AGeneric
+ {
+ public byte _bVal;
+ }
+
+ public class B_A_Generic : A
+ {
+ public T _bVal;
+ }
+
+ public class B_A_byte_Generic : AGeneric
+ {
+ public T _bVal;
+ }
+
+ public class B_A_D_Generic : AGeneric
+ {
+ public T _bVal;
+ }
+
+ public class B_A_BS_Generic : AGeneric
+ {
+ public T _bVal;
+ }
+
+ public class B_A_E_Generic : AGeneric
+ {
+ public T _bVal;
+ }
+
+ public class B_ABoring_byte : ABoringGeneric
+ {
+ public byte _bVal;
+ }
+
+ public class B_ABoring_D : ABoringGeneric
+ {
+ public byte _bVal;
+ }
+
+ public class B_ABoring_BS : ABoringGeneric
+ {
+ public byte _bVal;
+ }
+
+ public class B_ABoring_E : ABoringGeneric
+ {
+ public byte _bVal;
+ }
+
+ public class BTest
+ {
+ public static int Test()
+ {
+ int failure = 0;
+ {
+ var a = (A)Activator.CreateInstance(typeof(A));
+ a._aVal = 1;
+ if (1 != (byte)typeof(A).GetField("_aVal").GetValue(a))
+ {
+ ATest.ReportTestFailure("B a_aVal", a, ref failure);
+ }
+ }
+
+ {
+ var a2 = (AGeneric)Activator.CreateInstance(typeof(AGeneric));
+ a2._aVal = 1;
+ if (1 != (byte)typeof(AGeneric).GetField("_aVal").GetValue(a2))
+ {
+ ATest.ReportTestFailure("B a2_aVal", a2, ref failure);
+ }
+ }
+
+ {
+ var a3 = (AGeneric)Activator.CreateInstance(typeof(AGeneric));
+ a3._aVal._dVal = 1;
+ if (1 != ((ByteStruct)typeof(AGeneric).GetField("_aVal").GetValue(a3))._dVal)
+ {
+ ATest.ReportTestFailure("B a3_aVal", a3, ref failure);
+ }
+ }
+
+ {
+ var a4 = (ABoringGeneric)Activator.CreateInstance(typeof(ABoringGeneric));
+ a4._aVal = 1;
+ if (1 != (byte)typeof(ABoringGeneric).GetField("_aVal").GetValue(a4))
+ {
+ ATest.ReportTestFailure("B a4_aVal", a4, ref failure);
+ }
+ }
+
+ {
+ var a5 = (ABoringGeneric)Activator.CreateInstance(typeof(ABoringGeneric));
+ a5._aVal = 1;
+ if (1 != (byte)typeof(ABoringGeneric).GetField("_aVal").GetValue(a5))
+ {
+ ATest.ReportTestFailure("B a5_aVal", a5, ref failure);
+ }
+ }
+
+
+ {
+ var b = (B_A)Activator.CreateInstance(typeof(B_A));
+ b._bVal = 1;
+ if (1 != (byte)typeof(B_A).GetField("_bVal").GetValue(b))
+ {
+ ATest.ReportTestFailure("B b_bVal", b, ref failure);
+ }
+ }
+
+ {
+ var b2 = (B_A_byte)Activator.CreateInstance(typeof(B_A_byte));
+ b2._bVal = 1;
+ if (1 != (byte)typeof(B_A_byte).GetField("_bVal").GetValue(b2))
+ {
+ ATest.ReportTestFailure("B b2_bVal", b2, ref failure);
+ }
+ }
+
+ {
+ var b3 = (B_A_D)Activator.CreateInstance(typeof(B_A_D));
+ b3._bVal = 1;
+ if (1 != (byte)typeof(B_A_D).GetField("_bVal").GetValue(b3))
+ {
+ ATest.ReportTestFailure("B b3_bVal", b3, ref failure);
+ }
+ }
+
+ {
+ var b4 = (B_A_Generic)Activator.CreateInstance(typeof(B_A_Generic));
+ b4._bVal = 1;
+ if (1 != (byte)typeof(B_A_Generic).GetField("_bVal").GetValue(b4))
+ {
+ ATest.ReportTestFailure("B b4_bVal", b4, ref failure);
+ }
+ }
+
+ {
+ var b5 = (B_A_byte_Generic)Activator.CreateInstance(typeof(B_A_byte_Generic));
+ b5._bVal = 1;
+ if (1 != (byte)typeof(B_A_byte_Generic).GetField("_bVal").GetValue(b5))
+ {
+ ATest.ReportTestFailure("B b5_bVal", b5, ref failure);
+ }
+ }
+
+ {
+ var b6 = (B_A_D_Generic)Activator.CreateInstance(typeof(B_A_D_Generic));
+ b6._bVal = 1;
+ if (1 != (byte)typeof(B_A_D_Generic).GetField("_bVal").GetValue(b6))
+ {
+ ATest.ReportTestFailure("B b6_bVal", b6, ref failure);
+ }
+ }
+
+ {
+ var b7 = (B_A_Generic)Activator.CreateInstance(typeof(B_A_Generic));
+ b7._bVal._dVal = 1;
+ if (1 != ((ByteStruct)typeof(B_A_Generic).GetField("_bVal").GetValue(b7))._dVal)
+ {
+ ATest.ReportTestFailure("B b7_bVal", b7, ref failure);
+ }
+ }
+
+ {
+ var b8 = (B_A_byte_Generic)Activator.CreateInstance(typeof(B_A_byte_Generic));
+ b8._bVal._dVal = 1;
+ if (1 != ((ByteStruct)typeof(B_A_byte_Generic).GetField("_bVal").GetValue(b8))._dVal)
+ {
+ ATest.ReportTestFailure("B b8_bVal", b8, ref failure);
+ }
+ }
+
+ {
+ var b9 = (B_A_D_Generic)Activator.CreateInstance(typeof(B_A_D_Generic));
+ b9._bVal._dVal = 1;
+ if (1 != ((ByteStruct)typeof(B_A_D_Generic).GetField("_bVal").GetValue(b9))._dVal)
+ {
+ ATest.ReportTestFailure("B b9_bVal", b9, ref failure);
+ }
+ }
+
+ {
+ var b10 = (B_ABoring_byte)Activator.CreateInstance(typeof(B_ABoring_byte));
+ b10._bVal = 1;
+ if (1 != (byte)typeof(B_ABoring_byte).GetField("_bVal").GetValue(b10))
+ {
+ ATest.ReportTestFailure("B b10_bVal", b10, ref failure);
+ }
+ }
+
+ {
+ var b11 = (B_ABoring_D)Activator.CreateInstance(typeof(B_ABoring_D));
+ b11._bVal = 1;
+ if (1 != (byte)typeof(B_ABoring_D).GetField("_bVal").GetValue(b11))
+ {
+ ATest.ReportTestFailure("B b11_bVal", b11, ref failure);
+ }
+ }
+
+ {
+ var b12 = (B_A_BS)Activator.CreateInstance(typeof(B_A_BS));
+ b12._bVal = 1;
+ if (1 != (byte)typeof(B_A_BS).GetField("_bVal").GetValue(b12))
+ {
+ ATest.ReportTestFailure("B b12_bVal", b12, ref failure);
+ }
+ }
+
+ {
+ var b13 = (B_A_E)Activator.CreateInstance(typeof(B_A_E));
+ b13._bVal = 1;
+ if (1 != (byte)typeof(B_A_E).GetField("_bVal").GetValue(b13))
+ {
+ ATest.ReportTestFailure("B b12_bVal", b13, ref failure);
+ }
+ }
+
+ {
+ var b14 = (B_ABoring_BS)Activator.CreateInstance(typeof(B_ABoring_BS));
+ b14._bVal = 1;
+ if (1 != (byte)typeof(B_ABoring_BS).GetField("_bVal").GetValue(b14))
+ {
+ ATest.ReportTestFailure("B b12_bVal", b14, ref failure);
+ }
+ }
+
+ {
+ var b15 = (B_ABoring_E)Activator.CreateInstance(typeof(B_ABoring_E));
+ b15._bVal = 1;
+ if (1 != (byte)typeof(B_ABoring_E).GetField("_bVal").GetValue(b15))
+ {
+ ATest.ReportTestFailure("B b12_bVal", b15, ref failure);
+ }
+ }
+
+ return failure;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/coreclr/tests/src/readytorun/crossboundarylayout/b/b.csproj b/src/coreclr/tests/src/readytorun/crossboundarylayout/b/b.csproj
new file mode 100644
index 00000000000000..1eb8e6e923bcc7
--- /dev/null
+++ b/src/coreclr/tests/src/readytorun/crossboundarylayout/b/b.csproj
@@ -0,0 +1,16 @@
+
+
+ library
+ SharedLibrary
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/coreclr/tests/src/readytorun/crossboundarylayout/buildcrossgen2image.cmd b/src/coreclr/tests/src/readytorun/crossboundarylayout/buildcrossgen2image.cmd
new file mode 100644
index 00000000000000..e75f4808a4d9e1
--- /dev/null
+++ b/src/coreclr/tests/src/readytorun/crossboundarylayout/buildcrossgen2image.cmd
@@ -0,0 +1,95 @@
+setlocal
+set COMPOSITENAME=
+set COMPILEARG=
+set TESTINITIALBINPATH=%2
+set TESTTARGET_DIR=%3
+set TESTBATCHROOT=%1
+
+
+:Loop
+if "%4"=="" goto Continue
+
+set COMPILEARG=%COMPILEARG% %TESTINITIALBINPATH%\%4.dll
+set COMPOSITENAME=%COMPOSITENAME%%4
+
+if "%5"=="CG2Single" (
+ call :CG2Single
+ shift
+) ELSE (
+ if "%5"=="CG2SingleInputBubble" (
+ call :CG2SingleInputBubble
+ shift
+ ) ELSE (
+ if "%5"=="CG1Single" (
+ call :CG1Single
+ shift
+ ) ELSE (
+ if "%5"=="CG2SingleBubbleADOnly" (
+ call :CG2SingleBubbleADOnly
+ shift
+ ) ELSE (
+ if "%5"=="CG2NoMethods" (
+ call :CG2NoMethods
+ shift
+ ) ELSE (
+ if "%5"=="CG2Composite" (
+ shift
+ call :Continue
+ )
+ )
+ )
+ )
+ )
+)
+
+shift
+goto Loop
+:Continue
+
+if "%COMPOSITENAME%"=="" goto done
+
+set BUILDCMD=%TESTBATCHROOT%\..\..\..\..\..\..\.dotnet\dotnet %CORE_ROOT%\crossgen2\crossgen2.dll -r %CORE_ROOT%\* -r %TESTINITIALBINPATH%\*.dll -o %TESTINITIALBINPATH%\%TESTTARGET_DIR%\%COMPOSITENAME%Composite.dll --composite %COMPILEARG%
+echo %BUILDCMD% > %TESTINITIALBINPATH%\%TESTTARGET_DIR%\%COMPOSITENAME%Composite.dll.log
+call %BUILDCMD% >> %TESTINITIALBINPATH%\%TESTTARGET_DIR%\%COMPOSITENAME%Composite.dll.log 2>&1
+if NOT EXIST %TESTINITIALBINPATH%\%TESTTARGET_DIR%\%COMPOSITENAME%Composite.dll del %TESTINITIALBINPATH%\%TESTTARGET_DIR%\a.dll
+goto done
+
+:CG2Single
+del %TESTINITIALBINPATH%\%TESTTARGET_DIR%\%COMPOSITENAME%.dll
+set BUILDCMD=%TESTBATCHROOT%\..\..\..\..\..\..\.dotnet\dotnet %CORE_ROOT%\crossgen2\crossgen2.dll -r %CORE_ROOT%\* -r %TESTINITIALBINPATH%\*.dll -o %TESTINITIALBINPATH%\%TESTTARGET_DIR%\%COMPOSITENAME%.dll %TESTINITIALBINPATH%\%COMPOSITENAME%.dll
+echo %BUILDCMD% > %TESTINITIALBINPATH%\%TESTTARGET_DIR%\%COMPOSITENAME%.dll.log
+call %BUILDCMD% >> %TESTINITIALBINPATH%\%TESTTARGET_DIR%\%COMPOSITENAME%.dll.log 2>&1
+goto done
+
+:CG2NoMethods
+del %TESTINITIALBINPATH%\%TESTTARGET_DIR%\%COMPOSITENAME%.dll
+set BUILDCMD=%TESTBATCHROOT%\..\..\..\..\..\..\.dotnet\dotnet %CORE_ROOT%\crossgen2\crossgen2.dll --compile-no-methods -r %CORE_ROOT%\* -r %TESTINITIALBINPATH%\*.dll -o %TESTINITIALBINPATH%\%TESTTARGET_DIR%\%COMPOSITENAME%.dll %TESTINITIALBINPATH%\%COMPOSITENAME%.dll
+echo %BUILDCMD% > %TESTINITIALBINPATH%\%TESTTARGET_DIR%\%COMPOSITENAME%.dll.log
+call %BUILDCMD% >> %TESTINITIALBINPATH%\%TESTTARGET_DIR%\%COMPOSITENAME%.dll.log 2>&1
+goto done
+
+:CG2SingleInputBubble
+del %TESTINITIALBINPATH%\%TESTTARGET_DIR%\%COMPOSITENAME%.dll
+set BUILDCMD=%TESTBATCHROOT%\..\..\..\..\..\..\.dotnet\dotnet %CORE_ROOT%\crossgen2\crossgen2.dll -r %CORE_ROOT%\* -r %TESTINITIALBINPATH%\*.dll -o %TESTINITIALBINPATH%\%TESTTARGET_DIR%\%COMPOSITENAME%.dll --inputbubble %TESTINITIALBINPATH%\%COMPOSITENAME%.dll
+echo %BUILDCMD% > %TESTINITIALBINPATH%\%TESTTARGET_DIR%\%COMPOSITENAME%.dll.log
+call %BUILDCMD% >> %TESTINITIALBINPATH%\%TESTTARGET_DIR%\%COMPOSITENAME%.dll.log 2>&1
+goto done
+
+:CG2SingleBubbleADOnly
+del %TESTINITIALBINPATH%\%TESTTARGET_DIR%\%COMPOSITENAME%.dll
+set BUILDCMD=%TESTBATCHROOT%\..\..\..\..\..\..\.dotnet\dotnet %CORE_ROOT%\crossgen2\crossgen2.dll -r %CORE_ROOT%\* -r %TESTINITIALBINPATH%\d.dll -o %TESTINITIALBINPATH%\%TESTTARGET_DIR%\%COMPOSITENAME%.dll --inputbubble %TESTINITIALBINPATH%\%COMPOSITENAME%.dll
+echo %BUILDCMD% > %TESTINITIALBINPATH%\%TESTTARGET_DIR%\%COMPOSITENAME%.dll.log
+call %BUILDCMD% >> %TESTINITIALBINPATH%\%TESTTARGET_DIR%\%COMPOSITENAME%.dll.log 2>&1
+goto done
+
+:CG1Single
+del %TESTINITIALBINPATH%\%TESTTARGET_DIR%\%COMPOSITENAME%.dll
+set BUILDCMD=%CORE_ROOT%\crossgen.exe /Platform_Assemblies_Paths %CORE_ROOT%;%TESTINITIALBINPATH% /out %TESTINITIALBINPATH%\%TESTTARGET_DIR%\%COMPOSITENAME%.dll /in %TESTINITIALBINPATH%\%COMPOSITENAME%.dll
+echo %BUILDCMD% > %TESTINITIALBINPATH%\%TESTTARGET_DIR%\%COMPOSITENAME%.dll.log
+call %BUILDCMD% >> %TESTINITIALBINPATH%\%TESTTARGET_DIR%\%COMPOSITENAME%.dll.log 2>&1
+goto done
+
+:done
+shift
+set COMPILEARG=
+set COMPOSITENAME=
diff --git a/src/coreclr/tests/src/readytorun/crossboundarylayout/crossboundarytest/c.cs b/src/coreclr/tests/src/readytorun/crossboundarylayout/crossboundarytest/c.cs
new file mode 100644
index 00000000000000..2e2bc2e42928bf
--- /dev/null
+++ b/src/coreclr/tests/src/readytorun/crossboundarylayout/crossboundarytest/c.cs
@@ -0,0 +1,289 @@
+// 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 CrossBoundaryLayout
+{
+ class C_B_A : B_A
+ {
+ public byte _cVal;
+ }
+
+ class C_B_A_byte : B_A_byte
+ {
+ public byte _cVal;
+ }
+
+ class C_B_A_D : B_A_D
+ {
+ public byte _cVal;
+ }
+
+ class C_B_A_Generic_byte : B_A_Generic
+ {
+ public byte _cVal;
+ }
+
+ class C_B_A_Generic_D : B_A_Generic
+ {
+ public byte _cVal;
+ }
+
+ class C_B_A_byte_Generic_byte : B_A_byte_Generic
+ {
+ public byte _cVal;
+ }
+
+ class C_B_A_byte_Generic_D : B_A_byte_Generic
+ {
+ public byte _cVal;
+ }
+
+ class C_B_A_D_Generic_byte : B_A_D_Generic
+ {
+ public byte _cVal;
+ }
+
+ class C_B_A_D_Generic_D : B_A_D_Generic
+ {
+ public byte _cVal;
+ }
+
+ public class CTest
+ {
+ public static int Test()
+ {
+ int failure = 0;
+
+ {
+ var a = (A)Activator.CreateInstance(typeof(A));
+ a._aVal = 1;
+ if (1 != (byte)typeof(A).GetField("_aVal").GetValue(a))
+ {
+ ATest.ReportTestFailure("C a_aVal", a, ref failure);
+ }
+ }
+
+ {
+ var a2 = (AGeneric)Activator.CreateInstance(typeof(AGeneric));
+ a2._aVal = 1;
+ if (1 != (byte)typeof(AGeneric).GetField("_aVal").GetValue(a2))
+ {
+ ATest.ReportTestFailure("C a2_aVal", a2, ref failure);
+ }
+ }
+
+ {
+ var a3 = (AGeneric)Activator.CreateInstance(typeof(AGeneric));
+ a3._aVal._dVal = 1;
+ if (1 != ((ByteStruct)typeof(AGeneric).GetField("_aVal").GetValue(a3))._dVal)
+ {
+ ATest.ReportTestFailure("C a3_aVal", a3, ref failure);
+ }
+ }
+
+ {
+ var a4 = (ABoringGeneric)Activator.CreateInstance(typeof(ABoringGeneric));
+ a4._aVal = 1;
+ if (1 != (byte)typeof(ABoringGeneric).GetField("_aVal").GetValue(a4))
+ {
+ ATest.ReportTestFailure("C a4_aVal", a4, ref failure);
+ }
+ }
+
+ {
+ var a5 = (ABoringGeneric)Activator.CreateInstance(typeof(ABoringGeneric));
+ a5._aVal = 1;
+ if (1 != (byte)typeof(ABoringGeneric).GetField("_aVal").GetValue(a5))
+ {
+ ATest.ReportTestFailure("C a5_aVal", a5, ref failure);
+ }
+ }
+
+
+ {
+ var b = (B_A)Activator.CreateInstance(typeof(B_A));
+ b._bVal = 1;
+ if (1 != (byte)typeof(B_A).GetField("_bVal").GetValue(b))
+ {
+ ATest.ReportTestFailure("C b_bVal", b, ref failure);
+ }
+ }
+
+ {
+ var b2 = (B_A_byte)Activator.CreateInstance(typeof(B_A_byte));
+ b2._bVal = 1;
+ if (1 != (byte)typeof(B_A_byte).GetField("_bVal").GetValue(b2))
+ {
+ ATest.ReportTestFailure("C b2_bVal", b2, ref failure);
+ }
+ }
+
+ {
+ var b3 = (B_A_D)Activator.CreateInstance(typeof(B_A_D));
+ b3._bVal = 1;
+ if (1 != (byte)typeof(B_A_D).GetField("_bVal").GetValue(b3))
+ {
+ ATest.ReportTestFailure("C b3_bVal", b3, ref failure);
+ }
+ }
+
+ {
+ var b4 = (B_A_Generic)Activator.CreateInstance(typeof(B_A_Generic));
+ b4._bVal = 1;
+ if (1 != (byte)typeof(B_A_Generic).GetField("_bVal").GetValue(b4))
+ {
+ ATest.ReportTestFailure("C b4_bVal", b4, ref failure);
+ }
+ }
+
+ {
+ var b5 = (B_A_byte_Generic)Activator.CreateInstance(typeof(B_A_byte_Generic));
+ b5._bVal = 1;
+ if (1 != (byte)typeof(B_A_byte_Generic).GetField("_bVal").GetValue(b5))
+ {
+ ATest.ReportTestFailure("C b5_bVal", b5, ref failure);
+ }
+ }
+
+ {
+ var b6 = (B_A_D_Generic)Activator.CreateInstance(typeof(B_A_D_Generic));
+ b6._bVal = 1;
+ if (1 != (byte)typeof(B_A_D_Generic).GetField("_bVal").GetValue(b6))
+ {
+ ATest.ReportTestFailure("C b6_bVal", b6, ref failure);
+ }
+ }
+
+ {
+ var b7 = (B_A_Generic)Activator.CreateInstance(typeof(B_A_Generic));
+ b7._bVal._dVal = 1;
+ if (1 != ((ByteStruct)typeof(B_A_Generic).GetField("_bVal").GetValue(b7))._dVal)
+ {
+ ATest.ReportTestFailure("C b7_bVal", b7, ref failure);
+ }
+ }
+
+ {
+ var b8 = (B_A_byte_Generic)Activator.CreateInstance(typeof(B_A_byte_Generic));
+ b8._bVal._dVal = 1;
+ if (1 != ((ByteStruct)typeof(B_A_byte_Generic).GetField("_bVal").GetValue(b8))._dVal)
+ {
+ ATest.ReportTestFailure("C b8_bVal", b8, ref failure);
+ }
+ }
+
+ {
+ var b9 = (B_A_D_Generic)Activator.CreateInstance(typeof(B_A_D_Generic));
+ b9._bVal._dVal = 1;
+ if (1 != ((ByteStruct)typeof(B_A_D_Generic).GetField("_bVal").GetValue(b9))._dVal)
+ {
+ ATest.ReportTestFailure("C b9_bVal", b9, ref failure);
+ }
+ }
+
+ {
+ var b10 = (B_ABoring_byte)Activator.CreateInstance(typeof(B_ABoring_byte));
+ b10._bVal = 1;
+ if (1 != (byte)typeof(B_ABoring_byte).GetField("_bVal").GetValue(b10))
+ {
+ ATest.ReportTestFailure("C b10_bVal", b10, ref failure);
+ }
+ }
+
+ {
+ var b11 = (B_ABoring_D)Activator.CreateInstance(typeof(B_ABoring_D));
+ b11._bVal = 1;
+ if (1 != (byte)typeof(B_ABoring_D).GetField("_bVal").GetValue(b11))
+ {
+ ATest.ReportTestFailure("C b11_bVal", b11, ref failure);
+ }
+ }
+
+ {
+ var c = (C_B_A)Activator.CreateInstance(typeof(C_B_A));
+ c._cVal = 1;
+ if (1 != (byte)typeof(C_B_A).GetField("_cVal").GetValue(c))
+ {
+ ATest.ReportTestFailure("C c_bVal", c, ref failure);
+ }
+ }
+
+ {
+ var c2 = (C_B_A_byte)Activator.CreateInstance(typeof(C_B_A_byte));
+ c2._cVal = 1;
+ if (1 != (byte)typeof(C_B_A_byte).GetField("_cVal").GetValue(c2))
+ {
+ ATest.ReportTestFailure("C c2_bVal", c2, ref failure);
+ }
+ }
+
+ {
+ var c3 = (C_B_A_D)Activator.CreateInstance(typeof(C_B_A_D));
+ c3._cVal = 1;
+ if (1 != (byte)typeof(C_B_A_D).GetField("_cVal").GetValue(c3))
+ {
+ ATest.ReportTestFailure("C c3_bVal", c3, ref failure);
+ }
+ }
+
+ {
+ var c4 = (C_B_A_Generic_byte)Activator.CreateInstance(typeof(C_B_A_Generic_byte));
+ c4._cVal = 1;
+ if (1 != (byte)typeof(C_B_A_Generic_byte).GetField("_cVal").GetValue(c4))
+ {
+ ATest.ReportTestFailure("C c4_bVal", c4, ref failure);
+ }
+ }
+
+ {
+ var c5 = (C_B_A_byte_Generic_byte)Activator.CreateInstance(typeof(C_B_A_byte_Generic_byte));
+ c5._cVal = 1;
+ if (1 != (byte)typeof(C_B_A_byte_Generic_byte).GetField("_cVal").GetValue(c5))
+ {
+ ATest.ReportTestFailure("C c5_bVal", c5, ref failure);
+ }
+ }
+
+ {
+ var c6 = (C_B_A_D_Generic_byte)Activator.CreateInstance(typeof(C_B_A_D_Generic_byte));
+ c6._cVal = 1;
+ if (1 != (byte)typeof(C_B_A_D_Generic_byte).GetField("_cVal").GetValue(c6))
+ {
+ ATest.ReportTestFailure("C c6_bVal", c6, ref failure);
+ }
+ }
+
+ {
+ var c7 = (C_B_A_Generic_D)Activator.CreateInstance(typeof(C_B_A_Generic_D));
+ c7._cVal = 1;
+ if (1 != (byte)typeof(C_B_A_Generic_D).GetField("_cVal").GetValue(c7))
+ {
+ ATest.ReportTestFailure("C c7_bVal", c7, ref failure);
+ }
+ }
+
+ {
+ var c8 = (C_B_A_byte_Generic_D)Activator.CreateInstance(typeof(C_B_A_byte_Generic_D));
+ c8._cVal = 1;
+ if (1 != (byte)typeof(C_B_A_byte_Generic_D).GetField("_cVal").GetValue(c8))
+ {
+ ATest.ReportTestFailure("C c8_bVal", c8, ref failure);
+ }
+ }
+
+ {
+ var c9 = (C_B_A_D_Generic_D)Activator.CreateInstance(typeof(C_B_A_D_Generic_D));
+ c9._cVal = 1;
+ if (1 != (byte)typeof(C_B_A_D_Generic_D).GetField("_cVal").GetValue(c9))
+ {
+ ATest.ReportTestFailure("C c9_bVal", c9, ref failure);
+ }
+ }
+
+ return failure;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/coreclr/tests/src/readytorun/crossboundarylayout/crossboundarytest/c1.cs b/src/coreclr/tests/src/readytorun/crossboundarylayout/crossboundarytest/c1.cs
new file mode 100644
index 00000000000000..859a20aa5a68d0
--- /dev/null
+++ b/src/coreclr/tests/src/readytorun/crossboundarylayout/crossboundarytest/c1.cs
@@ -0,0 +1,378 @@
+// 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 CrossBoundaryLayout
+{
+ public class A1BoringGeneric
+ {
+ public byte _aVal;
+ }
+
+ public class B1_A : A
+ {
+ public byte _bVal;
+ }
+
+ public class B1_A_byte : AGeneric
+ {
+ public byte _bVal;
+ }
+
+ public class B1_A_D : AGeneric
+ {
+ public byte _bVal;
+ }
+
+ public class B1_A_Generic : A
+ {
+ public T _bVal;
+ }
+
+ public class B1_A_byte_Generic : AGeneric
+ {
+ public T _bVal;
+ }
+
+ public class B1_A_D_Generic : AGeneric
+ {
+ public T _bVal;
+ }
+
+ public class B1_ABoring_byte : ABoringGeneric
+ {
+ public byte _bVal;
+ }
+
+ public class B1_ABoring_D : ABoringGeneric
+ {
+ public byte _bVal;
+ }
+
+ public class B1_A1Boring_byte : A1BoringGeneric
+ {
+ public byte _bVal;
+ }
+
+ public class B1_A1Boring_D : A1BoringGeneric
+ {
+ public byte _bVal;
+ }
+
+ class C1_B_A : B1_A
+ {
+ public byte _cVal;
+ }
+
+ class C1_B_A_byte : B1_A_byte
+ {
+ public byte _cVal;
+ }
+
+ class C1_B_A_D : B1_A_D
+ {
+ public byte _cVal;
+ }
+
+ class C1_B_A_Generic_byte : B1_A_Generic
+ {
+ public byte _cVal;
+ }
+
+ class C1_B_A_Generic_D : B1_A_Generic
+ {
+ public byte _cVal;
+ }
+
+ class C1_B_A_byte_Generic_byte : B1_A_byte_Generic
+ {
+ public byte _cVal;
+ }
+
+ class C1_B_A_byte_Generic_D : B1_A_byte_Generic
+ {
+ public byte _cVal;
+ }
+
+ class C1_B_A_D_Generic_byte : B1_A_D_Generic
+ {
+ public byte _cVal;
+ }
+
+ class C1_B_A_D_Generic_D : B1_A_D_Generic
+ {
+ public byte _cVal;
+ }
+
+ public class C1Test
+ {
+ public static int Test()
+ {
+ int failure = 0;
+ {
+ var a = (A)Activator.CreateInstance(typeof(A));
+ a._aVal = 1;
+ if (1 != (byte)typeof(A).GetField("_aVal").GetValue(a))
+ {
+ ATest.ReportTestFailure("C1 a_aVal", a, ref failure);
+ }
+ }
+
+ {
+ var a2 = (AGeneric)Activator.CreateInstance(typeof(AGeneric));
+ a2._aVal = 1;
+ if (1 != (byte)typeof(AGeneric).GetField("_aVal").GetValue(a2))
+ {
+ ATest.ReportTestFailure("C1 a2_aVal", a2, ref failure);
+ }
+ }
+
+ {
+ var a3 = (AGeneric)Activator.CreateInstance(typeof(AGeneric));
+ a3._aVal._dVal = 1;
+ if (1 != ((ByteStruct)typeof(AGeneric).GetField("_aVal").GetValue(a3))._dVal)
+ {
+ ATest.ReportTestFailure("C1 a3_aVal", a3, ref failure);
+ }
+ }
+
+ {
+ var a4 = (ABoringGeneric)Activator.CreateInstance(typeof(ABoringGeneric));
+ a4._aVal = 1;
+ if (1 != (byte)typeof(ABoringGeneric).GetField("_aVal").GetValue(a4))
+ {
+ ATest.ReportTestFailure("C1 a4_aVal", a4, ref failure);
+ }
+ }
+
+ {
+ var a5 = (ABoringGeneric)Activator.CreateInstance(typeof(ABoringGeneric));
+ a5._aVal = 1;
+ if (1 != (byte)typeof(ABoringGeneric).GetField("_aVal").GetValue(a5))
+ {
+ ATest.ReportTestFailure("C1 a5_aVal", a5, ref failure);
+ }
+ }
+
+ {
+ var a6 = (A1BoringGeneric)Activator.CreateInstance(typeof(A1BoringGeneric));
+ a6._aVal = 1;
+ if (1 != (byte)typeof(A1BoringGeneric).GetField("_aVal").GetValue(a6))
+ {
+ ATest.ReportTestFailure("C1 a6_aVal", a6, ref failure);
+ }
+ }
+
+ {
+ var a7 = (A1BoringGeneric)Activator.CreateInstance(typeof(A1BoringGeneric));
+ a7._aVal = 1;
+ if (1 != (byte)typeof(A1BoringGeneric).GetField("_aVal").GetValue(a7))
+ {
+ ATest.ReportTestFailure("C1 a7_aVal", a7, ref failure);
+ }
+ }
+
+ {
+ var b = (B1_A)Activator.CreateInstance(typeof(B1_A));
+ b._bVal = 1;
+ if (1 != (byte)typeof(B1_A).GetField("_bVal").GetValue(b))
+ {
+ ATest.ReportTestFailure("C1 b_bVal", b, ref failure);
+ }
+ }
+
+ {
+ var b2 = (B1_A_byte)Activator.CreateInstance(typeof(B1_A_byte));
+ b2._bVal = 1;
+ if (1 != (byte)typeof(B1_A_byte).GetField("_bVal").GetValue(b2))
+ {
+ ATest.ReportTestFailure("C1 b2_bVal", b2, ref failure);
+ }
+ }
+
+ {
+ var b3 = (B1_A_D)Activator.CreateInstance(typeof(B1_A_D));
+ b3._bVal = 1;
+ if (1 != (byte)typeof(B1_A_D).GetField("_bVal").GetValue(b3))
+ {
+ ATest.ReportTestFailure("C1 b3_bVal", b3, ref failure);
+ }
+ }
+
+ {
+ var b4 = (B1_A_Generic)Activator.CreateInstance(typeof(B1_A_Generic));
+ b4._bVal = 1;
+ if (1 != (byte)typeof(B1_A_Generic).GetField("_bVal").GetValue(b4))
+ {
+ ATest.ReportTestFailure("C1 b4_bVal", b4, ref failure);
+ }
+ }
+
+ {
+ var b5 = (B1_A_byte_Generic)Activator.CreateInstance(typeof(B1_A_byte_Generic));
+ b5._bVal = 1;
+ if (1 != (byte)typeof(B1_A_byte_Generic).GetField("_bVal").GetValue(b5))
+ {
+ ATest.ReportTestFailure("C1 b5_bVal", b5, ref failure);
+ }
+ }
+
+ {
+ var b6 = (B1_A_D_Generic)Activator.CreateInstance(typeof(B1_A_D_Generic));
+ b6._bVal = 1;
+ if (1 != (byte)typeof(B1_A_D_Generic).GetField("_bVal").GetValue(b6))
+ {
+ ATest.ReportTestFailure("C1 b6_bVal", b6, ref failure);
+ }
+ }
+
+ {
+ var b7 = (B1_A_Generic)Activator.CreateInstance(typeof(B1_A_Generic));
+ b7._bVal._dVal = 1;
+ if (1 != ((ByteStruct)typeof(B1_A_Generic).GetField("_bVal").GetValue(b7))._dVal)
+ {
+ ATest.ReportTestFailure("C1 b7_bVal", b7, ref failure);
+ }
+ }
+
+ {
+ var b8 = (B1_A_byte_Generic)Activator.CreateInstance(typeof(B1_A_byte_Generic));
+ b8._bVal._dVal = 1;
+ if (1 != ((ByteStruct)typeof(B1_A_byte_Generic).GetField("_bVal").GetValue(b8))._dVal)
+ {
+ ATest.ReportTestFailure("C1 b8_bVal", b8, ref failure);
+ }
+ }
+
+ {
+ var b9 = (B1_A_D_Generic)Activator.CreateInstance(typeof(B1_A_D_Generic));
+ b9._bVal._dVal = 1;
+ if (1 != ((ByteStruct)typeof(B1_A_D_Generic).GetField("_bVal").GetValue(b9))._dVal)
+ {
+ ATest.ReportTestFailure("C1 b9_bVal", b9, ref failure);
+ }
+ }
+
+ {
+ var b10 = (B1_ABoring_byte)Activator.CreateInstance(typeof(B1_ABoring_byte));
+ b10._bVal = 1;
+ if (1 != (byte)typeof(B1_ABoring_byte).GetField("_bVal").GetValue(b10))
+ {
+ ATest.ReportTestFailure("C1 b10_bVal", b10, ref failure);
+ }
+ }
+
+ {
+ var b11 = (B1_ABoring_D)Activator.CreateInstance(typeof(B1_ABoring_D));
+ b11._bVal = 1;
+ if (1 != (byte)typeof(B1_ABoring_D).GetField("_bVal").GetValue(b11))
+ {
+ ATest.ReportTestFailure("C1 b11_bVal", b11, ref failure);
+ }
+ }
+
+ {
+ var b12 = (B1_A1Boring_byte)Activator.CreateInstance(typeof(B1_A1Boring_byte));
+ b12._bVal = 1;
+ if (1 != (byte)typeof(B1_A1Boring_byte).GetField("_bVal").GetValue(b12))
+ {
+ ATest.ReportTestFailure("C1 b12_bVal", b12, ref failure);
+ }
+ }
+
+ {
+ var b13 = (B1_A1Boring_D)Activator.CreateInstance(typeof(B1_A1Boring_D));
+ b13._bVal = 1;
+ if (1 != (byte)typeof(B1_A1Boring_D).GetField("_bVal").GetValue(b13))
+ {
+ ATest.ReportTestFailure("C1 b13_bVal", b13, ref failure);
+ }
+ }
+
+ {
+ var c = (C1_B_A)Activator.CreateInstance(typeof(C1_B_A));
+ c._cVal = 1;
+ if (1 != (byte)typeof(C1_B_A).GetField("_cVal").GetValue(c))
+ {
+ ATest.ReportTestFailure("C1 c_bVal", c, ref failure);
+ }
+ }
+
+ {
+ var c2 = (C1_B_A_byte)Activator.CreateInstance(typeof(C1_B_A_byte));
+ c2._cVal = 1;
+ if (1 != (byte)typeof(C1_B_A_byte).GetField("_cVal").GetValue(c2))
+ {
+ ATest.ReportTestFailure("C1 c2_bVal", c2, ref failure);
+ }
+ }
+
+ {
+ var c3 = (C1_B_A_D)Activator.CreateInstance(typeof(C1_B_A_D));
+ c3._cVal = 1;
+ if (1 != (byte)typeof(C1_B_A_D).GetField("_cVal").GetValue(c3))
+ {
+ ATest.ReportTestFailure("C1 c3_bVal", c3, ref failure);
+ }
+ }
+
+ {
+ var c4 = (C1_B_A_Generic_byte)Activator.CreateInstance(typeof(C1_B_A_Generic_byte));
+ c4._cVal = 1;
+ if (1 != (byte)typeof(C1_B_A_Generic_byte).GetField("_cVal").GetValue(c4))
+ {
+ ATest.ReportTestFailure("C1 c4_bVal", c4, ref failure);
+ }
+ }
+
+ {
+ var c5 = (C1_B_A_byte_Generic_byte)Activator.CreateInstance(typeof(C1_B_A_byte_Generic_byte));
+ c5._cVal = 1;
+ if (1 != (byte)typeof(C1_B_A_byte_Generic_byte).GetField("_cVal").GetValue(c5))
+ {
+ ATest.ReportTestFailure("C1 c5_bVal", c5, ref failure);
+ }
+ }
+
+ {
+ var c6 = (C1_B_A_D_Generic_byte)Activator.CreateInstance(typeof(C1_B_A_D_Generic_byte));
+ c6._cVal = 1;
+ if (1 != (byte)typeof(C1_B_A_D_Generic_byte).GetField("_cVal").GetValue(c6))
+ {
+ ATest.ReportTestFailure("C1 c6_bVal", c6, ref failure);
+ }
+ }
+
+ {
+ var c7 = (C1_B_A_Generic_D)Activator.CreateInstance(typeof(C1_B_A_Generic_D));
+ c7._cVal = 1;
+ if (1 != (byte)typeof(C1_B_A_Generic_D).GetField("_cVal").GetValue(c7))
+ {
+ ATest.ReportTestFailure("C1 c7_bVal", c7, ref failure);
+ }
+ }
+
+ {
+ var c8 = (C1_B_A_byte_Generic_D)Activator.CreateInstance(typeof(C1_B_A_byte_Generic_D));
+ c8._cVal = 1;
+ if (1 != (byte)typeof(C1_B_A_byte_Generic_D).GetField("_cVal").GetValue(c8))
+ {
+ ATest.ReportTestFailure("C1 c8_bVal", c8, ref failure);
+ }
+ }
+
+ {
+ var c9 = (C1_B_A_D_Generic_D)Activator.CreateInstance(typeof(C1_B_A_D_Generic_D));
+ c9._cVal = 1;
+ if (1 != (byte)typeof(C1_B_A_D_Generic_D).GetField("_cVal").GetValue(c9))
+ {
+ ATest.ReportTestFailure("C1 c9_bVal", c9, ref failure);
+ }
+ }
+
+ return failure;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/coreclr/tests/src/readytorun/crossboundarylayout/crossboundarytest/crossboundarytest.csproj b/src/coreclr/tests/src/readytorun/crossboundarylayout/crossboundarytest/crossboundarytest.csproj
new file mode 100644
index 00000000000000..a1eb9a74a4a525
--- /dev/null
+++ b/src/coreclr/tests/src/readytorun/crossboundarylayout/crossboundarytest/crossboundarytest.csproj
@@ -0,0 +1,19 @@
+
+
+ exe
+ 1
+ BuildAndRun
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/coreclr/tests/src/readytorun/crossboundarylayout/crossboundarytest/main.cs b/src/coreclr/tests/src/readytorun/crossboundarylayout/crossboundarytest/main.cs
new file mode 100644
index 00000000000000..8b757a7bfa20d8
--- /dev/null
+++ b/src/coreclr/tests/src/readytorun/crossboundarylayout/crossboundarytest/main.cs
@@ -0,0 +1,21 @@
+// 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 CrossBoundaryLayout
+{
+ class Program
+ {
+ public static int Main(string[] args)
+ {
+ int failure = ATest.Test();
+ failure += BTest.Test();
+ failure += CTest.Test();
+ failure += C1Test.Test();
+
+ return 100 + failure;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/coreclr/tests/src/readytorun/crossboundarylayout/crossboundarytests.cmd b/src/coreclr/tests/src/readytorun/crossboundarylayout/crossboundarytests.cmd
new file mode 100644
index 00000000000000..f634952a02a7f3
--- /dev/null
+++ b/src/coreclr/tests/src/readytorun/crossboundarylayout/crossboundarytests.cmd
@@ -0,0 +1,322 @@
+echo off
+setlocal
+set TESTDIR=%~dp0\..\..\..\..\..\..\artifacts\tests\coreclr\Windows_NT.x64.Debug\readytorun\crossboundarylayout\crossboundarytest\crossboundarytest
+set TESTBATCHROOT=%~dp0
+
+call :testSpecificCompositeScenarios
+call :testAllCombinationsOfCompositeAndR2R
+call :testCG2SingleInputBubbleCompiledWithoutReferenceToBCE
+call :testCG2SingleMixedInputBubble
+call :testCG2SingleInputBubbleAll
+call :testCG2All
+call :testCG1All
+
+goto done
+
+:testSpecificCompositeScenarios
+echo Test some of the interesting composite scenarios first
+
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B2C2D2E1 a e CG2Composite b crossboundarytest d CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% all a b crossboundarytest d
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% ad a d
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% abd a b d
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% a_crossboundarytest_d a crossboundarytest d
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% a_b_crossboundarytest a b crossboundarytest
+
+goto done
+
+:testAllCombinationsOfCompositeAndR2R
+echo testing all possible combinations of 1 regular R2R image mixed with the rest of the files being in a single composite image or alone
+echo Also test all possible arrangements of 2 composite images
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B1C0D0E0 a b CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B0C1D0E0 a crossboundarytest CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA0B1C1D0E0 b crossboundarytest CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B1C1D0E0 a b crossboundarytest CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA2B1C1D0E0 b crossboundarytest CG2Composite a CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B2C1D0E0 a crossboundarytest CG2Composite b CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA2B2C1D0E0 crossboundarytest CG2Single a b CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B0C0D1E0 a d CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA0B1C0D1E0 b d CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B1C0D1E0 a b d CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA2B1C0D1E0 b d CG2Composite a CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B2C0D1E0 a d CG2Composite b CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA2B2C0D1E0 d CG2Single a b CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA0B0C1D1E0 crossboundarytest d CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B0C1D1E0 a crossboundarytest d CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA2B0C1D1E0 crossboundarytest d CG2Composite a CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA0B1C1D1E0 b crossboundarytest d CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B1C1D1E0 a b crossboundarytest d CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA2B1C1D1E0 b crossboundarytest d CG2Composite a CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA0B2C1D1E0 crossboundarytest d CG2Composite b CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B2C1D1E0 a crossboundarytest d CG2Composite b CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA2B2C1D1E0 crossboundarytest d CG2Composite a b CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B0C2D1E0 a d CG2Composite crossboundarytest CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA2B0C2D1E0 d CG2Single a crossboundarytest CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA0B1C2D1E0 b d CG2Composite crossboundarytest CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B1C2D1E0 a b d CG2Composite crossboundarytest CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA2B1C2D1E0 b d CG2Composite a crossboundarytest CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA0B2C2D1E0 d CG2Single b crossboundarytest CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B2C2D1E0 a d CG2Composite b crossboundarytest CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA2B2C2D1E0 d CG2Single a b crossboundarytest CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B0C0D0E1 a e CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA0B1C0D0E1 b e CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B1C0D0E1 a b e CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA2B1C0D0E1 b e CG2Composite a CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B2C0D0E1 a e CG2Composite b CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA2B2C0D0E1 e CG2Single a b CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA0B0C1D0E1 crossboundarytest e CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B0C1D0E1 a crossboundarytest e CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA2B0C1D0E1 crossboundarytest e CG2Composite a CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA0B1C1D0E1 b crossboundarytest e CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B1C1D0E1 a b crossboundarytest e CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA2B1C1D0E1 b crossboundarytest e CG2Composite a CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA0B2C1D0E1 crossboundarytest e CG2Composite b CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B2C1D0E1 a crossboundarytest e CG2Composite b CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA2B2C1D0E1 crossboundarytest e CG2Composite a b CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B0C2D0E1 a e CG2Composite crossboundarytest CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA2B0C2D0E1 e CG2Single a crossboundarytest CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA0B1C2D0E1 b e CG2Composite crossboundarytest CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B1C2D0E1 a b e CG2Composite crossboundarytest CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA2B1C2D0E1 b e CG2Composite a crossboundarytest CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA0B2C2D0E1 e CG2Single b crossboundarytest CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B2C2D0E1 a e CG2Composite b crossboundarytest CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA2B2C2D0E1 e CG2Single a b crossboundarytest CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA0B0C0D1E1 d e CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B0C0D1E1 a d e CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA2B0C0D1E1 d e CG2Composite a CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA0B1C0D1E1 b d e CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B1C0D1E1 a b d e CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA2B1C0D1E1 b d e CG2Composite a CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA0B2C0D1E1 d e CG2Composite b CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B2C0D1E1 a d e CG2Composite b CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA2B2C0D1E1 d e CG2Composite a b CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA0B0C1D1E1 crossboundarytest d e CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B0C1D1E1 a crossboundarytest d e CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA2B0C1D1E1 crossboundarytest d e CG2Composite a CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA0B1C1D1E1 b crossboundarytest d e CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B1C1D1E1 a b crossboundarytest d e CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA2B1C1D1E1 b crossboundarytest d e CG2Composite a CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA0B2C1D1E1 crossboundarytest d e CG2Composite b CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B2C1D1E1 a crossboundarytest d e CG2Composite b CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA2B2C1D1E1 crossboundarytest d e CG2Composite a b CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA0B0C2D1E1 d e CG2Composite crossboundarytest CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B0C2D1E1 a d e CG2Composite crossboundarytest CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA2B0C2D1E1 d e CG2Composite a crossboundarytest CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA0B1C2D1E1 b d e CG2Composite crossboundarytest CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B1C2D1E1 a b d e CG2Composite crossboundarytest CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA2B1C2D1E1 b d e CG2Composite a crossboundarytest CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA0B2C2D1E1 d e CG2Composite b crossboundarytest CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B2C2D1E1 a d e CG2Composite b crossboundarytest CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA2B2C2D1E1 d e CG2Composite a b crossboundarytest CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B0C0D2E1 a e CG2Composite d CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA2B0C0D2E1 e CG2Single a d CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA0B1C0D2E1 b e CG2Composite d CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B1C0D2E1 a b e CG2Composite d CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA2B1C0D2E1 b e CG2Composite a d CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA0B2C0D2E1 e CG2Single b d CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B2C0D2E1 a e CG2Composite b d CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA2B2C0D2E1 e CG2Single a b d CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA0B0C1D2E1 crossboundarytest e CG2Composite d CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B0C1D2E1 a crossboundarytest e CG2Composite d CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA2B0C1D2E1 crossboundarytest e CG2Composite a d CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA0B1C1D2E1 b crossboundarytest e CG2Composite d CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B1C1D2E1 a b crossboundarytest e CG2Composite d CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA2B1C1D2E1 b crossboundarytest e CG2Composite a d CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA0B2C1D2E1 crossboundarytest e CG2Composite b d CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B2C1D2E1 a crossboundarytest e CG2Composite b d CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA2B2C1D2E1 crossboundarytest e CG2Composite a b d CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA0B0C2D2E1 e CG2Single crossboundarytest d CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B0C2D2E1 a e CG2Composite crossboundarytest d CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA2B0C2D2E1 e CG2Single a crossboundarytest d CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA0B1C2D2E1 b e CG2Composite crossboundarytest d CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B1C2D2E1 a b e CG2Composite crossboundarytest d CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA2B1C2D2E1 b e CG2Composite a crossboundarytest d CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA0B2C2D2E1 e CG2Single b crossboundarytest d CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA1B2C2D2E1 a e CG2Composite b crossboundarytest d CG2Composite
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% compositeA2B2C2D2E1 e CG2Single a b crossboundarytest d CG2Composite
+
+goto done
+
+:testCG2SingleInputBubbleAll
+
+echo TEST All combinations of the 5 dlls compiled with Crossgen2 with input bubble enabled and all assemblies passed as reference inputs to crossgen2
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble_A____ a CG2SingleInputBubble d CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble__B___ b CG2SingleInputBubble a CG2NoMethods d CG2NoMethods e CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble_AB___ a CG2SingleInputBubble b CG2SingleInputBubble d CG2NoMethods e CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble___C__ crossboundarytest CG2SingleInputBubble a CG2NoMethods d CG2NoMethods b CG2NoMethods e CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble_A_C__ a CG2SingleInputBubble crossboundarytest CG2SingleInputBubble d CG2NoMethods b CG2NoMethods e CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble__BC__ b CG2SingleInputBubble crossboundarytest CG2SingleInputBubble a CG2NoMethods d CG2NoMethods e CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble_ABC__ a CG2SingleInputBubble b CG2SingleInputBubble crossboundarytest CG2SingleInputBubble e CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble____D_ d CG2SingleInputBubble
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble_A__D_ a CG2SingleInputBubble d CG2SingleInputBubble
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble__B_D_ b CG2SingleInputBubble d CG2SingleInputBubble a CG2NoMethods e CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble_AB_D_ a CG2SingleInputBubble b CG2SingleInputBubble d CG2SingleInputBubble e CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble___CD_ crossboundarytest CG2SingleInputBubble d CG2SingleInputBubble a CG2NoMethods b CG2NoMethods e CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble_A_CD_ a CG2SingleInputBubble crossboundarytest CG2SingleInputBubble d CG2SingleInputBubble b CG2NoMethods e CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble__BCD_ b CG2SingleInputBubble crossboundarytest CG2SingleInputBubble d CG2SingleInputBubble a CG2NoMethods e CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble_ABCD_ a CG2SingleInputBubble b CG2SingleInputBubble crossboundarytest CG2SingleInputBubble d CG2SingleInputBubble e CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble_____E e CG2SingleInputBubble
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble_A___E a CG2SingleInputBubble e CG2SingleInputBubble d CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble__B__E b CG2SingleInputBubble e CG2SingleInputBubble a CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble_AB__E a CG2SingleInputBubble b CG2SingleInputBubble e CG2SingleInputBubble d CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble___C_E crossboundarytest CG2SingleInputBubble e CG2SingleInputBubble a CG2NoMethods b CG2NoMethods d CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble_A_C_E a CG2SingleInputBubble crossboundarytest CG2SingleInputBubble e CG2SingleInputBubble d CG2NoMethods b CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble__BC_E b CG2SingleInputBubble crossboundarytest CG2SingleInputBubble e CG2SingleInputBubble a CG2NoMethods d CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble_ABC_E a CG2SingleInputBubble b CG2SingleInputBubble crossboundarytest CG2SingleInputBubble e CG2SingleInputBubble d CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble____DE d CG2SingleInputBubble e CG2SingleInputBubble
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble_A__DE a CG2SingleInputBubble d CG2SingleInputBubble e CG2SingleInputBubble
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble__B_DE b CG2SingleInputBubble d CG2SingleInputBubble e CG2SingleInputBubble a CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble_AB_DE a CG2SingleInputBubble b CG2SingleInputBubble d CG2SingleInputBubble e CG2SingleInputBubble
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble___CDE crossboundarytest CG2SingleInputBubble d CG2SingleInputBubble e CG2SingleInputBubble a CG2NoMethods b CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble_A_CDE a CG2SingleInputBubble crossboundarytest CG2SingleInputBubble d CG2SingleInputBubble e CG2SingleInputBubble b CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble__BCDE b CG2SingleInputBubble crossboundarytest CG2SingleInputBubble d CG2SingleInputBubble e CG2SingleInputBubble a CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble_ABCDE a CG2SingleInputBubble b CG2SingleInputBubble crossboundarytest CG2SingleInputBubble d CG2SingleInputBubble e CG2SingleInputBubble
+
+goto done
+
+:testCG2SingleInputBubbleCompiledWithoutReferenceToBCE
+echo TEST All combinations of the 5 dlls compiled with Crossgen2 with input bubble enabled and all assemblies passed as
+echo reference inputs to crossgen2 when compiled b, crossboundarytest and e. a, and d are compiled with the reference
+echo set limited to a and d. This simulates a the model of two different sets of input bubble matched assemblies where there is a
+echo root set such as the runtime repo worth of libraries, and a seperately compiled application set.
+
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble2_A____ a CG2SingleBubbleADOnly d CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble2__B___ b CG2SingleInputBubble a CG2NoMethods d CG2NoMethods e CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble2_AB___ a CG2SingleBubbleADOnly b CG2SingleInputBubble d CG2NoMethods e CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble2___C__ crossboundarytest CG2SingleInputBubble a CG2NoMethods d CG2NoMethods b CG2NoMethods e CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble2_A_C__ a CG2SingleBubbleADOnly crossboundarytest CG2SingleInputBubble d CG2NoMethods b CG2NoMethods e CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble2__BC__ b CG2SingleInputBubble crossboundarytest CG2SingleInputBubble a CG2NoMethods d CG2NoMethods e CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble2_ABC__ a CG2SingleBubbleADOnly b CG2SingleInputBubble crossboundarytest CG2SingleInputBubble e CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble2____D_ d CG2SingleInputBubble
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble2_A__D_ a CG2SingleBubbleADOnly d CG2SingleBubbleADOnly
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble2__B_D_ b CG2SingleInputBubble d CG2SingleBubbleADOnly a CG2NoMethods e CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble2_AB_D_ a CG2SingleBubbleADOnly b CG2SingleInputBubble d CG2SingleBubbleADOnly e CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble2___CD_ crossboundarytest CG2SingleInputBubble d CG2SingleBubbleADOnly a CG2NoMethods b CG2NoMethods e CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble2_A_CD_ a CG2SingleBubbleADOnly crossboundarytest CG2SingleInputBubble d CG2SingleBubbleADOnly b CG2NoMethods e CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble2__BCD_ b CG2SingleInputBubble crossboundarytest CG2SingleInputBubble d CG2SingleBubbleADOnly a CG2NoMethods e CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble2_ABCD_ a CG2SingleBubbleADOnly b CG2SingleInputBubble crossboundarytest CG2SingleInputBubble d CG2SingleBubbleADOnly e CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble2_____E e CG2SingleInputBubble
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble2_A___E a CG2SingleBubbleADOnly e CG2SingleInputBubble d CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble2__B__E b CG2SingleInputBubble e CG2SingleInputBubble a CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble2_AB__E a CG2SingleBubbleADOnly b CG2SingleInputBubble e CG2SingleInputBubble d CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble2___C_E crossboundarytest CG2SingleInputBubble e CG2SingleInputBubble a CG2NoMethods b CG2NoMethods d CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble2_A_C_E a CG2SingleBubbleADOnly crossboundarytest CG2SingleInputBubble e CG2SingleInputBubble b CG2NoMethods d CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble2__BC_E b CG2SingleInputBubble crossboundarytest CG2SingleInputBubble e CG2SingleInputBubble d CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble2_ABC_E a CG2SingleBubbleADOnly b CG2SingleInputBubble crossboundarytest CG2SingleInputBubble e CG2SingleInputBubble d CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble2____DE d CG2SingleBubbleADOnly e CG2SingleInputBubble
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble2_A__DE a CG2SingleBubbleADOnly d CG2SingleBubbleADOnly e CG2SingleInputBubble
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble2__B_DE b CG2SingleInputBubble d CG2SingleBubbleADOnly e CG2SingleInputBubble a CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble2_AB_DE a CG2SingleBubbleADOnly b CG2SingleInputBubble d CG2SingleBubbleADOnly e CG2SingleInputBubble
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble2___CDE crossboundarytest CG2SingleInputBubble d CG2SingleBubbleADOnly e CG2SingleInputBubble a CG2NoMethods b CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble2_A_CDE a CG2SingleBubbleADOnly crossboundarytest CG2SingleInputBubble d CG2SingleBubbleADOnly e CG2SingleInputBubble b CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble2__BCDE b CG2SingleInputBubble crossboundarytest CG2SingleInputBubble d CG2SingleBubbleADOnly e CG2SingleInputBubble a CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble2_ABCDE a CG2SingleBubbleADOnly b CG2SingleInputBubble crossboundarytest CG2SingleInputBubble d CG2SingleBubbleADOnly e CG2SingleInputBubble
+
+goto done
+
+:testCG2SingleMixedInputBubble
+echo TEST All combinations of the 5 dlls compiled with Crossgen2 with input bubble enabled for the root set and not
+echo for the more derived set of assemblies. b, crossboundarytest, and e are compiled as standard R2R and
+echo a, and d are compiled with the reference echo set limited to a and d with input bubble enabled. This simulates a the model
+echo of a framework that ships with input bubble enabled, and the application with standard R2R rules.
+
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble3_A____ a CG2SingleBubbleADOnly d CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble3_AB___ a CG2SingleBubbleADOnly b CG2Single d CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble3_A_C__ a CG2SingleBubbleADOnly crossboundarytest CG2Single d CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble3_ABC__ a CG2SingleBubbleADOnly b CG2Single crossboundarytest CG2Single d CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble3____D_ d CG2SingleBubbleADOnly
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble3_A__D_ a CG2SingleBubbleADOnly d CG2SingleBubbleADOnly
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble3__B_D_ b CG2Single d CG2SingleBubbleADOnly
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble3_AB_D_ a CG2SingleBubbleADOnly b CG2Single d CG2SingleBubbleADOnly
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble3___CD_ crossboundarytest CG2Single d CG2SingleBubbleADOnly
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble3_A_CD_ a CG2SingleBubbleADOnly crossboundarytest CG2Single d CG2SingleBubbleADOnly
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble3__BCD_ b CG2Single crossboundarytest CG2Single d CG2SingleBubbleADOnly
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble3_ABCD_ a CG2SingleBubbleADOnly b CG2Single crossboundarytest CG2Single d CG2SingleBubbleADOnly
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble3_A___E a CG2SingleBubbleADOnly e CG2Single d CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble3_AB__E a CG2SingleBubbleADOnly b CG2Single e CG2Single d CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble3_A_C_E a CG2SingleBubbleADOnly crossboundarytest CG2Single e CG2Single d CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble3_ABC_E a CG2SingleBubbleADOnly b CG2Single crossboundarytest CG2Single e CG2Single d CG2NoMethods
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble3____DE d CG2SingleBubbleADOnly e CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble3_A__DE a CG2SingleBubbleADOnly d CG2SingleBubbleADOnly e CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble3__B_DE b CG2Single d CG2SingleBubbleADOnly e CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble3_AB_DE a CG2SingleBubbleADOnly b CG2Single d CG2SingleBubbleADOnly e CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble3___CDE crossboundarytest CG2Single d CG2SingleBubbleADOnly e CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble3_A_CDE a CG2SingleBubbleADOnly crossboundarytest CG2Single d CG2SingleBubbleADOnly e CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble3__BCDE b CG2Single crossboundarytest CG2Single d CG2SingleBubbleADOnly e CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2bubble3_ABCDE a CG2SingleBubbleADOnly b CG2Single crossboundarytest CG2Single d CG2SingleBubbleADOnly e CG2Single
+
+goto done
+
+
+:testCG2All
+echo TEST All combinations of compiling standard R2R with the crossgen2 tool instad of crossgen1
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2_A____ a CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2__B___ b CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2_AB___ a CG2Single b CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2___C__ crossboundarytest CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2_A_C__ a CG2Single crossboundarytest CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2__BC__ b CG2Single crossboundarytest CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2_ABC__ a CG2Single b CG2Single crossboundarytest CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2____D_ d CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2_A__D_ a CG2Single d CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2__B_D_ b CG2Single d CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2_AB_D_ a CG2Single b CG2Single d CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2___CD_ crossboundarytest CG2Single d CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2_A_CD_ a CG2Single crossboundarytest CG2Single d CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2__BCD_ b CG2Single crossboundarytest CG2Single d CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2_ABCD_ a CG2Single b CG2Single crossboundarytest CG2Single d CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2_____E e CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2_A___E a CG2Single e CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2__B__E b CG2Single e CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2_AB__E a CG2Single b CG2Single e CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2___C_E crossboundarytest CG2Single e CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2_A_C_E a CG2Single crossboundarytest CG2Single e CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2__BC_E b CG2Single crossboundarytest CG2Single e CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2_ABC_E a CG2Single b CG2Single crossboundarytest CG2Single e CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2____DE d CG2Single e CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2_A__DE a CG2Single d CG2Single e CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2__B_DE b CG2Single d CG2Single e CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2_AB_DE a CG2Single b CG2Single d CG2Single e CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2___CDE crossboundarytest CG2Single d CG2Single e CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2_A_CDE a CG2Single crossboundarytest CG2Single d CG2Single e CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2__BCDE b CG2Single crossboundarytest CG2Single d CG2Single e CG2Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg2_ABCDE a CG2Single b CG2Single crossboundarytest CG2Single d CG2Single e CG2Single
+
+:testCG1All
+echo TEST All combinations of compiling standard R2R with the crossgen tool instad of crossgen2
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg1_A____ a CG1Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg1__B___ b CG1Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg1_AB___ a CG1Single b CG1Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg1___C__ crossboundarytest CG1Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg1_A_C__ a CG1Single crossboundarytest CG1Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg1__BC__ b CG1Single crossboundarytest CG1Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg1_ABC__ a CG1Single b CG1Single crossboundarytest CG1Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg1____D_ d CG1Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg1_A__D_ a CG1Single d CG1Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg1__B_D_ b CG1Single d CG1Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg1_AB_D_ a CG1Single b CG1Single d CG1Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg1___CD_ crossboundarytest CG1Single d CG1Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg1_A_CD_ a CG1Single crossboundarytest CG1Single d CG1Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg1__BCD_ b CG1Single crossboundarytest CG1Single d CG1Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg1_ABCD_ a CG1Single b CG1Single crossboundarytest CG1Single d CG1Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg1_____E e CG1Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg1_A___E a CG1Single e CG1Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg1__B__E b CG1Single e CG1Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg1_AB__E a CG1Single b CG1Single e CG1Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg1___C_E crossboundarytest CG1Single e CG1Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg1_A_C_E a CG1Single crossboundarytest CG1Single e CG1Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg1__BC_E b CG1Single crossboundarytest CG1Single e CG1Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg1_ABC_E a CG1Single b CG1Single crossboundarytest CG1Single e CG1Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg1____DE d CG1Single e CG1Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg1_A__DE a CG1Single d CG1Single e CG1Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg1__B_DE b CG1Single d CG1Single e CG1Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg1_AB_DE a CG1Single b CG1Single d CG1Single e CG1Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg1___CDE crossboundarytest CG1Single d CG1Single e CG1Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg1_A_CDE a CG1Single crossboundarytest CG1Single d CG1Single e CG1Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg1__BCDE b CG1Single crossboundarytest CG1Single d CG1Single e CG1Single
+call %TESTBATCHROOT%\runindividualtest.cmd %TESTBATCHROOT% %TESTDIR% cg1_ABCDE a CG1Single b CG1Single crossboundarytest CG1Single d CG1Single e CG1Single
+
+
+goto done
+
+:done
diff --git a/src/coreclr/tests/src/readytorun/crossboundarylayout/d/d.cs b/src/coreclr/tests/src/readytorun/crossboundarylayout/d/d.cs
new file mode 100644
index 00000000000000..9d6b8bd8ab1667
--- /dev/null
+++ b/src/coreclr/tests/src/readytorun/crossboundarylayout/d/d.cs
@@ -0,0 +1,13 @@
+// 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 CrossBoundaryLayout
+{
+ public struct ByteStruct
+ {
+ public byte _dVal;
+ }
+}
\ No newline at end of file
diff --git a/src/coreclr/tests/src/readytorun/crossboundarylayout/d/d.csproj b/src/coreclr/tests/src/readytorun/crossboundarylayout/d/d.csproj
new file mode 100644
index 00000000000000..09eb1e5530790e
--- /dev/null
+++ b/src/coreclr/tests/src/readytorun/crossboundarylayout/d/d.csproj
@@ -0,0 +1,10 @@
+
+
+ library
+ SharedLibrary
+
+
+
+
+
+
diff --git a/src/coreclr/tests/src/readytorun/crossboundarylayout/e/e.cs b/src/coreclr/tests/src/readytorun/crossboundarylayout/e/e.cs
new file mode 100644
index 00000000000000..bbbc3387f43c6b
--- /dev/null
+++ b/src/coreclr/tests/src/readytorun/crossboundarylayout/e/e.cs
@@ -0,0 +1,13 @@
+// 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 CrossBoundaryLayout
+{
+ public struct ByteStructE
+ {
+ public byte _eVal;
+ }
+}
\ No newline at end of file
diff --git a/src/coreclr/tests/src/readytorun/crossboundarylayout/e/e.csproj b/src/coreclr/tests/src/readytorun/crossboundarylayout/e/e.csproj
new file mode 100644
index 00000000000000..3e752d68f2ea7e
--- /dev/null
+++ b/src/coreclr/tests/src/readytorun/crossboundarylayout/e/e.csproj
@@ -0,0 +1,10 @@
+
+
+ library
+ SharedLibrary
+
+
+
+
+
+
diff --git a/src/coreclr/tests/src/readytorun/crossboundarylayout/runindividualtest.cmd b/src/coreclr/tests/src/readytorun/crossboundarylayout/runindividualtest.cmd
new file mode 100644
index 00000000000000..55d86f9e91e057
--- /dev/null
+++ b/src/coreclr/tests/src/readytorun/crossboundarylayout/runindividualtest.cmd
@@ -0,0 +1,14 @@
+setlocal
+rd /s /q %2\%3 2> nul
+md %2\%3
+copy %2\* %2\%3 > nul
+call %1\buildcrossgen2image.cmd %*
+@echo on
+%CORE_ROOT%\corerun %2\%3\crossboundarytest.dll
+@echo off
+if %ERRORLEVEL% NEQ 100 (
+ echo FAILED
+ goto done
+)
+echo PASSED
+:done
\ No newline at end of file