Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,34 +5,33 @@

using Internal.TypeSystem;

using Debug = System.Diagnostics.Debug;

namespace ILCompiler
{
public partial class CompilerTypeSystemContext
{
private readonly object _structCacheLock = new object();
private readonly Dictionary<int, TypeDesc> _structsBySize = new Dictionary<int, TypeDesc>();
private volatile TypeDesc _cachedEmptyStruct;
private volatile TypeDesc _cachedV128Type;

/// <summary>
/// Gets the first SIMD v128 type encountered during lowering, or null if none has been seen.
/// Used by RaiseSignature to produce a roundtrippable type for the 'V' encoding.
/// </summary>
public TypeDesc CachedV128Type => _cachedV128Type;
private volatile TypeDesc _wasmV128Type;

/// <summary>
/// Caches a SIMD v128 type discovered during lowering. Only the first one is retained.
/// Gets the type RaiseSignature produces for the 'V' encoding. All v128 types share the same
/// wasm ABI (16 bytes, 16-byte aligned), so any one of them round-trips 'V' identically;
/// resolving a fixed one keeps raising independent of the order lowering encountered them in.
/// </summary>
public void CacheV128Type(TypeDesc type)
public TypeDesc WasmV128Type
{
// All v128 types share the same wasm ABI (16-byte aligned), so any one round-trips the
// 'V' encoding identically; a smaller alignment would change raised signatures silently.
Debug.Assert(type is DefType defType && defType.InstanceFieldAlignment.AsInt == 16,
$"v128 type {type} must be 16-byte aligned to be interchangeable in raised signatures");
get
{
TypeDesc type = _wasmV128Type;
if (type is null)
{
var vector128 = (MetadataType)SystemModule.GetType("System.Runtime.Intrinsics"u8, "Vector128`1"u8);
_wasmV128Type = type = vector128.MakeInstantiatedType(GetWellKnownType(WellKnownType.Byte));
}

_cachedV128Type ??= type;
return type;
}
}

/// <summary>
Expand Down
34 changes: 14 additions & 20 deletions src/coreclr/tools/Common/JitInterface/WasmLowering.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -123,17 +123,21 @@ private static bool IsWasmV128Type(TypeDesc type)
}

// Vector128<T> is always a 16-byte v128.
if (Internal.TypeSystem.Interop.InteropTypes.IsSystemRuntimeIntrinsicsVector128T(type.Context, type))
{
return true;
}

//
// Vector<T> is target-sized, so it is only a v128 when the target's maximum SIMD width is
// 128-bit (i.e. it is exactly 16 bytes). This matches the JIT recognizing it as TYP_SIMD16
// via getVectorTByteLength() and keeps the ABI correct should wasm later gain wider vectors.
return type is DefType vectorOfT &&
VectorOfTFieldLayoutAlgorithm.IsVectorOfTType(vectorOfT) &&
type.GetElementSize().AsInt == 16;
bool isV128 = Internal.TypeSystem.Interop.InteropTypes.IsSystemRuntimeIntrinsicsVector128T(type.Context, type) ||
(type is DefType vectorOfT &&
VectorOfTFieldLayoutAlgorithm.IsVectorOfTType(vectorOfT) &&
type.GetElementSize().AsInt == 16);

// The wasm ABI gives every v128 a 16-byte aligned argument slot, so a smaller metadata
// alignment would silently misplace it relative to the runtime's own ArgIterator layout.
Debug.Assert(!isV128 || ((DefType)type).InstanceFieldAlignment.AsInt == 16,
$"v128 type {type} must be 16-byte aligned");

return isV128;
}

public static WasmValueType LowerType(TypeDesc type)
Expand DownExpand Up@@ -219,8 +223,7 @@ public static WasmValueType LowerType(TypeDesc type)
'l' => context.GetWellKnownType(WellKnownType.Int64),
'f' => context.GetWellKnownType(WellKnownType.Single),
'd' => context.GetWellKnownType(WellKnownType.Double),
'V' => ((CompilerTypeSystemContext)context).CachedV128Type
?? throw new InvalidOperationException("Encountered 'V' in signature but no v128 type was cached during lowering"),
'V' => ((CompilerTypeSystemContext)context).WasmV128Type,
_ => throw new InvalidOperationException($"Unknown signature char: {c}")
};

Expand DownExpand Up@@ -402,12 +405,7 @@ public static WasmSignature GetSignature(MethodSignature signature, LoweringFlag
}
else
{
WasmValueType returnWasmType = LowerType(loweredReturnType);
if (returnWasmType == WasmValueType.V128)
{
((CompilerTypeSystemContext)returnType.Context).CacheV128Type(loweredReturnType);
}
sigBuilder.Append(WasmValueTypeToSigChar(returnWasmType));
sigBuilder.Append(WasmValueTypeToSigChar(LowerType(loweredReturnType)));
}

// Reserve space for potential implicit this, stack pointer parameter, portable entrypoint parameter,
Expand DownExpand Up@@ -484,10 +482,6 @@ public static WasmSignature GetSignature(MethodSignature signature, LoweringFlag
else
{
WasmValueType paramWasmType = LowerType(loweredParamType);
if (paramWasmType == WasmValueType.V128)
{
((CompilerTypeSystemContext)paramType.Context).CacheV128Type(loweredParamType);
}
sigBuilder.Append(WasmValueTypeToSigChar(paramWasmType));
result.Add(paramWasmType);
}
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -21,6 +21,9 @@

<ItemGroup>
<ProjectReference Include="../ILCompiler.Reflection.ReadyToRun/ILCompiler.Reflection.ReadyToRun.csproj" />
<!-- Aliased because it redefines the ReadyToRun* constant enums that
ILCompiler.Reflection.ReadyToRun already brings into the global namespace. -->
<ProjectReference Include="../ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj" Aliases="crossgen2" />
<ProjectReference Include="../crossgen2/crossgen2_inbuild.csproj" ReferenceOutputAssembly="false">
<!-- crossgen2 is a CoreCLR artifact, so publish it in the CoreCLR configuration. This keeps it
alongside the other CoreCLR artifacts the test consumes (System.Private.CoreLib, the JITs)
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -341,21 +341,7 @@ private List<string> BuildReferencePaths()

paths.Add(Path.Combine(_paths.RuntimePackDir, "*.dll"));

// SPCL lives in the runtime pack native/ dir in full builds (placed by
// externals.csproj BinPlace during libs.pretest). In partial CI builds
// that skip libs.pretest, the runtime pack layout may not exist, but the
// CoreCLR artifacts directory always has SPCL after clr.nativecorelib.
string spcl = Path.Combine(_paths.RuntimePackNativeDir, "System.Private.CoreLib.dll");
if (!File.Exists(spcl))
{
string fallback = Path.Combine(_paths.CoreCLRArtifactsDir, "System.Private.CoreLib.dll");
if (File.Exists(fallback))
{
_output.WriteLine($"[R2RTestRunner] SPCL not found at '{spcl}'; using CoreCLR artifacts fallback '{fallback}'");
spcl = fallback;
}
}

string spcl = _paths.SystemPrivateCoreLibPath;
Assert.True(File.Exists(spcl),
$"System.Private.CoreLib.dll not found at '{spcl}'. " +
$"Searched RuntimePackNativeDir='{_paths.RuntimePackNativeDir}' and " +
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -133,6 +133,30 @@ public string RuntimePackNativeDir
}
}

/// <summary>
/// Path to System.Private.CoreLib.dll. It lives in the runtime pack native/ dir in full builds
/// (placed by externals.csproj BinPlace during libs.pretest), but partial builds that skip
/// libs.pretest only have it in the CoreCLR artifacts directory.
/// </summary>
public string SystemPrivateCoreLibPath
{
get
{
string path = Path.Combine(RuntimePackNativeDir, "System.Private.CoreLib.dll");
if (!File.Exists(path))
{
string fallback = Path.Combine(CoreCLRArtifactsDir, "System.Private.CoreLib.dll");
if (File.Exists(fallback))
{
_output.WriteLine($"[TestPaths] '{path}' not found; falling back to '{fallback}'");
return fallback;
}
}

return path;
}
}

/// <summary>
/// Path to the CoreCLR artifacts directory (contains native bits like corerun).
/// e.g. artifacts/bin/coreclr/linux.x64.Checked/
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,34 +5,33 @@

using Internal.TypeSystem;

using Debug = System.Diagnostics.Debug;

namespace ILCompiler
{
public partial class CompilerTypeSystemContext
{
private readonly object _structCacheLock = new object();
private readonly Dictionary<int, TypeDesc> _structsBySize = new Dictionary<int, TypeDesc>();
private volatile TypeDesc _cachedEmptyStruct;
private volatile TypeDesc _cachedV128Type;

/// <summary>
/// Gets the first SIMD v128 type encountered during lowering, or null if none has been seen.
/// Used by RaiseSignature to produce a roundtrippable type for the 'V' encoding.
/// </summary>
public TypeDesc CachedV128Type => _cachedV128Type;
private volatile TypeDesc _wasmV128Type;

/// <summary>
/// Caches a SIMD v128 type discovered during lowering. Only the first one is retained.
/// Gets the type RaiseSignature produces for the 'V' encoding. All v128 types share the same
/// wasm ABI (16 bytes, 16-byte aligned), so any one of them round-trips 'V' identically;
/// resolving a fixed one keeps raising independent of the order lowering encountered them in.
/// </summary>
public void CacheV128Type(TypeDesc type)
public TypeDesc WasmV128Type
{
// All v128 types share the same wasm ABI (16-byte aligned), so any one round-trips the
// 'V' encoding identically; a smaller alignment would change raised signatures silently.
Debug.Assert(type is DefType defType && defType.InstanceFieldAlignment.AsInt == 16,
$"v128 type {type} must be 16-byte aligned to be interchangeable in raised signatures");
get
{
TypeDesc type = _wasmV128Type;
if (type is null)
{
var vector128 = (MetadataType)SystemModule.GetType("System.Runtime.Intrinsics"u8, "Vector128`1"u8);
_wasmV128Type = type = vector128.MakeInstantiatedType(GetWellKnownType(WellKnownType.Byte));
}

_cachedV128Type ??= type;
return type;
}
}

/// <summary>
Expand Down
34 changes: 14 additions & 20 deletions src/coreclr/tools/Common/JitInterface/WasmLowering.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -123,17 +123,21 @@ private static bool IsWasmV128Type(TypeDesc type)
}

// Vector128<T> is always a 16-byte v128.
if (Internal.TypeSystem.Interop.InteropTypes.IsSystemRuntimeIntrinsicsVector128T(type.Context, type))
{
return true;
}

//
// Vector<T> is target-sized, so it is only a v128 when the target's maximum SIMD width is
// 128-bit (i.e. it is exactly 16 bytes). This matches the JIT recognizing it as TYP_SIMD16
// via getVectorTByteLength() and keeps the ABI correct should wasm later gain wider vectors.
return type is DefType vectorOfT &&
VectorOfTFieldLayoutAlgorithm.IsVectorOfTType(vectorOfT) &&
type.GetElementSize().AsInt == 16;
bool isV128 = Internal.TypeSystem.Interop.InteropTypes.IsSystemRuntimeIntrinsicsVector128T(type.Context, type) ||
(type is DefType vectorOfT &&
VectorOfTFieldLayoutAlgorithm.IsVectorOfTType(vectorOfT) &&
type.GetElementSize().AsInt == 16);

// The wasm ABI gives every v128 a 16-byte aligned argument slot, so a smaller metadata
// alignment would silently misplace it relative to the runtime's own ArgIterator layout.
Debug.Assert(!isV128 || ((DefType)type).InstanceFieldAlignment.AsInt == 16,
$"v128 type {type} must be 16-byte aligned");

return isV128;
}

public static WasmValueType LowerType(TypeDesc type)
Expand DownExpand Up@@ -219,8 +223,7 @@ public static WasmValueType LowerType(TypeDesc type)
'l' => context.GetWellKnownType(WellKnownType.Int64),
'f' => context.GetWellKnownType(WellKnownType.Single),
'd' => context.GetWellKnownType(WellKnownType.Double),
'V' => ((CompilerTypeSystemContext)context).CachedV128Type
?? throw new InvalidOperationException("Encountered 'V' in signature but no v128 type was cached during lowering"),
'V' => ((CompilerTypeSystemContext)context).WasmV128Type,
_ => throw new InvalidOperationException($"Unknown signature char: {c}")
};

Expand DownExpand Up@@ -402,12 +405,7 @@ public static WasmSignature GetSignature(MethodSignature signature, LoweringFlag
}
else
{
WasmValueType returnWasmType = LowerType(loweredReturnType);
if (returnWasmType == WasmValueType.V128)
{
((CompilerTypeSystemContext)returnType.Context).CacheV128Type(loweredReturnType);
}
sigBuilder.Append(WasmValueTypeToSigChar(returnWasmType));
sigBuilder.Append(WasmValueTypeToSigChar(LowerType(loweredReturnType)));
}

// Reserve space for potential implicit this, stack pointer parameter, portable entrypoint parameter,
Expand DownExpand Up@@ -484,10 +482,6 @@ public static WasmSignature GetSignature(MethodSignature signature, LoweringFlag
else
{
WasmValueType paramWasmType = LowerType(loweredParamType);
if (paramWasmType == WasmValueType.V128)
{
((CompilerTypeSystemContext)paramType.Context).CacheV128Type(loweredParamType);
}
sigBuilder.Append(WasmValueTypeToSigChar(paramWasmType));
result.Add(paramWasmType);
}
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -21,6 +21,9 @@

<ItemGroup>
<ProjectReference Include="../ILCompiler.Reflection.ReadyToRun/ILCompiler.Reflection.ReadyToRun.csproj" />
<!-- Aliased because it redefines the ReadyToRun* constant enums that
ILCompiler.Reflection.ReadyToRun already brings into the global namespace. -->
<ProjectReference Include="../ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj" Aliases="crossgen2" />
<ProjectReference Include="../crossgen2/crossgen2_inbuild.csproj" ReferenceOutputAssembly="false">
<!-- crossgen2 is a CoreCLR artifact, so publish it in the CoreCLR configuration. This keeps it
alongside the other CoreCLR artifacts the test consumes (System.Private.CoreLib, the JITs)
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -341,21 +341,7 @@ private List<string> BuildReferencePaths()

paths.Add(Path.Combine(_paths.RuntimePackDir, "*.dll"));

// SPCL lives in the runtime pack native/ dir in full builds (placed by
// externals.csproj BinPlace during libs.pretest). In partial CI builds
// that skip libs.pretest, the runtime pack layout may not exist, but the
// CoreCLR artifacts directory always has SPCL after clr.nativecorelib.
string spcl = Path.Combine(_paths.RuntimePackNativeDir, "System.Private.CoreLib.dll");
if (!File.Exists(spcl))
{
string fallback = Path.Combine(_paths.CoreCLRArtifactsDir, "System.Private.CoreLib.dll");
if (File.Exists(fallback))
{
_output.WriteLine($"[R2RTestRunner] SPCL not found at '{spcl}'; using CoreCLR artifacts fallback '{fallback}'");
spcl = fallback;
}
}

string spcl = _paths.SystemPrivateCoreLibPath;
Assert.True(File.Exists(spcl),
$"System.Private.CoreLib.dll not found at '{spcl}'. " +
$"Searched RuntimePackNativeDir='{_paths.RuntimePackNativeDir}' and " +
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -133,6 +133,30 @@ public string RuntimePackNativeDir
}
}

/// <summary>
/// Path to System.Private.CoreLib.dll. It lives in the runtime pack native/ dir in full builds
/// (placed by externals.csproj BinPlace during libs.pretest), but partial builds that skip
/// libs.pretest only have it in the CoreCLR artifacts directory.
/// </summary>
public string SystemPrivateCoreLibPath
{
get
{
string path = Path.Combine(RuntimePackNativeDir, "System.Private.CoreLib.dll");
if (!File.Exists(path))
{
string fallback = Path.Combine(CoreCLRArtifactsDir, "System.Private.CoreLib.dll");
if (File.Exists(fallback))
{
_output.WriteLine($"[TestPaths] '{path}' not found; falling back to '{fallback}'");
return fallback;
}
}

return path;
}
}

/// <summary>
/// Path to the CoreCLR artifacts directory (contains native bits like corerun).
/// e.g. artifacts/bin/coreclr/linux.x64.Checked/
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,34 +5,33 @@

using Internal.TypeSystem;

using Debug = System.Diagnostics.Debug;

namespace ILCompiler
{
public partial class CompilerTypeSystemContext
{
private readonly object _structCacheLock = new object();
private readonly Dictionary<int, TypeDesc> _structsBySize = new Dictionary<int, TypeDesc>();
private volatile TypeDesc _cachedEmptyStruct;
private volatile TypeDesc _cachedV128Type;

/// <summary>
/// Gets the first SIMD v128 type encountered during lowering, or null if none has been seen.
/// Used by RaiseSignature to produce a roundtrippable type for the 'V' encoding.
/// </summary>
public TypeDesc CachedV128Type => _cachedV128Type;
private volatile TypeDesc _wasmV128Type;

/// <summary>
/// Caches a SIMD v128 type discovered during lowering. Only the first one is retained.
/// Gets the type RaiseSignature produces for the 'V' encoding. All v128 types share the same
/// wasm ABI (16 bytes, 16-byte aligned), so any one of them round-trips 'V' identically;
/// resolving a fixed one keeps raising independent of the order lowering encountered them in.
/// </summary>
public void CacheV128Type(TypeDesc type)
public TypeDesc WasmV128Type
{
// All v128 types share the same wasm ABI (16-byte aligned), so any one round-trips the
// 'V' encoding identically; a smaller alignment would change raised signatures silently.
Debug.Assert(type is DefType defType && defType.InstanceFieldAlignment.AsInt == 16,
$"v128 type {type} must be 16-byte aligned to be interchangeable in raised signatures");
get
{
TypeDesc type = _wasmV128Type;
if (type is null)
{
var vector128 = (MetadataType)SystemModule.GetType("System.Runtime.Intrinsics"u8, "Vector128`1"u8);
_wasmV128Type = type = vector128.MakeInstantiatedType(GetWellKnownType(WellKnownType.Byte));
}

_cachedV128Type ??= type;
return type;
}
}

/// <summary>
Expand Down
34 changes: 14 additions & 20 deletions src/coreclr/tools/Common/JitInterface/WasmLowering.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -123,17 +123,21 @@ private static bool IsWasmV128Type(TypeDesc type)
}

// Vector128<T> is always a 16-byte v128.
if (Internal.TypeSystem.Interop.InteropTypes.IsSystemRuntimeIntrinsicsVector128T(type.Context, type))
{
return true;
}

//
// Vector<T> is target-sized, so it is only a v128 when the target's maximum SIMD width is
// 128-bit (i.e. it is exactly 16 bytes). This matches the JIT recognizing it as TYP_SIMD16
// via getVectorTByteLength() and keeps the ABI correct should wasm later gain wider vectors.
return type is DefType vectorOfT &&
VectorOfTFieldLayoutAlgorithm.IsVectorOfTType(vectorOfT) &&
type.GetElementSize().AsInt == 16;
bool isV128 = Internal.TypeSystem.Interop.InteropTypes.IsSystemRuntimeIntrinsicsVector128T(type.Context, type) ||
(type is DefType vectorOfT &&
VectorOfTFieldLayoutAlgorithm.IsVectorOfTType(vectorOfT) &&
type.GetElementSize().AsInt == 16);

// The wasm ABI gives every v128 a 16-byte aligned argument slot, so a smaller metadata
// alignment would silently misplace it relative to the runtime's own ArgIterator layout.
Debug.Assert(!isV128 || ((DefType)type).InstanceFieldAlignment.AsInt == 16,
$"v128 type {type} must be 16-byte aligned");

return isV128;
}

public static WasmValueType LowerType(TypeDesc type)
Expand DownExpand Up@@ -219,8 +223,7 @@ public static WasmValueType LowerType(TypeDesc type)
'l' => context.GetWellKnownType(WellKnownType.Int64),
'f' => context.GetWellKnownType(WellKnownType.Single),
'd' => context.GetWellKnownType(WellKnownType.Double),
'V' => ((CompilerTypeSystemContext)context).CachedV128Type
?? throw new InvalidOperationException("Encountered 'V' in signature but no v128 type was cached during lowering"),
'V' => ((CompilerTypeSystemContext)context).WasmV128Type,
_ => throw new InvalidOperationException($"Unknown signature char: {c}")
};

Expand DownExpand Up@@ -402,12 +405,7 @@ public static WasmSignature GetSignature(MethodSignature signature, LoweringFlag
}
else
{
WasmValueType returnWasmType = LowerType(loweredReturnType);
if (returnWasmType == WasmValueType.V128)
{
((CompilerTypeSystemContext)returnType.Context).CacheV128Type(loweredReturnType);
}
sigBuilder.Append(WasmValueTypeToSigChar(returnWasmType));
sigBuilder.Append(WasmValueTypeToSigChar(LowerType(loweredReturnType)));
}

// Reserve space for potential implicit this, stack pointer parameter, portable entrypoint parameter,
Expand DownExpand Up@@ -484,10 +482,6 @@ public static WasmSignature GetSignature(MethodSignature signature, LoweringFlag
else
{
WasmValueType paramWasmType = LowerType(loweredParamType);
if (paramWasmType == WasmValueType.V128)
{
((CompilerTypeSystemContext)paramType.Context).CacheV128Type(loweredParamType);
}
sigBuilder.Append(WasmValueTypeToSigChar(paramWasmType));
result.Add(paramWasmType);
}
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -21,6 +21,9 @@

<ItemGroup>
<ProjectReference Include="../ILCompiler.Reflection.ReadyToRun/ILCompiler.Reflection.ReadyToRun.csproj" />
<!-- Aliased because it redefines the ReadyToRun* constant enums that
ILCompiler.Reflection.ReadyToRun already brings into the global namespace. -->
<ProjectReference Include="../ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj" Aliases="crossgen2" />
<ProjectReference Include="../crossgen2/crossgen2_inbuild.csproj" ReferenceOutputAssembly="false">
<!-- crossgen2 is a CoreCLR artifact, so publish it in the CoreCLR configuration. This keeps it
alongside the other CoreCLR artifacts the test consumes (System.Private.CoreLib, the JITs)
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -341,21 +341,7 @@ private List<string> BuildReferencePaths()

paths.Add(Path.Combine(_paths.RuntimePackDir, "*.dll"));

// SPCL lives in the runtime pack native/ dir in full builds (placed by
// externals.csproj BinPlace during libs.pretest). In partial CI builds
// that skip libs.pretest, the runtime pack layout may not exist, but the
// CoreCLR artifacts directory always has SPCL after clr.nativecorelib.
string spcl = Path.Combine(_paths.RuntimePackNativeDir, "System.Private.CoreLib.dll");
if (!File.Exists(spcl))
{
string fallback = Path.Combine(_paths.CoreCLRArtifactsDir, "System.Private.CoreLib.dll");
if (File.Exists(fallback))
{
_output.WriteLine($"[R2RTestRunner] SPCL not found at '{spcl}'; using CoreCLR artifacts fallback '{fallback}'");
spcl = fallback;
}
}

string spcl = _paths.SystemPrivateCoreLibPath;
Assert.True(File.Exists(spcl),
$"System.Private.CoreLib.dll not found at '{spcl}'. " +
$"Searched RuntimePackNativeDir='{_paths.RuntimePackNativeDir}' and " +
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -133,6 +133,30 @@ public string RuntimePackNativeDir
}
}

/// <summary>
/// Path to System.Private.CoreLib.dll. It lives in the runtime pack native/ dir in full builds
/// (placed by externals.csproj BinPlace during libs.pretest), but partial builds that skip
/// libs.pretest only have it in the CoreCLR artifacts directory.
/// </summary>
public string SystemPrivateCoreLibPath
{
get
{
string path = Path.Combine(RuntimePackNativeDir, "System.Private.CoreLib.dll");
if (!File.Exists(path))
{
string fallback = Path.Combine(CoreCLRArtifactsDir, "System.Private.CoreLib.dll");
if (File.Exists(fallback))
{
_output.WriteLine($"[TestPaths] '{path}' not found; falling back to '{fallback}'");
return fallback;
}
}

return path;
}
}

/// <summary>
/// Path to the CoreCLR artifacts directory (contains native bits like corerun).
/// e.g. artifacts/bin/coreclr/linux.x64.Checked/
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,34 +5,33 @@

using Internal.TypeSystem;

using Debug = System.Diagnostics.Debug;

namespace ILCompiler
{
public partial class CompilerTypeSystemContext
{
private readonly object _structCacheLock = new object();
private readonly Dictionary<int, TypeDesc> _structsBySize = new Dictionary<int, TypeDesc>();
private volatile TypeDesc _cachedEmptyStruct;
private volatile TypeDesc _cachedV128Type;

/// <summary>
/// Gets the first SIMD v128 type encountered during lowering, or null if none has been seen.
/// Used by RaiseSignature to produce a roundtrippable type for the 'V' encoding.
/// </summary>
public TypeDesc CachedV128Type => _cachedV128Type;
private volatile TypeDesc _wasmV128Type;

/// <summary>
/// Caches a SIMD v128 type discovered during lowering. Only the first one is retained.
/// Gets the type RaiseSignature produces for the 'V' encoding. All v128 types share the same
/// wasm ABI (16 bytes, 16-byte aligned), so any one of them round-trips 'V' identically;
/// resolving a fixed one keeps raising independent of the order lowering encountered them in.
/// </summary>
public void CacheV128Type(TypeDesc type)
public TypeDesc WasmV128Type
{
// All v128 types share the same wasm ABI (16-byte aligned), so any one round-trips the
// 'V' encoding identically; a smaller alignment would change raised signatures silently.
Debug.Assert(type is DefType defType && defType.InstanceFieldAlignment.AsInt == 16,
$"v128 type {type} must be 16-byte aligned to be interchangeable in raised signatures");
get
{
TypeDesc type = _wasmV128Type;
if (type is null)
{
var vector128 = (MetadataType)SystemModule.GetType("System.Runtime.Intrinsics"u8, "Vector128`1"u8);
_wasmV128Type = type = vector128.MakeInstantiatedType(GetWellKnownType(WellKnownType.Byte));
}

_cachedV128Type ??= type;
return type;
}
}

/// <summary>
Expand Down
34 changes: 14 additions & 20 deletions src/coreclr/tools/Common/JitInterface/WasmLowering.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -123,17 +123,21 @@ private static bool IsWasmV128Type(TypeDesc type)
}

// Vector128<T> is always a 16-byte v128.
if (Internal.TypeSystem.Interop.InteropTypes.IsSystemRuntimeIntrinsicsVector128T(type.Context, type))
{
return true;
}

//
// Vector<T> is target-sized, so it is only a v128 when the target's maximum SIMD width is
// 128-bit (i.e. it is exactly 16 bytes). This matches the JIT recognizing it as TYP_SIMD16
// via getVectorTByteLength() and keeps the ABI correct should wasm later gain wider vectors.
return type is DefType vectorOfT &&
VectorOfTFieldLayoutAlgorithm.IsVectorOfTType(vectorOfT) &&
type.GetElementSize().AsInt == 16;
bool isV128 = Internal.TypeSystem.Interop.InteropTypes.IsSystemRuntimeIntrinsicsVector128T(type.Context, type) ||
(type is DefType vectorOfT &&
VectorOfTFieldLayoutAlgorithm.IsVectorOfTType(vectorOfT) &&
type.GetElementSize().AsInt == 16);

// The wasm ABI gives every v128 a 16-byte aligned argument slot, so a smaller metadata
// alignment would silently misplace it relative to the runtime's own ArgIterator layout.
Debug.Assert(!isV128 || ((DefType)type).InstanceFieldAlignment.AsInt == 16,
$"v128 type {type} must be 16-byte aligned");

return isV128;
}

public static WasmValueType LowerType(TypeDesc type)
Expand DownExpand Up@@ -219,8 +223,7 @@ public static WasmValueType LowerType(TypeDesc type)
'l' => context.GetWellKnownType(WellKnownType.Int64),
'f' => context.GetWellKnownType(WellKnownType.Single),
'd' => context.GetWellKnownType(WellKnownType.Double),
'V' => ((CompilerTypeSystemContext)context).CachedV128Type
?? throw new InvalidOperationException("Encountered 'V' in signature but no v128 type was cached during lowering"),
'V' => ((CompilerTypeSystemContext)context).WasmV128Type,
_ => throw new InvalidOperationException($"Unknown signature char: {c}")
};

Expand DownExpand Up@@ -402,12 +405,7 @@ public static WasmSignature GetSignature(MethodSignature signature, LoweringFlag
}
else
{
WasmValueType returnWasmType = LowerType(loweredReturnType);
if (returnWasmType == WasmValueType.V128)
{
((CompilerTypeSystemContext)returnType.Context).CacheV128Type(loweredReturnType);
}
sigBuilder.Append(WasmValueTypeToSigChar(returnWasmType));
sigBuilder.Append(WasmValueTypeToSigChar(LowerType(loweredReturnType)));
}

// Reserve space for potential implicit this, stack pointer parameter, portable entrypoint parameter,
Expand DownExpand Up@@ -484,10 +482,6 @@ public static WasmSignature GetSignature(MethodSignature signature, LoweringFlag
else
{
WasmValueType paramWasmType = LowerType(loweredParamType);
if (paramWasmType == WasmValueType.V128)
{
((CompilerTypeSystemContext)paramType.Context).CacheV128Type(loweredParamType);
}
sigBuilder.Append(WasmValueTypeToSigChar(paramWasmType));
result.Add(paramWasmType);
}
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -21,6 +21,9 @@

<ItemGroup>
<ProjectReference Include="../ILCompiler.Reflection.ReadyToRun/ILCompiler.Reflection.ReadyToRun.csproj" />
<!-- Aliased because it redefines the ReadyToRun* constant enums that
ILCompiler.Reflection.ReadyToRun already brings into the global namespace. -->
<ProjectReference Include="../ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj" Aliases="crossgen2" />
<ProjectReference Include="../crossgen2/crossgen2_inbuild.csproj" ReferenceOutputAssembly="false">
<!-- crossgen2 is a CoreCLR artifact, so publish it in the CoreCLR configuration. This keeps it
alongside the other CoreCLR artifacts the test consumes (System.Private.CoreLib, the JITs)
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -341,21 +341,7 @@ private List<string> BuildReferencePaths()

paths.Add(Path.Combine(_paths.RuntimePackDir, "*.dll"));

// SPCL lives in the runtime pack native/ dir in full builds (placed by
// externals.csproj BinPlace during libs.pretest). In partial CI builds
// that skip libs.pretest, the runtime pack layout may not exist, but the
// CoreCLR artifacts directory always has SPCL after clr.nativecorelib.
string spcl = Path.Combine(_paths.RuntimePackNativeDir, "System.Private.CoreLib.dll");
if (!File.Exists(spcl))
{
string fallback = Path.Combine(_paths.CoreCLRArtifactsDir, "System.Private.CoreLib.dll");
if (File.Exists(fallback))
{
_output.WriteLine($"[R2RTestRunner] SPCL not found at '{spcl}'; using CoreCLR artifacts fallback '{fallback}'");
spcl = fallback;
}
}

string spcl = _paths.SystemPrivateCoreLibPath;
Assert.True(File.Exists(spcl),
$"System.Private.CoreLib.dll not found at '{spcl}'. " +
$"Searched RuntimePackNativeDir='{_paths.RuntimePackNativeDir}' and " +
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -133,6 +133,30 @@ public string RuntimePackNativeDir
}
}

/// <summary>
/// Path to System.Private.CoreLib.dll. It lives in the runtime pack native/ dir in full builds
/// (placed by externals.csproj BinPlace during libs.pretest), but partial builds that skip
/// libs.pretest only have it in the CoreCLR artifacts directory.
/// </summary>
public string SystemPrivateCoreLibPath
{
get
{
string path = Path.Combine(RuntimePackNativeDir, "System.Private.CoreLib.dll");
if (!File.Exists(path))
{
string fallback = Path.Combine(CoreCLRArtifactsDir, "System.Private.CoreLib.dll");
if (File.Exists(fallback))
{
_output.WriteLine($"[TestPaths] '{path}' not found; falling back to '{fallback}'");
return fallback;
}
}

return path;
}
}

/// <summary>
/// Path to the CoreCLR artifacts directory (contains native bits like corerun).
/// e.g. artifacts/bin/coreclr/linux.x64.Checked/
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,34 +5,33 @@

using Internal.TypeSystem;

using Debug = System.Diagnostics.Debug;

namespace ILCompiler
{
public partial class CompilerTypeSystemContext
{
private readonly object _structCacheLock = new object();
private readonly Dictionary<int, TypeDesc> _structsBySize = new Dictionary<int, TypeDesc>();
private volatile TypeDesc _cachedEmptyStruct;
private volatile TypeDesc _cachedV128Type;

/// <summary>
/// Gets the first SIMD v128 type encountered during lowering, or null if none has been seen.
/// Used by RaiseSignature to produce a roundtrippable type for the 'V' encoding.
/// </summary>
public TypeDesc CachedV128Type => _cachedV128Type;
private volatile TypeDesc _wasmV128Type;

/// <summary>
/// Caches a SIMD v128 type discovered during lowering. Only the first one is retained.
/// Gets the type RaiseSignature produces for the 'V' encoding. All v128 types share the same
/// wasm ABI (16 bytes, 16-byte aligned), so any one of them round-trips 'V' identically;
/// resolving a fixed one keeps raising independent of the order lowering encountered them in.
/// </summary>
public void CacheV128Type(TypeDesc type)
public TypeDesc WasmV128Type
{
// All v128 types share the same wasm ABI (16-byte aligned), so any one round-trips the
// 'V' encoding identically; a smaller alignment would change raised signatures silently.
Debug.Assert(type is DefType defType && defType.InstanceFieldAlignment.AsInt == 16,
$"v128 type {type} must be 16-byte aligned to be interchangeable in raised signatures");
get
{
TypeDesc type = _wasmV128Type;
if (type is null)
{
var vector128 = (MetadataType)SystemModule.GetType("System.Runtime.Intrinsics"u8, "Vector128`1"u8);
_wasmV128Type = type = vector128.MakeInstantiatedType(GetWellKnownType(WellKnownType.Byte));
}

_cachedV128Type ??= type;
return type;
}
}

/// <summary>
Expand Down
34 changes: 14 additions & 20 deletions src/coreclr/tools/Common/JitInterface/WasmLowering.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -123,17 +123,21 @@ private static bool IsWasmV128Type(TypeDesc type)
}

// Vector128<T> is always a 16-byte v128.
if (Internal.TypeSystem.Interop.InteropTypes.IsSystemRuntimeIntrinsicsVector128T(type.Context, type))
{
return true;
}

//
// Vector<T> is target-sized, so it is only a v128 when the target's maximum SIMD width is
// 128-bit (i.e. it is exactly 16 bytes). This matches the JIT recognizing it as TYP_SIMD16
// via getVectorTByteLength() and keeps the ABI correct should wasm later gain wider vectors.
return type is DefType vectorOfT &&
VectorOfTFieldLayoutAlgorithm.IsVectorOfTType(vectorOfT) &&
type.GetElementSize().AsInt == 16;
bool isV128 = Internal.TypeSystem.Interop.InteropTypes.IsSystemRuntimeIntrinsicsVector128T(type.Context, type) ||
(type is DefType vectorOfT &&
VectorOfTFieldLayoutAlgorithm.IsVectorOfTType(vectorOfT) &&
type.GetElementSize().AsInt == 16);

// The wasm ABI gives every v128 a 16-byte aligned argument slot, so a smaller metadata
// alignment would silently misplace it relative to the runtime's own ArgIterator layout.
Debug.Assert(!isV128 || ((DefType)type).InstanceFieldAlignment.AsInt == 16,
$"v128 type {type} must be 16-byte aligned");

return isV128;
}

public static WasmValueType LowerType(TypeDesc type)
Expand DownExpand Up@@ -219,8 +223,7 @@ public static WasmValueType LowerType(TypeDesc type)
'l' => context.GetWellKnownType(WellKnownType.Int64),
'f' => context.GetWellKnownType(WellKnownType.Single),
'd' => context.GetWellKnownType(WellKnownType.Double),
'V' => ((CompilerTypeSystemContext)context).CachedV128Type
?? throw new InvalidOperationException("Encountered 'V' in signature but no v128 type was cached during lowering"),
'V' => ((CompilerTypeSystemContext)context).WasmV128Type,
_ => throw new InvalidOperationException($"Unknown signature char: {c}")
};

Expand DownExpand Up@@ -402,12 +405,7 @@ public static WasmSignature GetSignature(MethodSignature signature, LoweringFlag
}
else
{
WasmValueType returnWasmType = LowerType(loweredReturnType);
if (returnWasmType == WasmValueType.V128)
{
((CompilerTypeSystemContext)returnType.Context).CacheV128Type(loweredReturnType);
}
sigBuilder.Append(WasmValueTypeToSigChar(returnWasmType));
sigBuilder.Append(WasmValueTypeToSigChar(LowerType(loweredReturnType)));
}

// Reserve space for potential implicit this, stack pointer parameter, portable entrypoint parameter,
Expand DownExpand Up@@ -484,10 +482,6 @@ public static WasmSignature GetSignature(MethodSignature signature, LoweringFlag
else
{
WasmValueType paramWasmType = LowerType(loweredParamType);
if (paramWasmType == WasmValueType.V128)
{
((CompilerTypeSystemContext)paramType.Context).CacheV128Type(loweredParamType);
}
sigBuilder.Append(WasmValueTypeToSigChar(paramWasmType));
result.Add(paramWasmType);
}
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -21,6 +21,9 @@

<ItemGroup>
<ProjectReference Include="../ILCompiler.Reflection.ReadyToRun/ILCompiler.Reflection.ReadyToRun.csproj" />
<!-- Aliased because it redefines the ReadyToRun* constant enums that
ILCompiler.Reflection.ReadyToRun already brings into the global namespace. -->
<ProjectReference Include="../ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj" Aliases="crossgen2" />
<ProjectReference Include="../crossgen2/crossgen2_inbuild.csproj" ReferenceOutputAssembly="false">
<!-- crossgen2 is a CoreCLR artifact, so publish it in the CoreCLR configuration. This keeps it
alongside the other CoreCLR artifacts the test consumes (System.Private.CoreLib, the JITs)
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -341,21 +341,7 @@ private List<string> BuildReferencePaths()

paths.Add(Path.Combine(_paths.RuntimePackDir, "*.dll"));

// SPCL lives in the runtime pack native/ dir in full builds (placed by
// externals.csproj BinPlace during libs.pretest). In partial CI builds
// that skip libs.pretest, the runtime pack layout may not exist, but the
// CoreCLR artifacts directory always has SPCL after clr.nativecorelib.
string spcl = Path.Combine(_paths.RuntimePackNativeDir, "System.Private.CoreLib.dll");
if (!File.Exists(spcl))
{
string fallback = Path.Combine(_paths.CoreCLRArtifactsDir, "System.Private.CoreLib.dll");
if (File.Exists(fallback))
{
_output.WriteLine($"[R2RTestRunner] SPCL not found at '{spcl}'; using CoreCLR artifacts fallback '{fallback}'");
spcl = fallback;
}
}

string spcl = _paths.SystemPrivateCoreLibPath;
Assert.True(File.Exists(spcl),
$"System.Private.CoreLib.dll not found at '{spcl}'. " +
$"Searched RuntimePackNativeDir='{_paths.RuntimePackNativeDir}' and " +
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -133,6 +133,30 @@ public string RuntimePackNativeDir
}
}

/// <summary>
/// Path to System.Private.CoreLib.dll. It lives in the runtime pack native/ dir in full builds
/// (placed by externals.csproj BinPlace during libs.pretest), but partial builds that skip
/// libs.pretest only have it in the CoreCLR artifacts directory.
/// </summary>
public string SystemPrivateCoreLibPath
{
get
{
string path = Path.Combine(RuntimePackNativeDir, "System.Private.CoreLib.dll");
if (!File.Exists(path))
{
string fallback = Path.Combine(CoreCLRArtifactsDir, "System.Private.CoreLib.dll");
if (File.Exists(fallback))
{
_output.WriteLine($"[TestPaths] '{path}' not found; falling back to '{fallback}'");
return fallback;
}
}

return path;
}
}

/// <summary>
/// Path to the CoreCLR artifacts directory (contains native bits like corerun).
/// e.g. artifacts/bin/coreclr/linux.x64.Checked/
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,34 +5,33 @@

using Internal.TypeSystem;

using Debug = System.Diagnostics.Debug;

namespace ILCompiler
{
public partial class CompilerTypeSystemContext
{
private readonly object _structCacheLock = new object();
private readonly Dictionary<int, TypeDesc> _structsBySize = new Dictionary<int, TypeDesc>();
private volatile TypeDesc _cachedEmptyStruct;
private volatile TypeDesc _cachedV128Type;

/// <summary>
/// Gets the first SIMD v128 type encountered during lowering, or null if none has been seen.
/// Used by RaiseSignature to produce a roundtrippable type for the 'V' encoding.
/// </summary>
public TypeDesc CachedV128Type => _cachedV128Type;
private volatile TypeDesc _wasmV128Type;

/// <summary>
/// Caches a SIMD v128 type discovered during lowering. Only the first one is retained.
/// Gets the type RaiseSignature produces for the 'V' encoding. All v128 types share the same
/// wasm ABI (16 bytes, 16-byte aligned), so any one of them round-trips 'V' identically;
/// resolving a fixed one keeps raising independent of the order lowering encountered them in.
/// </summary>
public void CacheV128Type(TypeDesc type)
public TypeDesc WasmV128Type
{
// All v128 types share the same wasm ABI (16-byte aligned), so any one round-trips the
// 'V' encoding identically; a smaller alignment would change raised signatures silently.
Debug.Assert(type is DefType defType && defType.InstanceFieldAlignment.AsInt == 16,
$"v128 type {type} must be 16-byte aligned to be interchangeable in raised signatures");
get
{
TypeDesc type = _wasmV128Type;
if (type is null)
{
var vector128 = (MetadataType)SystemModule.GetType("System.Runtime.Intrinsics"u8, "Vector128`1"u8);
_wasmV128Type = type = vector128.MakeInstantiatedType(GetWellKnownType(WellKnownType.Byte));
}

_cachedV128Type ??= type;
return type;
}
}

/// <summary>
Expand Down
34 changes: 14 additions & 20 deletions src/coreclr/tools/Common/JitInterface/WasmLowering.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -123,17 +123,21 @@ private static bool IsWasmV128Type(TypeDesc type)
}

// Vector128<T> is always a 16-byte v128.
if (Internal.TypeSystem.Interop.InteropTypes.IsSystemRuntimeIntrinsicsVector128T(type.Context, type))
{
return true;
}

//
// Vector<T> is target-sized, so it is only a v128 when the target's maximum SIMD width is
// 128-bit (i.e. it is exactly 16 bytes). This matches the JIT recognizing it as TYP_SIMD16
// via getVectorTByteLength() and keeps the ABI correct should wasm later gain wider vectors.
return type is DefType vectorOfT &&
VectorOfTFieldLayoutAlgorithm.IsVectorOfTType(vectorOfT) &&
type.GetElementSize().AsInt == 16;
bool isV128 = Internal.TypeSystem.Interop.InteropTypes.IsSystemRuntimeIntrinsicsVector128T(type.Context, type) ||
(type is DefType vectorOfT &&
VectorOfTFieldLayoutAlgorithm.IsVectorOfTType(vectorOfT) &&
type.GetElementSize().AsInt == 16);

// The wasm ABI gives every v128 a 16-byte aligned argument slot, so a smaller metadata
// alignment would silently misplace it relative to the runtime's own ArgIterator layout.
Debug.Assert(!isV128 || ((DefType)type).InstanceFieldAlignment.AsInt == 16,
$"v128 type {type} must be 16-byte aligned");

return isV128;
}

public static WasmValueType LowerType(TypeDesc type)
Expand DownExpand Up@@ -219,8 +223,7 @@ public static WasmValueType LowerType(TypeDesc type)
'l' => context.GetWellKnownType(WellKnownType.Int64),
'f' => context.GetWellKnownType(WellKnownType.Single),
'd' => context.GetWellKnownType(WellKnownType.Double),
'V' => ((CompilerTypeSystemContext)context).CachedV128Type
?? throw new InvalidOperationException("Encountered 'V' in signature but no v128 type was cached during lowering"),
'V' => ((CompilerTypeSystemContext)context).WasmV128Type,
_ => throw new InvalidOperationException($"Unknown signature char: {c}")
};

Expand DownExpand Up@@ -402,12 +405,7 @@ public static WasmSignature GetSignature(MethodSignature signature, LoweringFlag
}
else
{
WasmValueType returnWasmType = LowerType(loweredReturnType);
if (returnWasmType == WasmValueType.V128)
{
((CompilerTypeSystemContext)returnType.Context).CacheV128Type(loweredReturnType);
}
sigBuilder.Append(WasmValueTypeToSigChar(returnWasmType));
sigBuilder.Append(WasmValueTypeToSigChar(LowerType(loweredReturnType)));
}

// Reserve space for potential implicit this, stack pointer parameter, portable entrypoint parameter,
Expand DownExpand Up@@ -484,10 +482,6 @@ public static WasmSignature GetSignature(MethodSignature signature, LoweringFlag
else
{
WasmValueType paramWasmType = LowerType(loweredParamType);
if (paramWasmType == WasmValueType.V128)
{
((CompilerTypeSystemContext)paramType.Context).CacheV128Type(loweredParamType);
}
sigBuilder.Append(WasmValueTypeToSigChar(paramWasmType));
result.Add(paramWasmType);
}
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -21,6 +21,9 @@

<ItemGroup>
<ProjectReference Include="../ILCompiler.Reflection.ReadyToRun/ILCompiler.Reflection.ReadyToRun.csproj" />
<!-- Aliased because it redefines the ReadyToRun* constant enums that
ILCompiler.Reflection.ReadyToRun already brings into the global namespace. -->
<ProjectReference Include="../ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj" Aliases="crossgen2" />
<ProjectReference Include="../crossgen2/crossgen2_inbuild.csproj" ReferenceOutputAssembly="false">
<!-- crossgen2 is a CoreCLR artifact, so publish it in the CoreCLR configuration. This keeps it
alongside the other CoreCLR artifacts the test consumes (System.Private.CoreLib, the JITs)
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -341,21 +341,7 @@ private List<string> BuildReferencePaths()

paths.Add(Path.Combine(_paths.RuntimePackDir, "*.dll"));

// SPCL lives in the runtime pack native/ dir in full builds (placed by
// externals.csproj BinPlace during libs.pretest). In partial CI builds
// that skip libs.pretest, the runtime pack layout may not exist, but the
// CoreCLR artifacts directory always has SPCL after clr.nativecorelib.
string spcl = Path.Combine(_paths.RuntimePackNativeDir, "System.Private.CoreLib.dll");
if (!File.Exists(spcl))
{
string fallback = Path.Combine(_paths.CoreCLRArtifactsDir, "System.Private.CoreLib.dll");
if (File.Exists(fallback))
{
_output.WriteLine($"[R2RTestRunner] SPCL not found at '{spcl}'; using CoreCLR artifacts fallback '{fallback}'");
spcl = fallback;
}
}

string spcl = _paths.SystemPrivateCoreLibPath;
Assert.True(File.Exists(spcl),
$"System.Private.CoreLib.dll not found at '{spcl}'. " +
$"Searched RuntimePackNativeDir='{_paths.RuntimePackNativeDir}' and " +
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -133,6 +133,30 @@ public string RuntimePackNativeDir
}
}

/// <summary>
/// Path to System.Private.CoreLib.dll. It lives in the runtime pack native/ dir in full builds
/// (placed by externals.csproj BinPlace during libs.pretest), but partial builds that skip
/// libs.pretest only have it in the CoreCLR artifacts directory.
/// </summary>
public string SystemPrivateCoreLibPath
{
get
{
string path = Path.Combine(RuntimePackNativeDir, "System.Private.CoreLib.dll");
if (!File.Exists(path))
{
string fallback = Path.Combine(CoreCLRArtifactsDir, "System.Private.CoreLib.dll");
if (File.Exists(fallback))
{
_output.WriteLine($"[TestPaths] '{path}' not found; falling back to '{fallback}'");
return fallback;
}
}

return path;
}
}

/// <summary>
/// Path to the CoreCLR artifacts directory (contains native bits like corerun).
/// e.g. artifacts/bin/coreclr/linux.x64.Checked/
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,34 +5,33 @@

using Internal.TypeSystem;

using Debug = System.Diagnostics.Debug;

namespace ILCompiler
{
public partial class CompilerTypeSystemContext
{
private readonly object _structCacheLock = new object();
private readonly Dictionary<int, TypeDesc> _structsBySize = new Dictionary<int, TypeDesc>();
private volatile TypeDesc _cachedEmptyStruct;
private volatile TypeDesc _cachedV128Type;

/// <summary>
/// Gets the first SIMD v128 type encountered during lowering, or null if none has been seen.
/// Used by RaiseSignature to produce a roundtrippable type for the 'V' encoding.
/// </summary>
public TypeDesc CachedV128Type => _cachedV128Type;
private volatile TypeDesc _wasmV128Type;

/// <summary>
/// Caches a SIMD v128 type discovered during lowering. Only the first one is retained.
/// Gets the type RaiseSignature produces for the 'V' encoding. All v128 types share the same
/// wasm ABI (16 bytes, 16-byte aligned), so any one of them round-trips 'V' identically;
/// resolving a fixed one keeps raising independent of the order lowering encountered them in.
/// </summary>
public void CacheV128Type(TypeDesc type)
public TypeDesc WasmV128Type
{
// All v128 types share the same wasm ABI (16-byte aligned), so any one round-trips the
// 'V' encoding identically; a smaller alignment would change raised signatures silently.
Debug.Assert(type is DefType defType && defType.InstanceFieldAlignment.AsInt == 16,
$"v128 type {type} must be 16-byte aligned to be interchangeable in raised signatures");
get
{
TypeDesc type = _wasmV128Type;
if (type is null)
{
var vector128 = (MetadataType)SystemModule.GetType("System.Runtime.Intrinsics"u8, "Vector128`1"u8);
_wasmV128Type = type = vector128.MakeInstantiatedType(GetWellKnownType(WellKnownType.Byte));
}

_cachedV128Type ??= type;
return type;
}
}

/// <summary>
Expand Down
34 changes: 14 additions & 20 deletions src/coreclr/tools/Common/JitInterface/WasmLowering.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -123,17 +123,21 @@ private static bool IsWasmV128Type(TypeDesc type)
}

// Vector128<T> is always a 16-byte v128.
if (Internal.TypeSystem.Interop.InteropTypes.IsSystemRuntimeIntrinsicsVector128T(type.Context, type))
{
return true;
}

//
// Vector<T> is target-sized, so it is only a v128 when the target's maximum SIMD width is
// 128-bit (i.e. it is exactly 16 bytes). This matches the JIT recognizing it as TYP_SIMD16
// via getVectorTByteLength() and keeps the ABI correct should wasm later gain wider vectors.
return type is DefType vectorOfT &&
VectorOfTFieldLayoutAlgorithm.IsVectorOfTType(vectorOfT) &&
type.GetElementSize().AsInt == 16;
bool isV128 = Internal.TypeSystem.Interop.InteropTypes.IsSystemRuntimeIntrinsicsVector128T(type.Context, type) ||
(type is DefType vectorOfT &&
VectorOfTFieldLayoutAlgorithm.IsVectorOfTType(vectorOfT) &&
type.GetElementSize().AsInt == 16);

// The wasm ABI gives every v128 a 16-byte aligned argument slot, so a smaller metadata
// alignment would silently misplace it relative to the runtime's own ArgIterator layout.
Debug.Assert(!isV128 || ((DefType)type).InstanceFieldAlignment.AsInt == 16,
$"v128 type {type} must be 16-byte aligned");

return isV128;
}

public static WasmValueType LowerType(TypeDesc type)
Expand DownExpand Up@@ -219,8 +223,7 @@ public static WasmValueType LowerType(TypeDesc type)
'l' => context.GetWellKnownType(WellKnownType.Int64),
'f' => context.GetWellKnownType(WellKnownType.Single),
'd' => context.GetWellKnownType(WellKnownType.Double),
'V' => ((CompilerTypeSystemContext)context).CachedV128Type
?? throw new InvalidOperationException("Encountered 'V' in signature but no v128 type was cached during lowering"),
'V' => ((CompilerTypeSystemContext)context).WasmV128Type,
_ => throw new InvalidOperationException($"Unknown signature char: {c}")
};

Expand DownExpand Up@@ -402,12 +405,7 @@ public static WasmSignature GetSignature(MethodSignature signature, LoweringFlag
}
else
{
WasmValueType returnWasmType = LowerType(loweredReturnType);
if (returnWasmType == WasmValueType.V128)
{
((CompilerTypeSystemContext)returnType.Context).CacheV128Type(loweredReturnType);
}
sigBuilder.Append(WasmValueTypeToSigChar(returnWasmType));
sigBuilder.Append(WasmValueTypeToSigChar(LowerType(loweredReturnType)));
}

// Reserve space for potential implicit this, stack pointer parameter, portable entrypoint parameter,
Expand DownExpand Up@@ -484,10 +482,6 @@ public static WasmSignature GetSignature(MethodSignature signature, LoweringFlag
else
{
WasmValueType paramWasmType = LowerType(loweredParamType);
if (paramWasmType == WasmValueType.V128)
{
((CompilerTypeSystemContext)paramType.Context).CacheV128Type(loweredParamType);
}
sigBuilder.Append(WasmValueTypeToSigChar(paramWasmType));
result.Add(paramWasmType);
}
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -21,6 +21,9 @@

<ItemGroup>
<ProjectReference Include="../ILCompiler.Reflection.ReadyToRun/ILCompiler.Reflection.ReadyToRun.csproj" />
<!-- Aliased because it redefines the ReadyToRun* constant enums that
ILCompiler.Reflection.ReadyToRun already brings into the global namespace. -->
<ProjectReference Include="../ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj" Aliases="crossgen2" />
<ProjectReference Include="../crossgen2/crossgen2_inbuild.csproj" ReferenceOutputAssembly="false">
<!-- crossgen2 is a CoreCLR artifact, so publish it in the CoreCLR configuration. This keeps it
alongside the other CoreCLR artifacts the test consumes (System.Private.CoreLib, the JITs)
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -341,21 +341,7 @@ private List<string> BuildReferencePaths()

paths.Add(Path.Combine(_paths.RuntimePackDir, "*.dll"));

// SPCL lives in the runtime pack native/ dir in full builds (placed by
// externals.csproj BinPlace during libs.pretest). In partial CI builds
// that skip libs.pretest, the runtime pack layout may not exist, but the
// CoreCLR artifacts directory always has SPCL after clr.nativecorelib.
string spcl = Path.Combine(_paths.RuntimePackNativeDir, "System.Private.CoreLib.dll");
if (!File.Exists(spcl))
{
string fallback = Path.Combine(_paths.CoreCLRArtifactsDir, "System.Private.CoreLib.dll");
if (File.Exists(fallback))
{
_output.WriteLine($"[R2RTestRunner] SPCL not found at '{spcl}'; using CoreCLR artifacts fallback '{fallback}'");
spcl = fallback;
}
}

string spcl = _paths.SystemPrivateCoreLibPath;
Assert.True(File.Exists(spcl),
$"System.Private.CoreLib.dll not found at '{spcl}'. " +
$"Searched RuntimePackNativeDir='{_paths.RuntimePackNativeDir}' and " +
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -133,6 +133,30 @@ public string RuntimePackNativeDir
}
}

/// <summary>
/// Path to System.Private.CoreLib.dll. It lives in the runtime pack native/ dir in full builds
/// (placed by externals.csproj BinPlace during libs.pretest), but partial builds that skip
/// libs.pretest only have it in the CoreCLR artifacts directory.
/// </summary>
public string SystemPrivateCoreLibPath
{
get
{
string path = Path.Combine(RuntimePackNativeDir, "System.Private.CoreLib.dll");
if (!File.Exists(path))
{
string fallback = Path.Combine(CoreCLRArtifactsDir, "System.Private.CoreLib.dll");
if (File.Exists(fallback))
{
_output.WriteLine($"[TestPaths] '{path}' not found; falling back to '{fallback}'");
return fallback;
}
}

return path;
}
}

/// <summary>
/// Path to the CoreCLR artifacts directory (contains native bits like corerun).
/// e.g. artifacts/bin/coreclr/linux.x64.Checked/
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,34 +5,33 @@

using Internal.TypeSystem;

using Debug = System.Diagnostics.Debug;

namespace ILCompiler
{
public partial class CompilerTypeSystemContext
{
private readonly object _structCacheLock = new object();
private readonly Dictionary<int, TypeDesc> _structsBySize = new Dictionary<int, TypeDesc>();
private volatile TypeDesc _cachedEmptyStruct;
private volatile TypeDesc _cachedV128Type;

/// <summary>
/// Gets the first SIMD v128 type encountered during lowering, or null if none has been seen.
/// Used by RaiseSignature to produce a roundtrippable type for the 'V' encoding.
/// </summary>
public TypeDesc CachedV128Type => _cachedV128Type;
private volatile TypeDesc _wasmV128Type;

/// <summary>
/// Caches a SIMD v128 type discovered during lowering. Only the first one is retained.
/// Gets the type RaiseSignature produces for the 'V' encoding. All v128 types share the same
/// wasm ABI (16 bytes, 16-byte aligned), so any one of them round-trips 'V' identically;
/// resolving a fixed one keeps raising independent of the order lowering encountered them in.
/// </summary>
public void CacheV128Type(TypeDesc type)
public TypeDesc WasmV128Type
{
// All v128 types share the same wasm ABI (16-byte aligned), so any one round-trips the
// 'V' encoding identically; a smaller alignment would change raised signatures silently.
Debug.Assert(type is DefType defType && defType.InstanceFieldAlignment.AsInt == 16,
$"v128 type {type} must be 16-byte aligned to be interchangeable in raised signatures");
get
{
TypeDesc type = _wasmV128Type;
if (type is null)
{
var vector128 = (MetadataType)SystemModule.GetType("System.Runtime.Intrinsics"u8, "Vector128`1"u8);
_wasmV128Type = type = vector128.MakeInstantiatedType(GetWellKnownType(WellKnownType.Byte));
}

_cachedV128Type ??= type;
return type;
}
}

/// <summary>
Expand Down
34 changes: 14 additions & 20 deletions src/coreclr/tools/Common/JitInterface/WasmLowering.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -123,17 +123,21 @@ private static bool IsWasmV128Type(TypeDesc type)
}

// Vector128<T> is always a 16-byte v128.
if (Internal.TypeSystem.Interop.InteropTypes.IsSystemRuntimeIntrinsicsVector128T(type.Context, type))
{
return true;
}

//
// Vector<T> is target-sized, so it is only a v128 when the target's maximum SIMD width is
// 128-bit (i.e. it is exactly 16 bytes). This matches the JIT recognizing it as TYP_SIMD16
// via getVectorTByteLength() and keeps the ABI correct should wasm later gain wider vectors.
return type is DefType vectorOfT &&
VectorOfTFieldLayoutAlgorithm.IsVectorOfTType(vectorOfT) &&
type.GetElementSize().AsInt == 16;
bool isV128 = Internal.TypeSystem.Interop.InteropTypes.IsSystemRuntimeIntrinsicsVector128T(type.Context, type) ||
(type is DefType vectorOfT &&
VectorOfTFieldLayoutAlgorithm.IsVectorOfTType(vectorOfT) &&
type.GetElementSize().AsInt == 16);

// The wasm ABI gives every v128 a 16-byte aligned argument slot, so a smaller metadata
// alignment would silently misplace it relative to the runtime's own ArgIterator layout.
Debug.Assert(!isV128 || ((DefType)type).InstanceFieldAlignment.AsInt == 16,
$"v128 type {type} must be 16-byte aligned");

return isV128;
}

public static WasmValueType LowerType(TypeDesc type)
Expand DownExpand Up@@ -219,8 +223,7 @@ public static WasmValueType LowerType(TypeDesc type)
'l' => context.GetWellKnownType(WellKnownType.Int64),
'f' => context.GetWellKnownType(WellKnownType.Single),
'd' => context.GetWellKnownType(WellKnownType.Double),
'V' => ((CompilerTypeSystemContext)context).CachedV128Type
?? throw new InvalidOperationException("Encountered 'V' in signature but no v128 type was cached during lowering"),
'V' => ((CompilerTypeSystemContext)context).WasmV128Type,
_ => throw new InvalidOperationException($"Unknown signature char: {c}")
};

Expand DownExpand Up@@ -402,12 +405,7 @@ public static WasmSignature GetSignature(MethodSignature signature, LoweringFlag
}
else
{
WasmValueType returnWasmType = LowerType(loweredReturnType);
if (returnWasmType == WasmValueType.V128)
{
((CompilerTypeSystemContext)returnType.Context).CacheV128Type(loweredReturnType);
}
sigBuilder.Append(WasmValueTypeToSigChar(returnWasmType));
sigBuilder.Append(WasmValueTypeToSigChar(LowerType(loweredReturnType)));
}

// Reserve space for potential implicit this, stack pointer parameter, portable entrypoint parameter,
Expand DownExpand Up@@ -484,10 +482,6 @@ public static WasmSignature GetSignature(MethodSignature signature, LoweringFlag
else
{
WasmValueType paramWasmType = LowerType(loweredParamType);
if (paramWasmType == WasmValueType.V128)
{
((CompilerTypeSystemContext)paramType.Context).CacheV128Type(loweredParamType);
}
sigBuilder.Append(WasmValueTypeToSigChar(paramWasmType));
result.Add(paramWasmType);
}
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -21,6 +21,9 @@

<ItemGroup>
<ProjectReference Include="../ILCompiler.Reflection.ReadyToRun/ILCompiler.Reflection.ReadyToRun.csproj" />
<!-- Aliased because it redefines the ReadyToRun* constant enums that
ILCompiler.Reflection.ReadyToRun already brings into the global namespace. -->
<ProjectReference Include="../ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj" Aliases="crossgen2" />
<ProjectReference Include="../crossgen2/crossgen2_inbuild.csproj" ReferenceOutputAssembly="false">
<!-- crossgen2 is a CoreCLR artifact, so publish it in the CoreCLR configuration. This keeps it
alongside the other CoreCLR artifacts the test consumes (System.Private.CoreLib, the JITs)
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -341,21 +341,7 @@ private List<string> BuildReferencePaths()

paths.Add(Path.Combine(_paths.RuntimePackDir, "*.dll"));

// SPCL lives in the runtime pack native/ dir in full builds (placed by
// externals.csproj BinPlace during libs.pretest). In partial CI builds
// that skip libs.pretest, the runtime pack layout may not exist, but the
// CoreCLR artifacts directory always has SPCL after clr.nativecorelib.
string spcl = Path.Combine(_paths.RuntimePackNativeDir, "System.Private.CoreLib.dll");
if (!File.Exists(spcl))
{
string fallback = Path.Combine(_paths.CoreCLRArtifactsDir, "System.Private.CoreLib.dll");
if (File.Exists(fallback))
{
_output.WriteLine($"[R2RTestRunner] SPCL not found at '{spcl}'; using CoreCLR artifacts fallback '{fallback}'");
spcl = fallback;
}
}

string spcl = _paths.SystemPrivateCoreLibPath;
Assert.True(File.Exists(spcl),
$"System.Private.CoreLib.dll not found at '{spcl}'. " +
$"Searched RuntimePackNativeDir='{_paths.RuntimePackNativeDir}' and " +
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -133,6 +133,30 @@ public string RuntimePackNativeDir
}
}

/// <summary>
/// Path to System.Private.CoreLib.dll. It lives in the runtime pack native/ dir in full builds
/// (placed by externals.csproj BinPlace during libs.pretest), but partial builds that skip
/// libs.pretest only have it in the CoreCLR artifacts directory.
/// </summary>
public string SystemPrivateCoreLibPath
{
get
{
string path = Path.Combine(RuntimePackNativeDir, "System.Private.CoreLib.dll");
if (!File.Exists(path))
{
string fallback = Path.Combine(CoreCLRArtifactsDir, "System.Private.CoreLib.dll");
if (File.Exists(fallback))
{
_output.WriteLine($"[TestPaths] '{path}' not found; falling back to '{fallback}'");
return fallback;
}
}

return path;
}
}

/// <summary>
/// Path to the CoreCLR artifacts directory (contains native bits like corerun).
/// e.g. artifacts/bin/coreclr/linux.x64.Checked/
Expand Down
Loading
Loading