diff --git a/.github/workflows/bump-chrome-version.yml b/.github/workflows/bump-chrome-version.yml
new file mode 100644
index 00000000000000..edb8be150135e1
--- /dev/null
+++ b/.github/workflows/bump-chrome-version.yml
@@ -0,0 +1,65 @@
+name: Update Chrome Version used for wasm testing
+
+permissions:
+ contents: write
+ pull-requests: write
+
+on:
+ schedule:
+ - cron: '0 0 * * 0'
+
+ workflow_dispatch:
+
+jobs:
+ update:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+ - name: Setup Branch
+ run: |
+ git config user.name github-actions[bot]
+ git config user.email github-actions[bot]@users.noreply.github.com
+ git checkout -b update-chrome-version-${{ github.run_id }}
+
+ - name: Run UpdateToLatestVersion
+ run: >-
+ make -C src/mono/wasm build-tasks &&
+ .dotnet/dotnet build eng/testing/bump-chrome-version.proj -p:Configuration=Release &&
+ git add eng/testing/ChromeVersions.props
+
+ - name: Check for changes
+ id: check_changes
+ run: |
+ echo "has_changes=$(git diff-index --quiet HEAD && echo false || echo true)" >> $GITHUB_OUTPUT
+
+ - name: Commit Update
+ run: |
+ echo steps.check_changes.outputs.has_changes=${{steps.check_changes.outputs.has_changes}}
+ if ${{steps.check_changes.outputs.has_changes}} == 'true'; then
+ git commit -m "Automated bump of chrome version"
+ git push --set-upstream origin update-chrome-version-${{ github.run_id }}
+ else
+ echo "No changes detected."
+ fi
+
+ - name: Create PR
+ if: steps.check_changes.outputs.has_changes == 'true'
+ uses: actions/github-script@v6
+ with:
+ script: |
+ const { data: pullRequest } = await github.rest.pulls.create({
+ base: context.ref,
+ head: "update-chrome-version-${{ github.run_id }}",
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ title: '[wasm] Bump chrome version used for testing',
+ body: ''
+ });
+ await github.rest.pulls.requestReviewers({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ pull_number: pullRequest.number,
+ reviewers: ["radical"]
+ });
+ return pullRequest.number;
diff --git a/eng/pipelines/common/evaluate-default-paths.yml b/eng/pipelines/common/evaluate-default-paths.yml
index 5fb74a3741f413..1ae0e9c8cd141a 100644
--- a/eng/pipelines/common/evaluate-default-paths.yml
+++ b/eng/pipelines/common/evaluate-default-paths.yml
@@ -6,7 +6,7 @@ parameters:
# do not set them when using the template
_const_paths:
_wasm_specific_only: [
- eng/testing/ProvisioningVersions.props
+ eng/testing/ChromeVersions.props
eng/testing/WasmRunner*
eng/testing/WasiRunner*
eng/testing/scenarios/BuildWasmAppsJobsList.txt
@@ -182,7 +182,7 @@ jobs:
include:
- eng/Version.Details.xml
- eng/Versions.props
- eng/testing/ProvisioningVersions.props
+ eng/testing/ChromeVersions.props
- eng/testing/scenarios/BuildWasmAppsJobsList.txt
- eng/testing/workloads-testing.targets
- src/installer/pkg/sfx/Microsoft.NETCore.App/*
@@ -215,7 +215,7 @@ jobs:
- subset: wasmdebuggertests
combined: true
include:
- - eng/testing/ProvisioningVersions.props
+ - eng/testing/ChromeVersions.props
- src/libraries/System.Runtime.InteropServices/*
- src/libraries/System.Runtime.InteropServices.JavaScript/*
- src/mono/mono/*
diff --git a/eng/pipelines/installer/jobs/build-job.yml b/eng/pipelines/installer/jobs/build-job.yml
index 5a0e37157e45c5..5ae2122f70571d 100644
--- a/eng/pipelines/installer/jobs/build-job.yml
+++ b/eng/pipelines/installer/jobs/build-job.yml
@@ -86,18 +86,26 @@ jobs:
- name: OfficialBuildArg
value: ''
+ # Explicitly enable tests for linux even though it is a cross build using mariner
+ # They still work in this configuration and until they run on Helix, it is our only
+ # linux test coverage in the installer pipeline
- name: SkipTests
value: ${{ or(
not(in(parameters.archType, 'x64', 'x86')),
eq(parameters.runtimeFlavor, 'mono'),
eq(parameters.isOfficialBuild, true),
- eq(parameters.crossBuild, true),
+ and(
+ eq(parameters.crossBuild, true),
+ not(and(
+ eq(parameters.osGroup, 'linux'),
+ eq(parameters.osSubgroup, ''))
+ )),
eq(parameters.pgoType, 'PGO')) }}
- name: BuildAction
value: -test
- - ${{ if eq(or(not(in(parameters.archType, 'x64', 'x86')), eq(parameters.runtimeFlavor, 'mono'), eq(parameters.isOfficialBuild, true), eq(parameters.crossBuild, true), eq(parameters.pgoType, 'PGO')), true) }}:
+ - ${{ if eq(or(not(in(parameters.archType, 'x64', 'x86')), eq(parameters.runtimeFlavor, 'mono'), eq(parameters.isOfficialBuild, true), and(eq(parameters.crossBuild, true), not(and(eq(parameters.osGroup, 'linux'), eq(parameters.osSubgroup, '')))), eq(parameters.pgoType, 'PGO')), true) }}:
- name: BuildAction
value: ''
@@ -296,6 +304,25 @@ jobs:
- checkout: self
clean: true
fetchDepth: $(checkoutFetchDepth)
+
+ - ${{ if ne(variables['System.TeamProject'], 'public') }}:
+ - ${{ if ne(parameters.osGroup, 'windows') }}:
+ - task: Bash@3
+ displayName: Setup Private Feeds Credentials
+ inputs:
+ filePath: $(Build.SourcesDirectory)/eng/common/SetupNugetSources.sh
+ arguments: $(Build.SourcesDirectory)/NuGet.config $Token
+ env:
+ Token: $(dn-bot-dnceng-artifact-feeds-rw)
+ - ${{ else }}:
+ - task: PowerShell@2
+ displayName: Setup Private Feeds Credentials
+ inputs:
+ filePath: $(Build.SourcesDirectory)/eng/common/SetupNugetSources.ps1
+ arguments: -ConfigFile $(Build.SourcesDirectory)/NuGet.config -Password $Env:Token
+ env:
+ Token: $(dn-bot-dnceng-artifact-feeds-rw)
+
- ${{ if ne(parameters.liveRuntimeBuildConfig, '') }}:
- template: /eng/pipelines/common/download-artifact-step.yml
parameters:
@@ -378,6 +405,7 @@ jobs:
runtimeVariant: ${{ parameters.runtimeVariant }}
isOfficialBuild: ${{ eq(parameters.isOfficialBuild, true) }}
pgoType: ${{ parameters.pgoType }}
+ skipTests: ${{ eq(variables.SkipTests, true) }}
- ${{ if ne(parameters.osGroup, 'windows') }}:
- script: set -x && df -h
diff --git a/eng/pipelines/libraries/stress/http.yml b/eng/pipelines/libraries/stress/http.yml
index 6c740e49d04d47..f4f9c45de36e48 100644
--- a/eng/pipelines/libraries/stress/http.yml
+++ b/eng/pipelines/libraries/stress/http.yml
@@ -13,6 +13,7 @@ schedules:
- main
- release/6.0
- release/7.0
+ - release/8.0
variables:
- template: ../variables.yml
diff --git a/eng/pipelines/libraries/stress/ssl.yml b/eng/pipelines/libraries/stress/ssl.yml
index 791251030f5753..ab93994400d346 100644
--- a/eng/pipelines/libraries/stress/ssl.yml
+++ b/eng/pipelines/libraries/stress/ssl.yml
@@ -13,6 +13,7 @@ schedules:
- main
- release/6.0
- release/7.0
+ - release/8.0
variables:
- template: ../variables.yml
diff --git a/eng/testing/ChromeVersions.props b/eng/testing/ChromeVersions.props
new file mode 100644
index 00000000000000..ff43dcee06fb2a
--- /dev/null
+++ b/eng/testing/ChromeVersions.props
@@ -0,0 +1,11 @@
+
+
+ 115.0.5790.170
+ 1148114
+ https://storage.googleapis.com/chromium-browser-snapshots/Linux_x64/1148123
+
+ 115.0.5790.171
+ 1148114
+ https://storage.googleapis.com/chromium-browser-snapshots/Win_x64/1148119
+
+
diff --git a/eng/testing/ProvisioningVersions.props b/eng/testing/ProvisioningVersions.props
deleted file mode 100644
index 3105078bdc3b59..00000000000000
--- a/eng/testing/ProvisioningVersions.props
+++ /dev/null
@@ -1,68 +0,0 @@
-
-
-
- stable
-
- win
- linux
- mac
-
- false
-
- $(ArtifactsBinDir)chrome\
- $(ArtifactsBinDir)chromedriver\
-
-
- 3
-
- $(ArtifactsBinDir)firefox\
- $([MSBuild]::NormalizePath($(FirefoxDir), '.install-firefox-$(FirefoxRevision).stamp'))
-
-
-
-
-
-
- false
-
- true
-
-
-
- 115.0.5790.170
- 1148114
- <_ChromeBaseSnapshotUrl>https://storage.googleapis.com/chromium-browser-snapshots/Linux_x64/1148123
-
-
- 115.0.5790.171
- 1148114
- <_ChromeBaseSnapshotUrl>https://storage.googleapis.com/chromium-browser-snapshots/Win_x64/1148119
-
-
-
- 108.0.1
- https://ftp.mozilla.org/pub/firefox/releases/$(FirefoxRevision)/linux-x86_64/en-US/firefox-$(FirefoxRevision).tar.bz2
- firefox
-
-
diff --git a/eng/testing/bump-chrome-version.proj b/eng/testing/bump-chrome-version.proj
new file mode 100644
index 00000000000000..18e92adc736aa8
--- /dev/null
+++ b/eng/testing/bump-chrome-version.proj
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_PropsContent>
+<Project>
+ <PropertyGroup>
+ <linux_ChromeVersion>$(linux_ChromeVersion)</linux_ChromeVersion>
+ <linux_ChromeRevision>$(linux_ChromeRevision)</linux_ChromeRevision>
+ <linux_ChromeBaseSnapshotUrl>$(linux_ChromeBaseSnapshotUrl)</linux_ChromeBaseSnapshotUrl>
+
+ <win_ChromeVersion>$(win_ChromeVersion)</win_ChromeVersion>
+ <win_ChromeRevision>$(win_ChromeRevision)</win_ChromeRevision>
+ <win_ChromeBaseSnapshotUrl>$(win_ChromeBaseSnapshotUrl)</win_ChromeBaseSnapshotUrl>
+ </PropertyGroup>
+</Project>
+
+
+
+
+
+
+
+
+
diff --git a/eng/testing/wasm-provisioning.targets b/eng/testing/wasm-provisioning.targets
index 65c192385e8c9b..fd3bbc50c06bb5 100644
--- a/eng/testing/wasm-provisioning.targets
+++ b/eng/testing/wasm-provisioning.targets
@@ -1,5 +1,29 @@
-
+
+
+ stable
+
+ win
+ linux
+ unsupported-platform
+
+
+ false
+
+ $(ArtifactsBinDir)firefox\
+ $([MSBuild]::NormalizePath($(FirefoxDir), '.install-firefox-$(FirefoxRevision).stamp'))
+ <_BrowserStampDir>$(ArtifactsBinDir)\
+
+
+
+
+
+ 108.0.1
+ https://ftp.mozilla.org/pub/firefox/releases/$(FirefoxRevision)/linux-x86_64/en-US/firefox-$(FirefoxRevision).tar.bz2
+ firefox
+
chrome-linux
@@ -7,6 +31,13 @@
chrome
chromedriver
<_ChromeOSPrefix>Linux_x64
+
+ $(linux_ChromeVersion)
+ $(linux_ChromeRevision)
+ <_ChromeBaseSnapshotUrl>$(linux_ChromeBaseSnapshotUrl)
+
+ $(linux_ChromeBaseSnapshotUrl)/chrome-linux.zip
+ $(linux_ChromeBaseSnapshotUrl)/chromedriver_linux64.zip
@@ -15,18 +46,38 @@
chrome.exe
chromedriver.exe
<_ChromeOSPrefix>Win_x64
+
+ $(win_ChromeVersion)
+ $(win_ChromeRevision)
+ <_ChromeBaseSnapshotUrl>$(win_ChromeBaseSnapshotUrl)
+
+ $(win_ChromeBaseSnapshotUrl)/chrome-win.zip
+ $(win_ChromeBaseSnapshotUrl)/chromedriver_win32.zip
-
- <_BrowserStampDir>$(ArtifactsBinDir)\
+
+ $(ArtifactsBinDir)chrome\
+ $(ArtifactsBinDir)chromedriver\
+ $([MSBuild]::NormalizePath('$(ChromeDir)', '.install-$(ChromeVersion)-$(ChromeRevision).stamp'))
+ $([MSBuild]::NormalizePath('$(ChromeDriverDir)', '.install-$(ChromeVersion)-$(ChromeRevision).stamp'))
+
$([MSBuild]::NormalizePath($(ChromeDir), $(ChromeDirName), $(ChromeBinaryName)))
$([MSBuild]::NormalizePath($(ChromeDriverDir), $(ChromeDriverDirName), $(ChromeDriverBinaryName)))
+
+ 108.0.1
+ https://ftp.mozilla.org/pub/firefox/releases/$(FirefoxRevision)/linux-x86_64/en-US/firefox-$(FirefoxRevision).tar.bz2
+ firefox
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
- $(_ChromeBaseSnapshotUrl)/chrome-linux.zip
- $(_ChromeBaseSnapshotUrl)/chromedriver_linux64.zip
-
-
- $(_ChromeBaseSnapshotUrl)/chrome-win.zip
- $(_ChromeBaseSnapshotUrl)/chromedriver_win32.zip
-
-
-
- $([MSBuild]::NormalizePath('$(ChromeDir)', '.install-$(ChromeVersion)-$(ChromeRevision).stamp'))
- $([MSBuild]::NormalizePath('$(ChromeDriverDir)', '.install-$(ChromeVersion)-$(ChromeRevision).stamp'))
-
-
diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp
index 07e03d3e0c2334..76c0212ceaba54 100644
--- a/src/coreclr/jit/codegencommon.cpp
+++ b/src/coreclr/jit/codegencommon.cpp
@@ -2979,12 +2979,10 @@ void CodeGen::genFnPrologCalleeRegArgs(regNumber xtraReg, bool* pXtraRegClobbere
// Change regType to the HFA type when we have a HFA argument
if (varDsc->lvIsHfaRegArg())
{
-#if defined(TARGET_ARM64)
- if (TargetOS::IsWindows && compiler->info.compIsVarArgs)
+ if (TargetOS::IsWindows && TargetArchitecture::IsArm64 && compiler->info.compIsVarArgs)
{
assert(!"Illegal incoming HFA arg encountered in Vararg method.");
}
-#endif // defined(TARGET_ARM64)
regType = varDsc->GetHfaType();
}
@@ -3046,7 +3044,7 @@ void CodeGen::genFnPrologCalleeRegArgs(regNumber xtraReg, bool* pXtraRegClobbere
for (unsigned slotCounter = 0; slotCounter < structDesc.eightByteCount; slotCounter++)
{
regNumber regNum = varDsc->lvRegNumForSlot(slotCounter);
- var_types regType;
+ var_types slotRegType;
#ifdef FEATURE_SIMD
// Assumption 1:
@@ -3075,15 +3073,15 @@ void CodeGen::genFnPrologCalleeRegArgs(regNumber xtraReg, bool* pXtraRegClobbere
if (varDsc->lvType == TYP_SIMD12)
{
- regType = TYP_DOUBLE;
+ slotRegType = TYP_DOUBLE;
}
else
#endif
{
- regType = compiler->GetEightByteType(structDesc, slotCounter);
+ slotRegType = compiler->GetEightByteType(structDesc, slotCounter);
}
- regArgNum = genMapRegNumToRegArgNum(regNum, regType);
+ regArgNum = genMapRegNumToRegArgNum(regNum, slotRegType);
if ((!doingFloat && (structDesc.IsIntegralSlot(slotCounter))) ||
(doingFloat && (structDesc.IsSseSlot(slotCounter))))
@@ -3101,7 +3099,7 @@ void CodeGen::genFnPrologCalleeRegArgs(regNumber xtraReg, bool* pXtraRegClobbere
// register)
regArgTab[regArgNum].varNum = varNum;
regArgTab[regArgNum].slot = (char)(slotCounter + 1);
- regArgTab[regArgNum].type = regType;
+ regArgTab[regArgNum].type = slotRegType;
slots++;
}
}
@@ -3120,7 +3118,8 @@ void CodeGen::genFnPrologCalleeRegArgs(regNumber xtraReg, bool* pXtraRegClobbere
regArgNum = genMapRegNumToRegArgNum(varDsc->GetArgReg(), regType);
slots = 1;
- if (TargetArchitecture::IsArm32)
+ if (TargetArchitecture::IsArm32 ||
+ (TargetOS::IsWindows && TargetArchitecture::IsArm64 && compiler->info.compIsVarArgs))
{
int lclSize = compiler->lvaLclSize(varNum);
if (lclSize > REGSIZE_BYTES)
diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp
index 1699b36c7c2c40..82a13b3013baba 100644
--- a/src/coreclr/jit/compiler.hpp
+++ b/src/coreclr/jit/compiler.hpp
@@ -2690,6 +2690,12 @@ inline var_types Compiler::mangleVarArgsType(var_types type)
default:
break;
}
+
+ if (varTypeIsSIMD(type))
+ {
+ // Vectors also get passed in int registers. Use TYP_INT.
+ return TYP_INT;
+ }
}
#endif // defined(TARGET_ARMARCH)
return type;
diff --git a/src/coreclr/jit/lclvars.cpp b/src/coreclr/jit/lclvars.cpp
index 3e922ee5ebcc65..e7c9a49ea48250 100644
--- a/src/coreclr/jit/lclvars.cpp
+++ b/src/coreclr/jit/lclvars.cpp
@@ -671,6 +671,7 @@ void Compiler::lvaInitUserArgs(InitVarDscInfo* varDscInfo, unsigned skipArgs, un
varDsc->SetHfaType(hfaType);
cSlots = varDsc->lvHfaSlots();
}
+
// The number of slots that must be enregistered if we are to consider this argument enregistered.
// This is normally the same as cSlots, since we normally either enregister the entire object,
// or none of it. For structs on ARM, however, we only need to enregister a single slot to consider
@@ -682,11 +683,13 @@ void Compiler::lvaInitUserArgs(InitVarDscInfo* varDscInfo, unsigned skipArgs, un
if (compFeatureArgSplit())
{
// On arm64 Windows we will need to properly handle the case where a >8byte <=16byte
- // struct is split between register r7 and virtual stack slot s[0]
- // We will only do this for calls to vararg methods on Windows Arm64
+ // struct (or vector) is split between register r7 and virtual stack slot s[0].
+ // We will only do this for calls to vararg methods on Windows Arm64.
+ // SIMD types (for which `varTypeIsStruct()` returns `true`) are also passed in general-purpose
+ // registers and can be split between registers and stack with Windows arm64 native varargs.
//
// !!This does not affect the normal arm64 calling convention or Unix Arm64!!
- if (this->info.compIsVarArgs && argType == TYP_STRUCT)
+ if (info.compIsVarArgs && (cSlots > 1))
{
if (varDscInfo->canEnreg(TYP_INT, 1) && // The beginning of the struct can go in a register
!varDscInfo->canEnreg(TYP_INT, cSlots)) // The end of the struct can't fit in a register
@@ -775,7 +778,7 @@ void Compiler::lvaInitUserArgs(InitVarDscInfo* varDscInfo, unsigned skipArgs, un
codeGen->regSet.rsMaskPreSpillRegArg |= regMask;
}
}
-#else // !TARGET_ARM
+#endif // TARGET_ARM
#if defined(UNIX_AMD64_ABI)
SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR structDesc;
@@ -817,7 +820,6 @@ void Compiler::lvaInitUserArgs(InitVarDscInfo* varDscInfo, unsigned skipArgs, un
}
}
#endif // UNIX_AMD64_ABI
-#endif // !TARGET_ARM
// The final home for this incoming register might be our local stack frame.
// For System V platforms the final home will always be on the local stack frame.
@@ -921,8 +923,7 @@ void Compiler::lvaInitUserArgs(InitVarDscInfo* varDscInfo, unsigned skipArgs, un
canPassArgInRegisters = varDscInfo->canEnreg(argType, cSlotsToEnregister);
#if defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
// On LoongArch64 and RISCV64, if there aren't any remaining floating-point registers to pass the
- // argument,
- // integer registers (if any) are used instead.
+ // argument, integer registers (if any) are used instead.
if (!canPassArgInRegisters && varTypeIsFloating(argType))
{
canPassArgInRegisters = varDscInfo->canEnreg(TYP_I_IMPL, cSlotsToEnregister);
@@ -979,7 +980,7 @@ void Compiler::lvaInitUserArgs(InitVarDscInfo* varDscInfo, unsigned skipArgs, un
if (isHfaArg)
{
- // We need to save the fact that this HFA is enregistered
+ // We need to save the fact that this HFA is enregistered.
// Note that we can have HVAs of SIMD types even if we are not recognizing intrinsics.
// In that case, we won't have normalized the vector types on the varDsc, so if we have a single vector
// register, we need to set the type now. Otherwise, later we'll assume this is passed by reference.
diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp
index f29d6a57148136..20733c64cfee01 100644
--- a/src/coreclr/jit/morph.cpp
+++ b/src/coreclr/jit/morph.cpp
@@ -2269,13 +2269,11 @@ void CallArgs::AddFinalArgsAndDetermineABIInfo(Compiler* comp, GenTreeCall* call
hfaType = comp->GetHfaType(argSigClass);
isHfaArg = varTypeIsValidHfaType(hfaType);
-#if defined(TARGET_ARM64)
- if (TargetOS::IsWindows)
+ if (TargetOS::IsWindows && TargetArchitecture::IsArm64 && callIsVararg)
{
// Make sure for vararg methods isHfaArg is not true.
- isHfaArg = callIsVararg ? false : isHfaArg;
+ isHfaArg = false;
}
-#endif // defined(TARGET_ARM64)
if (isHfaArg)
{
@@ -2614,7 +2612,7 @@ void CallArgs::AddFinalArgsAndDetermineABIInfo(Compiler* comp, GenTreeCall* call
//
if (!isRegArg && (size > 1))
{
- // Arm64 windows native varargs allows splitting a 16 byte struct between stack
+ // Arm64 windows native varargs allows splitting a 16 byte struct (or SIMD type) between stack
// and the last general purpose register.
if (TargetOS::IsWindows && callIsVararg)
{
diff --git a/src/coreclr/jit/vartype.h b/src/coreclr/jit/vartype.h
index 116d5ce2c0519a..3c38a3427ebd29 100644
--- a/src/coreclr/jit/vartype.h
+++ b/src/coreclr/jit/vartype.h
@@ -348,6 +348,8 @@ inline bool varTypeUsesFloatArgReg(T vt)
{
#ifdef TARGET_ARM64
// Arm64 passes SIMD types in floating point registers.
+ // Exception: Windows arm64 native varargs passes them using general-purpose (integer) registers or
+ // by value on the stack, or split between registers and stack.
return varTypeUsesFloatReg(vt);
#else
// Other targets pass them as regular structs - by reference or by value.
diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets
index a4f34ef2225483..b73da221f44b0b 100644
--- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets
+++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets
@@ -248,7 +248,7 @@ The .NET Foundation licenses this file to you under the MIT license.
-
+
diff --git a/src/coreclr/nativeaot/docs/reflection-free-mode.md b/src/coreclr/nativeaot/docs/reflection-free-mode.md
index f4acb394c67c98..6b49771fb1b552 100644
--- a/src/coreclr/nativeaot/docs/reflection-free-mode.md
+++ b/src/coreclr/nativeaot/docs/reflection-free-mode.md
@@ -1,6 +1,6 @@
# Reflection-free mode
-Reflection-free mode is a mode of the NativeAOT compiler and runtime that greatly reduces the functionality of the reflection APIs and brings a couple interesting benefits as a result. The benefits of this mode are:
+Reflection-free mode is a highly experimental mode of the NativeAOT compiler and runtime that greatly reduces the functionality of the reflection APIs and brings a couple interesting benefits as a result. The benefits of this mode are:
* Greatly reduced size of self contained deployments - a fully self-contained "Hello world" style app compiles to a 1 MB file (on x64) with _no dependencies_.
* Reduced working set and better code locality - parts of the program are more tightly packed together.
@@ -16,8 +16,6 @@ To enable reflection-free mode in a project that is already using NativeAOT, add
```
-(More switches are documented in the [Optimizing NativeAOT](optimizing.md) document.)
-
## What's different at compile time with reflection disabled
When reflection is disabled, the AOT compiler stops emitting data structures that are required to make reflection work at runtime and stops enforcing policies that makes the code more reflection friendly.
@@ -74,21 +72,17 @@ To achieve similar result for when querying for ``Assembly`` (will instead give
And here for CustomAttributes (will return an empty array):
-
```xml
```
-Note:
-
-To make ``NativeLibrary`` API, and on the same occasion``Socket``, to work, you'll need:
+## Internal implementation
-```xml
-
-
-
-
-```
+The reflection-free mode is implemented as a collection of features that can be controlled individually via the AOT compiler command line options for experiments and troubleshooting, including:
+- `--scanreflection` (also exposed as `IlcScanReflection` build property): Infer reflection usage by code analysis. This feature is disabled for reflection-free mode.
+- `--reflectiondata:none`: Disables generation of reflection data.
+- `--feature:System.Collections.Generic.DefaultComparers=false`: Disables `EqualityComparer.Default` and `Comparer.Default` optimizations that are based on reflection.
+The complete set of individual features that the reflection-free mode is composed from currently can be found by looking for `IlcDisableReflection` in [Microsoft.NETCore.Native.targets](../BuildIntegration/Microsoft.NETCore.Native.targets).
diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs
index 82560bf79bfae5..a39ebe53305a44 100644
--- a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs
+++ b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs
@@ -45,22 +45,6 @@ public ResultChecker (BaseAssemblyResolver originalsResolver,
_linkedReaderParameters = linkedReaderParameters;
}
- private static bool ShouldValidateIL (AssemblyDefinition inputAssembly)
- {
- if (HasAttribute (inputAssembly, nameof (SkipPeVerifyAttribute)))
- return false;
-
- var caaIsUnsafeFlag = (CustomAttributeArgument caa) =>
- (caa.Type.Name == "String" && caa.Type.Namespace == "System")
- && (string) caa.Value == "/unsafe";
- var customAttributeHasUnsafeFlag = (CustomAttribute ca) => ca.ConstructorArguments.Any (caaIsUnsafeFlag);
- if (GetCustomAttributes (inputAssembly, nameof (SetupCompileArgumentAttribute))
- .Any (customAttributeHasUnsafeFlag))
- return false;
-
- return true;
- }
-
public virtual void Check (ILCompilerTestCaseResult testResult)
{
InitializeResolvers (testResult);
diff --git a/src/coreclr/tools/superpmi/superpmi-shared/errorhandling.h b/src/coreclr/tools/superpmi/superpmi-shared/errorhandling.h
index 3c418b31d2536a..484106fd3878d6 100644
--- a/src/coreclr/tools/superpmi/superpmi-shared/errorhandling.h
+++ b/src/coreclr/tools/superpmi/superpmi-shared/errorhandling.h
@@ -34,7 +34,7 @@ void MSC_ONLY(__declspec(noreturn)) ThrowRecordedException(DWORD innerExceptionC
do \
{ \
if (!(expr)) \
- LogException(exCode, "SuperPMI assertion '%s' failed (" #msg ")", #expr, ##__VA_ARGS__); \
+ LogException(exCode, "SuperPMI assertion '%s' failed (" msg ")", #expr, ##__VA_ARGS__); \
} while (0)
#define AssertCode(expr, exCode) \
diff --git a/src/coreclr/tools/superpmi/superpmi-shared/logging.h b/src/coreclr/tools/superpmi/superpmi-shared/logging.h
index 957da040885eaf..15d7d097fcb5b7 100644
--- a/src/coreclr/tools/superpmi/superpmi-shared/logging.h
+++ b/src/coreclr/tools/superpmi/superpmi-shared/logging.h
@@ -30,7 +30,7 @@
do \
{ \
Logger::LogExceptionMessage(__FUNCTION__, __FILE__, __LINE__, exCode, msg, __VA_ARGS__); \
- ThrowSpmiException(exCode, msg, __VA_ARGS__); \
+ ThrowSpmiException(exCode, msg, __VA_ARGS__); \
} while (0)
// These are specified as flags so subsets of the logging functionality can be enabled/disabled at once
diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp
index 5ee9b2bb41dcb2..f103a3f307ba5c 100644
--- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp
+++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp
@@ -2365,7 +2365,7 @@ void MethodContext::recGetHelperFtn(CorInfoHelpFunc ftnNum, void** ppIndirection
DLDL oldValue = GetHelperFtn->Get(key);
AssertCodeMsg(oldValue.A == value.A && oldValue.B == oldValue.B, EXCEPTIONCODE_MC,
- "collision! old: %016" PRIX64 " %016" PRIX64 ", new: %016" PRIX64 " %016" PRIX64 " \n", oldValue.A, oldValue.B, value.A,
+ "collision! old: %016" PRIX64 " %016" PRIX64 ", new: %016" PRIX64 " %016" PRIX64, oldValue.A, oldValue.B, value.A,
value.B);
}
diff --git a/src/installer/tests/HostActivation.Tests/DependencyResolution/RidAssetResolution.cs b/src/installer/tests/HostActivation.Tests/DependencyResolution/RidAssetResolution.cs
index cb924267ca2548..afbf30a0ba4fa1 100644
--- a/src/installer/tests/HostActivation.Tests/DependencyResolution/RidAssetResolution.cs
+++ b/src/installer/tests/HostActivation.Tests/DependencyResolution/RidAssetResolution.cs
@@ -29,7 +29,23 @@ public class TestSetup
// Expected behaviour of the test based on above settings
public bool ShouldUseRidGraph => UseRidGraph == true;
- public bool ShouldUseFallbackRid => ShouldUseRidGraph && (Rid == UnknownRid || !HasRidGraph);
+
+ public bool? ShouldUseFallbackRid
+ {
+ get
+ {
+ if (!ShouldUseRidGraph)
+ return false;
+
+ if (Rid == UnknownRid || !HasRidGraph)
+ return true;
+
+ // We use the product RID graph for testing (for cases with a RID graph). If the test is running
+ // on a platform that isn't in that RID graph, we may end up with the fallback even when the RID
+ // graph is used and RID is not unknown. Value of null indicates this state.
+ return null;
+ }
+ }
public override string ToString() => $"""
{nameof(Rid)}: {(Rid ?? "")}
@@ -623,18 +639,20 @@ protected override void RunTest(
UpdateAppConfigForTest(app, setup, copyOnUpdate: false);
- dotnet.Exec(app.AppDll)
+ var result = dotnet.Exec(app.AppDll)
.EnableTracingAndCaptureOutputs()
.RuntimeId(setup.Rid)
- .Execute()
- .Should().Pass()
+ .Execute();
+ result.Should().Pass()
.And.HaveResolvedAssembly(expected.IncludedAssemblyPaths, app)
.And.NotHaveResolvedAssembly(expected.ExcludedAssemblyPaths, app)
.And.HaveResolvedNativeLibraryPath(expected.IncludedNativeLibraryPaths, app)
.And.NotHaveResolvedNativeLibraryPath(expected.ExcludedNativeLibraryPaths, app)
.And.HaveReadRidGraph(setup.ShouldUseRidGraph)
- .And.HaveUsedFallbackRid(setup.ShouldUseFallbackRid)
.And.HaveUsedFrameworkProbe(dotnet.GreatestVersionSharedFxPath, level: 1);
+
+ if (setup.ShouldUseFallbackRid.HasValue)
+ result.Should().HaveUsedFallbackRid(setup.ShouldUseFallbackRid.Value);
}
}
}
@@ -674,17 +692,19 @@ protected override void RunTest(
TestApp app = UpdateAppConfigForTest(SharedState.FrameworkReferenceApp, setup, copyOnUpdate: true);
- SharedState.RunComponentResolutionTest(component.AppDll, app, dotnet.GreatestVersionHostFxrPath, command => command
- .RuntimeId(setup.Rid))
- .Should().Pass()
+ var result = SharedState.RunComponentResolutionTest(component.AppDll, app, dotnet.GreatestVersionHostFxrPath, command => command
+ .RuntimeId(setup.Rid));
+ result.Should().Pass()
.And.HaveSuccessfullyResolvedComponentDependencies()
.And.HaveResolvedComponentDependencyAssembly(expected.IncludedAssemblyPaths, component)
.And.NotHaveResolvedComponentDependencyAssembly(expected.ExcludedAssemblyPaths, component)
.And.HaveResolvedComponentDependencyNativeLibraryPath(expected.IncludedNativeLibraryPaths, component)
.And.NotHaveResolvedComponentDependencyNativeLibraryPath(expected.ExcludedNativeLibraryPaths, component)
.And.HaveReadRidGraph(setup.ShouldUseRidGraph)
- .And.HaveUsedFallbackRid(setup.ShouldUseFallbackRid)
.And.NotHaveUsedFrameworkProbe(dotnet.GreatestVersionSharedFxPath);
+
+ if (setup.ShouldUseFallbackRid.HasValue)
+ result.Should().HaveUsedFallbackRid(setup.ShouldUseFallbackRid.Value);
}
}
@@ -723,16 +743,18 @@ protected override void RunTest(
app = UpdateAppConfigForTest(app, setup, copyOnUpdate: true);
- SharedState.RunComponentResolutionTest(component.AppDll, app, app.Location, command => command
- .RuntimeId(setup.Rid))
- .Should().Pass()
+ var result = SharedState.RunComponentResolutionTest(component.AppDll, app, app.Location, command => command
+ .RuntimeId(setup.Rid));
+ result.Should().Pass()
.And.HaveSuccessfullyResolvedComponentDependencies()
.And.HaveResolvedComponentDependencyAssembly(expected.IncludedAssemblyPaths, component)
.And.NotHaveResolvedComponentDependencyAssembly(expected.ExcludedAssemblyPaths, component)
.And.HaveResolvedComponentDependencyNativeLibraryPath(expected.IncludedNativeLibraryPaths, component)
.And.NotHaveResolvedComponentDependencyNativeLibraryPath(expected.ExcludedNativeLibraryPaths, component)
- .And.HaveReadRidGraph(setup.ShouldUseRidGraph)
- .And.HaveUsedFallbackRid(setup.ShouldUseFallbackRid);
+ .And.HaveReadRidGraph(setup.ShouldUseRidGraph);
+
+ if (setup.ShouldUseFallbackRid.HasValue)
+ result.Should().HaveUsedFallbackRid(setup.ShouldUseFallbackRid.Value);
}
public class ComponentSharedTestState : ComponentSharedTestStateBase
diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/RcwAroundCcwTests.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/RcwAroundCcwTests.cs
index 95ab9822d3d3d0..765c26ffac59c5 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/RcwAroundCcwTests.cs
+++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/RcwAroundCcwTests.cs
@@ -200,17 +200,33 @@ public void StatefulMarshalling()
var obj = CreateWrapper();
var data = new StatefulType() { i = 42 };
+ int preCallFreeCount = StatefulTypeMarshaller.FreeCount;
obj.Method(data);
Assert.Equal(42, data.i);
+ Assert.Equal(preCallFreeCount + 2, StatefulTypeMarshaller.FreeCount);
+
+ preCallFreeCount = StatefulTypeMarshaller.FreeCount;
obj.MethodIn(in data);
Assert.Equal(42, data.i);
+ Assert.Equal(preCallFreeCount + 2, StatefulTypeMarshaller.FreeCount);
+
var oldData = data;
+ preCallFreeCount = StatefulTypeMarshaller.FreeCount;
obj.MethodRef(ref data);
+ Assert.Equal(preCallFreeCount + 2, StatefulTypeMarshaller.FreeCount);
Assert.True(oldData == data); // We want reference equality here
+
+ preCallFreeCount = StatefulTypeMarshaller.FreeCount;
obj.MethodOut(out data);
+ Assert.Equal(preCallFreeCount + 2, StatefulTypeMarshaller.FreeCount);
Assert.Equal(1, data.i);
+
+ preCallFreeCount = StatefulTypeMarshaller.FreeCount;
Assert.Equal(1, obj.Return().i);
+ Assert.Equal(preCallFreeCount + 2, StatefulTypeMarshaller.FreeCount);
+ preCallFreeCount = StatefulTypeMarshaller.FreeCount;
Assert.Equal(1, obj.ReturnPreserveSig().i);
+ Assert.Equal(preCallFreeCount + 2, StatefulTypeMarshaller.FreeCount);
}
[Fact]
@@ -219,16 +235,67 @@ public void StatelessCallerAllocatedBufferMarshalling()
var obj = CreateWrapper();
var data = new StatelessCallerAllocatedBufferType() { I = 42 };
+ // ManagedToUnmanagedIn should use Caller Allocated Buffer and not allocate
+ StatelessCallerAllocatedBufferTypeMarshaller.DisableAllocations();
+
+ var numFreeCalls = StatelessCallerAllocatedBufferTypeMarshaller.FreeCount;
obj.Method(data);
+ Assert.Equal(1 + numFreeCalls, StatelessCallerAllocatedBufferTypeMarshaller.FreeCount);
Assert.Equal(42, data.I);
+
+ numFreeCalls = StatelessCallerAllocatedBufferTypeMarshaller.FreeCount;
obj.MethodIn(in data);
+ Assert.Equal(1 + numFreeCalls, StatelessCallerAllocatedBufferTypeMarshaller.FreeCount);
Assert.Equal(42, data.I);
+
+ // Other marshal modes will allocate
+ StatelessCallerAllocatedBufferTypeMarshaller.EnableAllocations();
+
+ numFreeCalls = StatelessCallerAllocatedBufferTypeMarshaller.FreeCount;
obj.MethodRef(ref data);
+ Assert.Equal(2 + numFreeCalls, StatelessCallerAllocatedBufferTypeMarshaller.FreeCount);
+ StatelessCallerAllocatedBufferTypeMarshaller.AssertAllPointersFreed();
Assert.Equal(200, data.I);
+
+ numFreeCalls = StatelessCallerAllocatedBufferTypeMarshaller.FreeCount;
obj.MethodOut(out data);
+ Assert.Equal(1 + numFreeCalls, StatelessCallerAllocatedBufferTypeMarshaller.FreeCount);
+ StatelessCallerAllocatedBufferTypeMarshaller.AssertAllPointersFreed();
Assert.Equal(20, data.I);
+
+ numFreeCalls = StatelessCallerAllocatedBufferTypeMarshaller.FreeCount;
Assert.Equal(201, obj.Return().I);
+ Assert.Equal(1 + numFreeCalls, StatelessCallerAllocatedBufferTypeMarshaller.FreeCount);
+
+ numFreeCalls = StatelessCallerAllocatedBufferTypeMarshaller.FreeCount;
Assert.Equal(202, obj.ReturnPreserveSig().I);
+ Assert.Equal(1 + numFreeCalls, StatelessCallerAllocatedBufferTypeMarshaller.FreeCount);
+ }
+
+ [Fact]
+ public void StatefulPinnedMarshalling()
+ {
+ var obj = CreateWrapper();
+ var data = new StatefulPinnedType() { I = 4 };
+
+ StatefulPinnedTypeMarshaller.ManagedToUnmanagedIn.DisableNonPinnedPath();
+
+ obj.Method(data);
+ Assert.Equal(4, data.I);
+
+ obj.MethodIn(in data);
+ Assert.Equal(4, data.I);
+
+ StatefulPinnedTypeMarshaller.ManagedToUnmanagedIn.EnableNonPinnedPath();
+
+ obj.MethodOut(out data);
+ Assert.Equal(102, data.I);
+
+ obj.MethodRef(ref data);
+ Assert.Equal(103, data.I);
+
+ data = obj.Return();
+ Assert.Equal(104, data.I);
}
[Fact]
diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/UnmanagedToManagedCustomMarshallingTests.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/UnmanagedToManagedCustomMarshallingTests.cs
index c88031d5c4ca68..8defdfd8c4e331 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/UnmanagedToManagedCustomMarshallingTests.cs
+++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/UnmanagedToManagedCustomMarshallingTests.cs
@@ -2,14 +2,11 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
-using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
-using System.Text;
using System.Threading;
-using System.Threading.Tasks;
using SharedTypes;
using Xunit;
using static ComInterfaceGenerator.Tests.UnmanagedToManagedCustomMarshallingTests;
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulMarshalling.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulMarshalling.cs
index 69f7e09a902d3d..47b6cc916c3384 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulMarshalling.cs
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulMarshalling.cs
@@ -50,6 +50,7 @@ internal struct StatefulNative
[CustomMarshaller(typeof(StatefulType), MarshalMode.ManagedToUnmanagedRef, typeof(Bidirectional))]
internal struct StatefulTypeMarshaller
{
+ public static int FreeCount => Bidirectional.FreeCount + ManagedToUnmanaged.FreeCount + UnmanagedToManaged.FreeCount;
internal struct Bidirectional
{
public static int FreeCount { get; private set; }
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulPinnedMarshalling.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulPinnedMarshalling.cs
index 1b5438cbdd6f25..eaac2608d8184a 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulPinnedMarshalling.cs
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulPinnedMarshalling.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
+using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
@@ -16,46 +17,271 @@ internal partial interface IStatefulPinnedMarshalling
void MethodOut(out StatefulPinnedType param);
void MethodRef(ref StatefulPinnedType param);
StatefulPinnedType Return();
- [PreserveSig]
- StatefulPinnedType ReturnPreserveSig();
+ }
+
+ [GeneratedComClass]
+ internal partial class StatefulPinnedMarshalling : IStatefulPinnedMarshalling
+ {
+ public void Method(StatefulPinnedType param) { param.I = 100; }
+ public void MethodIn(in StatefulPinnedType param) { param.I = 101; }
+ public void MethodOut(out StatefulPinnedType param) => param = new StatefulPinnedType() { I = 102 };
+ public void MethodRef(ref StatefulPinnedType param) { param = new StatefulPinnedType() { I = 103 }; }
+ public StatefulPinnedType Return() => new StatefulPinnedType() { I = 104 };
}
[NativeMarshalling(typeof(StatefulPinnedTypeMarshaller))]
internal class StatefulPinnedType
{
+ public int I;
}
- [CustomMarshaller(typeof(StatefulPinnedType), MarshalMode.Default, typeof(StatefulPinnedTypeMarshaller))]
- internal struct StatefulPinnedTypeMarshaller
+ internal unsafe struct StatefulPinnedNative
{
+ public int I;
+ }
- public static int BufferSize => 64;
- public ref int GetPinnableReference() => throw new System.NotImplementedException();
- public void FromManaged(StatefulPinnedType managed, Span buffer)
+ [CustomMarshaller(typeof(StatefulPinnedType), MarshalMode.ManagedToUnmanagedIn, typeof(ManagedToUnmanagedIn))]
+ [CustomMarshaller(typeof(StatefulPinnedType), MarshalMode.UnmanagedToManagedOut, typeof(UnmanagedToManagedOut))]
+ [CustomMarshaller(typeof(StatefulPinnedType), MarshalMode.UnmanagedToManagedIn, typeof(UnmanagedToManagedIn))]
+ [CustomMarshaller(typeof(StatefulPinnedType), MarshalMode.ManagedToUnmanagedOut, typeof(ManagedToUnmanagedOut))]
+ [CustomMarshaller(typeof(StatefulPinnedType), MarshalMode.ManagedToUnmanagedRef, typeof(ManagedToUnmanagedRef))]
+ [CustomMarshaller(typeof(StatefulPinnedType), MarshalMode.UnmanagedToManagedRef, typeof(UnmanagedToManagedRef))]
+ internal unsafe static class StatefulPinnedTypeMarshaller
+ {
+ public ref struct ManagedToUnmanagedIn
{
- throw new System.NotImplementedException();
+ static bool s_mustPin;
+ public static void DisableNonPinnedPath() => s_mustPin = true;
+ public static void EnableNonPinnedPath() => s_mustPin = false;
+
+ StatefulPinnedType _managed;
+ bool _hasManaged;
+ Span buffer;
+ nint _ptr;
+ bool _canFree;
+ bool _isPinned;
+ ref StatefulPinnedNative _refNativeStruct;
+
+ public void FromManaged(StatefulPinnedType managed)
+ {
+ _hasManaged = true;
+ _managed = managed;
+ }
+
+ public ref StatefulPinnedNative GetPinnableReference()
+ {
+ if (!_hasManaged)
+ throw new InvalidOperationException();
+ buffer = new byte[sizeof(StatefulPinnedNative)];
+ _isPinned = true;
+ _refNativeStruct = ref MemoryMarshal.AsRef(buffer);
+ return ref _refNativeStruct;
+ }
+
+ public StatefulPinnedNative* ToUnmanaged()
+ {
+ if (!_hasManaged)
+ throw new InvalidOperationException();
+
+ _canFree = true;
+ if (_isPinned)
+ {
+ _refNativeStruct = new StatefulPinnedNative() { I = _managed.I };
+ return (StatefulPinnedNative*)Unsafe.AsPointer(ref _refNativeStruct);
+ }
+
+ if (s_mustPin)
+ throw new InvalidOperationException("Expected to pin, but is instead converting with default ToUnmanaged.");
+
+ _ptr = Marshal.AllocHGlobal(sizeof(StatefulPinnedNative));
+ *(StatefulPinnedNative*)_ptr = new StatefulPinnedNative() { I = _managed.I };
+ return (StatefulPinnedNative*)_ptr;
+ }
+
+ public void Free()
+ {
+ if (!_canFree)
+ throw new InvalidOperationException();
+
+ if (!_isPinned && _ptr != 0)
+ {
+ Marshal.FreeHGlobal(_ptr);
+ }
+ }
}
- public nint ToUnmanaged()
+ public struct ManagedToUnmanagedOut
{
- throw new System.NotImplementedException();
+ StatefulPinnedNative* _unmanaged;
+ bool _hasUnmanaged;
+
+ public void FromUnmanaged(StatefulPinnedNative* unmanaged)
+ {
+ _unmanaged = unmanaged;
+ _hasUnmanaged = true;
+ }
+
+ public StatefulPinnedType ToManaged()
+ {
+ if (!_hasUnmanaged)
+ throw new InvalidOperationException();
+ return new StatefulPinnedType() { I = _unmanaged->I };
+ }
+
+ public void Free()
+ {
+ if (!_hasUnmanaged)
+ throw new InvalidOperationException();
+ var ptr = (nint)_unmanaged;
+ if (ptr != 0)
+ Marshal.FreeHGlobal(ptr);
+ }
}
- public void FromUnmanaged(nint unmanaged)
+ public struct UnmanagedToManagedIn
{
- throw new System.NotImplementedException();
+ StatefulPinnedNative* _unmanaged;
+ bool _hasUnmanaged;
+ public void FromUnmanaged(StatefulPinnedNative* unmanaged)
+ {
+ _unmanaged = unmanaged;
+ _hasUnmanaged = true;
+ }
+
+ public StatefulPinnedType ToManaged()
+ {
+ if (!_hasUnmanaged)
+ throw new InvalidOperationException();
+ return new StatefulPinnedType() { I = _unmanaged->I };
+ }
+
+ public void Free()
+ {
+ }
}
- public StatefulPinnedType ToManaged()
+ public struct UnmanagedToManagedOut
{
- throw new System.NotImplementedException();
+ StatefulPinnedType _managed;
+ bool _hasManaged;
+ nint _ptr;
+
+ public void FromManaged(StatefulPinnedType managed)
+ {
+ _hasManaged = true;
+ _managed = managed;
+ }
+
+ public StatefulPinnedNative* ToUnmanaged()
+ {
+ if (!_hasManaged)
+ throw new InvalidOperationException();
+ _ptr = Marshal.AllocHGlobal(sizeof(StatefulPinnedNative));
+ *(StatefulPinnedNative*)_ptr = new StatefulPinnedNative() { I = _managed.I };
+ return (StatefulPinnedNative*)_ptr;
+ }
+
+ public void Free()
+ {
+ }
}
- public void Free()
+
+ public struct ManagedToUnmanagedRef
{
- throw new System.NotImplementedException();
+ StatefulPinnedNative* _unmanaged;
+ bool _hasUnmanaged;
+ public void FromUnmanaged(StatefulPinnedNative* unmanaged)
+ {
+ _unmanaged = unmanaged;
+ _hasUnmanaged = true;
+ }
+
+ public StatefulPinnedType ToManaged()
+ {
+ if (!_hasUnmanaged)
+ throw new InvalidOperationException();
+ return new StatefulPinnedType() { I = _unmanaged->I };
+ }
+
+ StatefulPinnedType _managed;
+ bool _hasManaged;
+ nint _ptr;
+ bool _hasAllocated;
+
+ public void FromManaged(StatefulPinnedType managed)
+ {
+ _hasManaged = true;
+ _managed = managed;
+ }
+
+ public StatefulPinnedNative* ToUnmanaged()
+ {
+ if (!_hasManaged)
+ throw new InvalidOperationException();
+ _ptr = Marshal.AllocHGlobal(sizeof(StatefulPinnedNative));
+ _hasAllocated = true;
+ *(StatefulPinnedNative*)_ptr = new StatefulPinnedNative() { I = _managed.I };
+ return (StatefulPinnedNative*)_ptr;
+ }
+
+ public void Free()
+ {
+ if (_hasUnmanaged)
+ {
+ Marshal.FreeHGlobal((nint)_unmanaged);
+ }
+ else if (_hasAllocated)
+ {
+ Marshal.FreeHGlobal(_ptr);
+ }
+ }
}
+ public struct UnmanagedToManagedRef
+ {
+ StatefulPinnedNative* _unmanaged;
+ bool _hasUnmanaged;
+ public void FromUnmanaged(StatefulPinnedNative* unmanaged)
+ {
+ _unmanaged = unmanaged;
+ _hasUnmanaged = true;
+ }
+
+ public StatefulPinnedType ToManaged()
+ {
+ if (!_hasUnmanaged)
+ throw new InvalidOperationException();
+ return new StatefulPinnedType() { I = _unmanaged->I };
+ }
- public void OnInvoked() { }
+ StatefulPinnedType _managed;
+ bool _hasManaged;
+ nint _ptr;
+ bool _hasAllocated;
+
+ public void FromManaged(StatefulPinnedType managed)
+ {
+ _hasManaged = true;
+ _managed = managed;
+ }
+
+ public StatefulPinnedNative* ToUnmanaged()
+ {
+ if (!_hasManaged)
+ throw new InvalidOperationException();
+ _ptr = Marshal.AllocHGlobal(sizeof(StatefulPinnedNative));
+ _hasAllocated = true;
+ *(StatefulPinnedNative*)_ptr = new StatefulPinnedNative() { I = _managed.I };
+ return (StatefulPinnedNative*)_ptr;
+ }
+
+ public void Free()
+ {
+ if (_hasAllocated && _hasUnmanaged)
+ {
+ Marshal.FreeHGlobal((nint)_unmanaged);
+ }
+ }
+ }
}
}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCallerAllocateBufferMarshalling.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCallerAllocateBufferMarshalling.cs
index 1b04704251bff1..f8b1174799b136 100644
--- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCallerAllocateBufferMarshalling.cs
+++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCallerAllocateBufferMarshalling.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
@@ -39,39 +40,125 @@ internal class StatelessCallerAllocatedBufferType
public int I;
}
- [CustomMarshaller(typeof(StatelessCallerAllocatedBufferType), MarshalMode.Default, typeof(StatelessCallerAllocatedBufferTypeMarshaller))]
+ internal struct StatelessCallerAllocatedBufferNative
+ {
+ public int I;
+ }
+
+ [CustomMarshaller(typeof(StatelessCallerAllocatedBufferType), MarshalMode.ManagedToUnmanagedRef, typeof(Bidirectional))]
+ [CustomMarshaller(typeof(StatelessCallerAllocatedBufferType), MarshalMode.UnmanagedToManagedRef, typeof(Bidirectional))]
+ [CustomMarshaller(typeof(StatelessCallerAllocatedBufferType), MarshalMode.ElementIn, typeof(Bidirectional))]
+ [CustomMarshaller(typeof(StatelessCallerAllocatedBufferType), MarshalMode.ElementOut, typeof(Bidirectional))]
+ [CustomMarshaller(typeof(StatelessCallerAllocatedBufferType), MarshalMode.ElementRef, typeof(Bidirectional))]
+ [CustomMarshaller(typeof(StatelessCallerAllocatedBufferType), MarshalMode.ManagedToUnmanagedOut, typeof(UnmanagedToManaged))]
+ [CustomMarshaller(typeof(StatelessCallerAllocatedBufferType), MarshalMode.UnmanagedToManagedIn, typeof(UnmanagedToManaged))]
+ [CustomMarshaller(typeof(StatelessCallerAllocatedBufferType), MarshalMode.ManagedToUnmanagedIn, typeof(ManagedToUnmanagedIn))]
+ [CustomMarshaller(typeof(StatelessCallerAllocatedBufferType), MarshalMode.UnmanagedToManagedOut, typeof(UnmanagedToManagedOut))]
internal static unsafe class StatelessCallerAllocatedBufferTypeMarshaller
{
+ static bool _canAllocate = true;
+ public static void DisableAllocations() => _canAllocate = false;
+ public static void EnableAllocations() => _canAllocate = true;
+ public static void AssertAllPointersFreed()
+ {
+ if (_ptrs.Any()) throw new InvalidOperationException();
+ }
+
static HashSet _ptrs = new();
+
public static int FreeCount { get; private set; }
- public static int BufferSize => sizeof(int);
- public static int* ConvertToUnmanaged(StatelessCallerAllocatedBufferType managed, Span buffer)
+
+ public static class UnmanagedToManaged
{
- buffer[0] = managed.I;
- return (int*)Unsafe.AsPointer(ref buffer[0]);
+ public static StatelessCallerAllocatedBufferType ConvertToManaged(StatelessCallerAllocatedBufferNative* unmanaged)
+ {
+ return new StatelessCallerAllocatedBufferType() { I = unmanaged->I };
+ }
+
+ public static void Free(StatelessCallerAllocatedBufferNative* unmanaged)
+ {
+ FreeCount++;
+ if (_ptrs.Contains((nint)unmanaged))
+ {
+ Marshal.FreeHGlobal((nint)unmanaged);
+ _ptrs.Remove((nint)unmanaged);
+ }
+ }
}
- public static StatelessCallerAllocatedBufferType ConvertToManaged(int* unmanaged)
+ public static class ManagedToUnmanagedIn
{
- return new StatelessCallerAllocatedBufferType() { I = *unmanaged };
+ public static int BufferSize => sizeof(StatelessCallerAllocatedBufferNative);
+
+ public static StatelessCallerAllocatedBufferNative* ConvertToUnmanaged(StatelessCallerAllocatedBufferType managed, Span buffer)
+ {
+ var unmanaged = new StatelessCallerAllocatedBufferNative() { I = managed.I };
+ MemoryMarshal.Write(buffer, in unmanaged);
+ return (StatelessCallerAllocatedBufferNative*)Unsafe.AsPointer(ref MemoryMarshal.AsRef(buffer));
+ }
+
+ public static void Free(StatelessCallerAllocatedBufferNative* unmanaged)
+ {
+ FreeCount++;
+ if (_ptrs.Contains((nint)unmanaged))
+ {
+ Marshal.FreeHGlobal((nint)unmanaged);
+ _ptrs.Remove((nint)unmanaged);
+ }
+ }
}
- public static void Free(int* unmanaged)
+ public static class UnmanagedToManagedOut
{
- FreeCount++;
- if (_ptrs.Contains((nint)unmanaged))
+ public static StatelessCallerAllocatedBufferNative* ConvertToUnmanaged(StatelessCallerAllocatedBufferType managed)
{
- Marshal.FreeHGlobal((nint)unmanaged);
- _ptrs.Remove((nint)unmanaged);
+ if (!_canAllocate)
+ throw new InvalidOperationException("Marshalling used default ConverToUnmanaged when CallerAllocatedBuffer was expected");
+ nint ptr = Marshal.AllocHGlobal(sizeof(StatelessCallerAllocatedBufferNative));
+ _ptrs.Add(ptr);
+ var structPtr = (StatelessCallerAllocatedBufferNative*)ptr;
+ structPtr->I = managed.I;
+ return structPtr;
+ }
+
+ public static void Free(StatelessCallerAllocatedBufferNative* unmanaged)
+ {
+ FreeCount++;
+ if (_ptrs.Contains((nint)unmanaged))
+ {
+ Marshal.FreeHGlobal((nint)unmanaged);
+ _ptrs.Remove((nint)unmanaged);
+ }
}
}
- public static int* ConvertToUnmanaged(StatelessCallerAllocatedBufferType managed)
+ public static class Bidirectional
{
- nint ptr = Marshal.AllocHGlobal(sizeof(int));
- _ptrs.Add(ptr);
- *(int*)ptr = managed.I;
- return (int*)ptr;
+ public static StatelessCallerAllocatedBufferNative* ConvertToUnmanaged(StatelessCallerAllocatedBufferType managed)
+ {
+ if (!_canAllocate)
+ throw new InvalidOperationException("Marshalling used default ConverToUnmanaged when CallerAllocatedBuffer was expected");
+ nint ptr = Marshal.AllocHGlobal(sizeof(StatelessCallerAllocatedBufferNative));
+ _ptrs.Add(ptr);
+ var structPtr = (StatelessCallerAllocatedBufferNative*)ptr;
+ structPtr->I = managed.I;
+ return structPtr;
+ }
+
+ public static StatelessCallerAllocatedBufferType ConvertToManaged(StatelessCallerAllocatedBufferNative* unmanaged)
+ {
+ return new StatelessCallerAllocatedBufferType() { I = unmanaged->I };
+ }
+
+ public static void Free(StatelessCallerAllocatedBufferNative* unmanaged)
+ {
+ FreeCount++;
+ if (_ptrs.Contains((nint)unmanaged))
+ {
+ Marshal.FreeHGlobal((nint)unmanaged);
+ _ptrs.Remove((nint)unmanaged);
+ }
+ }
}
}
}
diff --git a/src/mono/mono/mini/decompose.c b/src/mono/mono/mini/decompose.c
index b4570cc0c7429d..2be1ff52e416d0 100644
--- a/src/mono/mono/mini/decompose.c
+++ b/src/mono/mono/mini/decompose.c
@@ -1226,7 +1226,7 @@ mono_decompose_vtype_opts (MonoCompile *cfg)
dest_var = get_vreg_to_inst (cfg, ins->dreg);
if (!src_var)
- src_var = mono_compile_create_var_for_vreg (cfg, m_class_get_byval_arg (ins->klass), OP_LOCAL, ins->dreg);
+ src_var = mono_compile_create_var_for_vreg (cfg, m_class_get_byval_arg (ins->klass), OP_LOCAL, ins->sreg1);
if (!dest_var)
dest_var = mono_compile_create_var_for_vreg (cfg, m_class_get_byval_arg (ins->klass), OP_LOCAL, ins->dreg);
diff --git a/src/mono/mono/mini/method-to-ir.c b/src/mono/mono/mini/method-to-ir.c
index b5f75ea1c3133d..e3605981bafcdf 100644
--- a/src/mono/mono/mini/method-to-ir.c
+++ b/src/mono/mono/mini/method-to-ir.c
@@ -10840,12 +10840,15 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
EMIT_NEW_TEMPLOADA (cfg, addr, vtvar->inst_c0);
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, addr->dreg, 0, ins->dreg);
EMIT_NEW_TEMPLOAD (cfg, ins, vtvar->inst_c0);
- ins->opcode = OP_LDTOKEN_FIELD;
- ins->inst_c0 = n;
- ins->inst_p1 = handle;
+ if (handle_class == mono_defaults.fieldhandle_class) {
+ ins->opcode = OP_LDTOKEN_FIELD;
+ ins->inst_c0 = n;
+ ins->inst_p1 = handle;
+
+ cfg->flags |= MONO_CFG_NEEDS_DECOMPOSE;
+ cfg->cbb->needs_decompose = TRUE;
+ }
- cfg->flags |= MONO_CFG_NEEDS_DECOMPOSE;
- cfg->cbb->needs_decompose = TRUE;
}
}
diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/WorkloadTelemetry.targets b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/WorkloadTelemetry.targets
index 8f78ce16b62587..cf97ec1f14c2af 100644
--- a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/WorkloadTelemetry.targets
+++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/WorkloadTelemetry.targets
@@ -19,6 +19,7 @@
+
@@ -35,6 +36,7 @@
<_WorkloadUsesInterpreter Condition="'$(_WorkloadUsesInterpreter)' == '' and '$(UseInterpreter)' == 'true'">true
<_WorkloadUsesInterpreter Condition="'$(_WorkloadUsesInterpreter)' == '' and '$(RunAOTCompilation)' != 'true' and ('$(_WorkloadUsesBlazorWasm)' == 'true' or '$(_WorkloadUsesWasmSDK)' == 'true')">true
<_WorkloadUsesLibraryMode Condition="'$(NativeLib)' != '' and ('$(_WorkloadUsesMonoAOT)' == 'true' or '$(_WorkloadUsesNativeAOT)' == 'true')">true
+ <_WorkloadUsesWasmStripILAfterAOT Condition="'$(WasmStripILAfterAOT)' == 'true'">true
diff --git a/src/mono/wasm/Wasm.Build.Tests/Blazor/BuildPublishTests.cs b/src/mono/wasm/Wasm.Build.Tests/Blazor/BuildPublishTests.cs
index ddca10f96aea89..2f5ef58e6bf291 100644
--- a/src/mono/wasm/Wasm.Build.Tests/Blazor/BuildPublishTests.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/Blazor/BuildPublishTests.cs
@@ -9,6 +9,7 @@
using Xunit.Abstractions;
using Xunit.Sdk;
using Microsoft.Playwright;
+using System.Runtime.InteropServices;
#nullable enable
@@ -37,16 +38,33 @@ public async Task DefaultTemplate_WithoutWorkload(string config)
await BlazorRunForPublishWithWebServer(new BlazorRunOptions() { Config = config });
}
+
+ public static TheoryData TestDataForDefaultTemplate_WithWorkload(bool isAot)
+ {
+ var data = new TheoryData();
+ data.Add("Debug", false);
+ data.Add("Release", false); // Release relinks by default
+ // [ActiveIssue("https://github.com/dotnet/runtime/issues/83497", TestPlatforms.Windows)]
+ if (!isAot || !RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ data.Add("Debug", true); // for aot:true on Windows, it fails
+ }
+
+ // [ActiveIssue("https://github.com/dotnet/runtime/issues/83497", TestPlatforms.Windows)]
+ if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ data.Add("Release", true);
+ }
+ return data;
+ }
+
[Theory]
- [InlineData("Debug")]
- [InlineData("Release")]
- public void DefaultTemplate_NoAOT_WithWorkload(string config)
+ [MemberData(nameof(TestDataForDefaultTemplate_WithWorkload), parameters: new object[] { false })]
+ public void DefaultTemplate_NoAOT_WithWorkload(string config, bool testUnicode)
{
- // disable relinking tests for Unicode: github.com/emscripten-core/emscripten/issues/17817
- // [ActiveIssue("https://github.com/dotnet/runtime/issues/83497")]
- string id = config == "Release" ?
- $"blz_no_aot_{config}_{GetRandomId()}" :
- $"blz_no_aot_{config}_{GetRandomId()}_{s_unicodeChar}";
+ string id = testUnicode ?
+ $"blz_no_aot_{config}_{GetRandomId()}_{s_unicodeChar}" :
+ $"blz_no_aot_{config}_{GetRandomId()}";
CreateBlazorWasmTemplateProject(id);
BlazorBuild(new BlazorBuildOptions(id, config, NativeFilesType.FromRuntimePack));
@@ -61,6 +79,19 @@ public void DefaultTemplate_NoAOT_WithWorkload(string config)
}
}
+ [Theory]
+ [MemberData(nameof(TestDataForDefaultTemplate_WithWorkload), parameters: new object[] { true })]
+ public void DefaultTemplate_AOT_WithWorkload(string config, bool testUnicode)
+ {
+ string id = testUnicode ?
+ $"blz_no_aot_{config}_{GetRandomId()}_{s_unicodeChar}" :
+ $"blz_no_aot_{config}_{GetRandomId()}";
+ CreateBlazorWasmTemplateProject(id);
+
+ BlazorBuild(new BlazorBuildOptions(id, config, NativeFilesType.FromRuntimePack));
+ BlazorPublish(new BlazorBuildOptions(id, config, NativeFilesType.AOT), "-p:RunAOTCompilation=true");
+ }
+
[Theory]
[InlineData("Debug", false)]
[InlineData("Release", false)]
diff --git a/src/mono/wasm/Wasm.Build.Tests/BuildPublishTests.cs b/src/mono/wasm/Wasm.Build.Tests/BuildPublishTests.cs
index 8b41916e526972..c027d761b509fa 100644
--- a/src/mono/wasm/Wasm.Build.Tests/BuildPublishTests.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/BuildPublishTests.cs
@@ -8,6 +8,7 @@
using Xunit;
using Xunit.Abstractions;
using Xunit.Sdk;
+using System.Collections.Generic;
#nullable enable
@@ -73,7 +74,9 @@ void Run() => RunAndTestWasmApp(
[BuildAndRun(host: RunHost.Chrome, aot: true, config: "Debug")]
public void BuildThenPublishWithAOT(BuildArgs buildArgs, RunHost host, string id)
{
- string projectName = GetTestProjectPath(prefix: "build_publish", config: buildArgs.Config);
+ bool testUnicode = true;
+ string projectName = GetTestProjectPath(
+ prefix: "build_publish", config: buildArgs.Config, appendUnicode: testUnicode);
buildArgs = buildArgs with { ProjectName = projectName };
buildArgs = ExpandBuildArgs(buildArgs, extraProperties: "<_WasmDevel>true");
@@ -97,7 +100,7 @@ public void BuildThenPublishWithAOT(BuildArgs buildArgs, RunHost host, string id
Assert.False(firstBuildStat["pinvoke.o"].Exists);
Assert.False(firstBuildStat[$"{mainDll}.bc"].Exists);
- CheckOutputForNativeBuild(expectAOT: false, expectRelinking: relinked, buildArgs, output);
+ CheckOutputForNativeBuild(expectAOT: false, expectRelinking: relinked, buildArgs, output, testUnicode);
Run(expectAOT: false);
@@ -108,25 +111,24 @@ public void BuildThenPublishWithAOT(BuildArgs buildArgs, RunHost host, string id
_testOutput.WriteLine($"{Environment.NewLine}Publishing with no changes ..{Environment.NewLine}");
- // FIXME: relinking for paths with unicode does not work:
- // [ActiveIssue("https://github.com/dotnet/runtime/issues/83497")]
+ Dictionary publishStat = new();
// relink by default for Release+publish
- // (_, output) = BuildProject(buildArgs,
- // id: id,
- // new BuildProjectOptions(
- // DotnetWasmFromRuntimePack: false,
- // CreateProject: false,
- // Publish: true,
- // UseCache: false,
- // Label: "first_publish"));
-
- // var publishStat = _provider.StatFiles(pathsDict.Select(kvp => kvp.Value.fullPath));
- // Assert.True(publishStat["pinvoke.o"].Exists);
- // Assert.True(publishStat[$"{mainDll}.bc"].Exists);
- // CheckOutputForNativeBuild(expectAOT: true, expectRelinking: false, buildArgs, output);
- // CompareStat(firstBuildStat, publishStat, pathsDict.Values);
-
- // Run(expectAOT: true);
+ (_, output) = BuildProject(buildArgs,
+ id: id,
+ new BuildProjectOptions(
+ DotnetWasmFromRuntimePack: false,
+ CreateProject: false,
+ Publish: true,
+ UseCache: false,
+ Label: "first_publish"));
+
+ publishStat = (Dictionary)_provider.StatFiles(pathsDict.Select(kvp => kvp.Value.fullPath));
+ Assert.True(publishStat["pinvoke.o"].Exists);
+ Assert.True(publishStat[$"{mainDll}.bc"].Exists);
+ CheckOutputForNativeBuild(expectAOT: true, expectRelinking: false, buildArgs, output, testUnicode);
+ _provider.CompareStat(firstBuildStat, publishStat, pathsDict.Values);
+
+ Run(expectAOT: true);
// second build
(_, output) = BuildProject(buildArgs,
@@ -140,13 +142,11 @@ public void BuildThenPublishWithAOT(BuildArgs buildArgs, RunHost host, string id
var secondBuildStat = _provider.StatFiles(pathsDict.Select(kvp => kvp.Value.fullPath));
// no relinking, or AOT
- CheckOutputForNativeBuild(expectAOT: false, expectRelinking: false, buildArgs, output);
+ CheckOutputForNativeBuild(expectAOT: false, expectRelinking: false, buildArgs, output, testUnicode);
// no native files changed
pathsDict.UpdateTo(unchanged: true);
- // FIXME: elinking for paths with unicode does not work:
- // [ActiveIssue("https://github.com/dotnet/runtime/issues/83497")]
- // CompareStat(publishStat, secondBuildStat, pathsDict.Values);
+ _provider.CompareStat(publishStat, secondBuildStat, pathsDict.Values);
void Run(bool expectAOT) => RunAndTestWasmApp(
buildArgs with { AOT = expectAOT },
@@ -154,15 +154,20 @@ void Run(bool expectAOT) => RunAndTestWasmApp(
host: host, id: id);
}
- void CheckOutputForNativeBuild(bool expectAOT, bool expectRelinking, BuildArgs buildArgs, string buildOutput)
+ void CheckOutputForNativeBuild(bool expectAOT, bool expectRelinking, BuildArgs buildArgs, string buildOutput, bool testUnicode)
{
- TestUtils.AssertSubstring($"{buildArgs.ProjectName}.dll -> {buildArgs.ProjectName}.dll.bc", buildOutput, contains: expectAOT);
- TestUtils.AssertSubstring($"{buildArgs.ProjectName}.dll.bc -> {buildArgs.ProjectName}.dll.o", buildOutput, contains: expectAOT);
-
- TestUtils.AssertSubstring("pinvoke.c -> pinvoke.o", buildOutput, contains: expectRelinking || expectAOT);
+ if (testUnicode)
+ {
+ string projectNameCore = buildArgs.ProjectName.Trim(new char[] {s_unicodeChar});
+ TestUtils.AssertMatches(@$"{projectNameCore}\S+.dll -> {projectNameCore}\S+.dll.bc", buildOutput, contains: expectAOT);
+ TestUtils.AssertMatches(@$"{projectNameCore}\S+.dll.bc -> {projectNameCore}\S+.dll.o", buildOutput, contains: expectAOT);
+ }
+ else
+ {
+ TestUtils.AssertSubstring($"{buildArgs.ProjectName}.dll -> {buildArgs.ProjectName}.dll.bc", buildOutput, contains: expectAOT);
+ TestUtils.AssertSubstring($"{buildArgs.ProjectName}.dll.bc -> {buildArgs.ProjectName}.dll.o", buildOutput, contains: expectAOT);
+ }
+ TestUtils.AssertMatches("pinvoke.c -> pinvoke.o", buildOutput, contains: expectRelinking || expectAOT);
}
-
- // appending UTF-8 char makes sure project build&publish under all types of paths is supported
- string GetTestProjectPath(string prefix, string config) => $"{prefix}_{config}_{s_unicodeChar}";
}
}
diff --git a/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs b/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs
index fa15c7bef6d817..2309e65175242a 100644
--- a/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs
@@ -228,7 +228,17 @@ protected string RunAndTestWasmApp(BuildArgs buildArgs,
);
TestUtils.AssertSubstring("AOT: image 'System.Private.CoreLib' found.", output, contains: buildArgs.AOT);
- TestUtils.AssertSubstring($"AOT: image '{buildArgs.ProjectName}' found.", output, contains: buildArgs.AOT);
+
+ if (s_isWindows && buildArgs.ProjectName.Contains(s_unicodeChar))
+ {
+ // unicode chars in output on Windows are decoded in unknown way, so finding utf8 string is more complicated
+ string projectNameCore = buildArgs.ProjectName.Trim(new char[] {s_unicodeChar});
+ TestUtils.AssertMatches(@$"AOT: image '{projectNameCore}\S+' found.", output, contains: buildArgs.AOT);
+ }
+ else
+ {
+ TestUtils.AssertSubstring($"AOT: image '{buildArgs.ProjectName}' found.", output, contains: buildArgs.AOT);
+ }
if (test != null)
test(output);
diff --git a/src/mono/wasm/Wasm.Build.Tests/Common/TestUtils.cs b/src/mono/wasm/Wasm.Build.Tests/Common/TestUtils.cs
index d2991f5a094837..57a1fcf22d4086 100644
--- a/src/mono/wasm/Wasm.Build.Tests/Common/TestUtils.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/Common/TestUtils.cs
@@ -74,6 +74,14 @@ public static void AssertSubstring(string substring, string full, bool contains)
Assert.DoesNotContain(substring, full);
}
+ public static void AssertMatches(string regex, string full, bool contains)
+ {
+ if (contains)
+ Assert.Matches(regex, full);
+ else
+ Assert.DoesNotMatch(regex, full);
+ }
+
public static void AssertEqual(object expected, object actual, string label)
{
if (expected?.Equals(actual) == true)
diff --git a/src/mono/wasm/Wasm.Build.Tests/NativeRebuildTests/NativeRebuildTestsBase.cs b/src/mono/wasm/Wasm.Build.Tests/NativeRebuildTests/NativeRebuildTestsBase.cs
index 956e1ca4e8b99c..10c2d6926d538d 100644
--- a/src/mono/wasm/Wasm.Build.Tests/NativeRebuildTests/NativeRebuildTestsBase.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/NativeRebuildTests/NativeRebuildTestsBase.cs
@@ -108,5 +108,9 @@ protected BuildArgs GenerateProjectContents(BuildArgs buildArgs, bool nativeReli
return ExpandBuildArgs(buildArgs, propertiesBuilder.ToString());
}
+ // appending UTF-8 char makes sure project build&publish under all types of paths is supported
+ protected string GetTestProjectPath(string prefix, string config, bool appendUnicode=true) =>
+ appendUnicode ? $"{prefix}_{config}_{s_unicodeChar}" : $"{prefix}_{config}";
+
}
}
diff --git a/src/tasks/WasmBuildTasks/GetChromeVersions.cs b/src/tasks/WasmBuildTasks/GetChromeVersions.cs
index 2adad0d091994f..c01fa41c4a99eb 100644
--- a/src/tasks/WasmBuildTasks/GetChromeVersions.cs
+++ b/src/tasks/WasmBuildTasks/GetChromeVersions.cs
@@ -24,10 +24,6 @@ public class GetChromeVersions : MBU.Task
private const string s_depsUrlPrefix = $"https://omahaproxy.appspot.com/deps.json?version=";
private const int s_versionCheckThresholdDays = 1;
- // start at the branch position found in all.json, and try to
- // download chrome, and chromedriver. If not found, then try up to
- // s_numBranchPositionsToTry lower versions
- private const int s_numBranchPositionsToTry = 50;
private static readonly HttpClient s_httpClient = new();
public string Channel { get; set; } = "stable";
@@ -44,6 +40,11 @@ public class GetChromeVersions : MBU.Task
public int MaxMajorVersionsToCheck { get; set; } = 2;
+ // start at the branch position found in all.json, and try to
+ // download chrome, and chromedriver. If not found, then try up to
+ // MaxBranchPositionsToCheck lower versions
+ public int MaxBranchPositionsToCheck { get; set; } = 75;
+
[Output]
public string ChromeVersion { get; set; } = string.Empty;
[Output]
@@ -240,7 +241,7 @@ private async Task GetDownloadFileStreamAsync(string filename, string ur
string baseUrl = $"{s_snapshotBaseUrl}/{OSPrefix}";
int branchPosition = int.Parse(version.branch_base_position);
- for (int i = 0; i < s_numBranchPositionsToTry; i++)
+ for (int i = 0; i < MaxBranchPositionsToCheck; i++)
{
string branchUrl = $"{baseUrl}/{branchPosition}";
string url = $"{branchUrl}/REVISIONS";
diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_71375/Runtime_71375.cs b/src/tests/JIT/Regression/JitBlue/Runtime_71375/Runtime_71375.cs
index 32010de2f339af..49d19799532189 100644
--- a/src/tests/JIT/Regression/JitBlue/Runtime_71375/Runtime_71375.cs
+++ b/src/tests/JIT/Regression/JitBlue/Runtime_71375/Runtime_71375.cs
@@ -10,10 +10,8 @@ public class Runtime_71375
[Fact]
public static int TestEntryPoint()
{
- // At the time of writing this test, the calling convention for incoming vector parameters on
- // Windows ARM64 was broken, so only the fact that "Problem" compiled without asserts was
- // checked. If/once the above is fixed, this test should be changed to actually call "Problem".
- RuntimeHelpers.PrepareMethod(typeof(Runtime_71375).GetMethod("Problem").MethodHandle);
+ if (Problem())
+ return 101;
return 100;
}
@@ -26,4 +24,58 @@ public static bool Problem()
{
return VarArgs(0, 0, 0, 0, 0, 0, Vector128.AllBitsSet, __arglist()) != -1;
}
+
+ [Fact]
+ public static int TestEntryPoint2()
+ {
+ if (Case2())
+ return 101;
+ return 100;
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static int VarArgs2(int arg1, int arg2, int arg3, int arg4, int arg5, Vector128 vecArg, __arglist) => vecArg.GetElement(0);
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public static bool Case2()
+ {
+ // vector is not split: it is passed in registers x6, x7
+ return VarArgs2(0, 0, 0, 0, 0, Vector128.AllBitsSet, __arglist()) != -1;
+ }
+
+ [Fact]
+ public static int TestEntryPoint3()
+ {
+ if (Case3())
+ return 101;
+ return 100;
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static int VarArgs3(int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, Vector128 vecArg, __arglist) => vecArg.GetElement(0);
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public static bool Case3()
+ {
+ // vector is not split: it is passed entirely on the stack
+ return VarArgs3(0, 0, 0, 0, 0, 0, 0, Vector128.AllBitsSet, __arglist()) != -1;
+ }
+
+ [Fact]
+ public static int TestEntryPoint4()
+ {
+ if (Case4())
+ return 101;
+ return 100;
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static int VarArgs4(int arg1, object arg2, int arg3, object arg4, int arg5, object arg6, Vector128 splitArg, __arglist) => splitArg.GetElement(0);
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public static bool Case4()
+ {
+ // Spit the vector but also pass some object types so the GC needs to know about them.
+ return VarArgs4(0, new object(), 0, new object(), 0, new object(), Vector128.AllBitsSet, __arglist(new object(), 1, new object())) != -1;
+ }
}
diff --git a/src/tests/issues.targets b/src/tests/issues.targets
index 265fafc5d79edd..2e3de7b4e9ceff 100644
--- a/src/tests/issues.targets
+++ b/src/tests/issues.targets
@@ -63,6 +63,9 @@
https://github.com/dotnet/runtime/issues/57786
+
+ https://github.com/dotnet/runtime/issues/90580
+
CoreCLR does not implement the mono embedding API
@@ -72,6 +75,9 @@
https://github.com/dotnet/runtime/issues/89585
+
+ https://github.com/dotnet/runtime/issues/88586
+
diff --git a/src/tools/illink/src/linker/Linker.Steps/UnreachableBlocksOptimizer.cs b/src/tools/illink/src/linker/Linker.Steps/UnreachableBlocksOptimizer.cs
index e25eaf0b9b8e41..d9fd14c5c9a5ee 100644
--- a/src/tools/illink/src/linker/Linker.Steps/UnreachableBlocksOptimizer.cs
+++ b/src/tools/illink/src/linker/Linker.Steps/UnreachableBlocksOptimizer.cs
@@ -92,21 +92,39 @@ static bool IsMethodSupported (MethodDefinition method)
return true;
}
- static bool HasJumpIntoTargetRange (Collection instructions, int firstInstr, int lastInstr, Func? mapping = null)
+ static bool HasJumpIntoTargetRange (Collection instructions, int firstInstr, int lastInstr, Func? mapping = null)
{
foreach (var instr in instructions) {
switch (instr.OpCode.FlowControl) {
case FlowControl.Branch:
case FlowControl.Cond_Branch:
if (instr.Operand is Instruction target) {
- int index = mapping == null ? instructions.IndexOf (target) : mapping (target);
- if (index >= firstInstr && index <= lastInstr)
- return true;
+ if (mapping != null && mapping (target) is int index) {
+ if (index >= firstInstr && index <= lastInstr) {
+ return true;
+ }
+ }
+ else {
+ for (int i = firstInstr; i <= lastInstr; i++) {
+ if (instructions[i] == target) {
+ return true;
+ }
+ }
+ }
} else {
foreach (var rtarget in (Instruction[]) instr.Operand) {
- int index = mapping == null ? instructions.IndexOf (rtarget) : mapping (rtarget);
- if (index >= firstInstr && index <= lastInstr)
- return true;
+ if (mapping != null && mapping (rtarget) is int index) {
+ if (index >= firstInstr && index <= lastInstr) {
+ return true;
+ }
+ }
+ else {
+ for (int i = firstInstr; i <= lastInstr; i++) {
+ if (instructions[i] == rtarget) {
+ return true;
+ }
+ }
+ }
}
}
@@ -1175,6 +1193,15 @@ int GetInstructionIndex (Instruction instruction)
return idx;
}
+ int? TryGetInstructionIndex (Instruction instruction)
+ {
+ Debug.Assert (mapping != null);
+ if (mapping.TryGetValue (instruction, out int idx))
+ return idx;
+
+ return null;
+ }
+
bool GetOperandsConstantValues (int index, out object? left, out object? right)
{
Debug.Assert (FoldedInstructions != null);
@@ -1213,7 +1240,7 @@ static bool IsPairedStlocLdloc (Instruction first, Instruction second)
bool IsJumpTargetRange (int firstInstr, int lastInstr)
{
Debug.Assert (FoldedInstructions != null);
- return HasJumpIntoTargetRange (FoldedInstructions, firstInstr, lastInstr, GetInstructionIndex);
+ return HasJumpIntoTargetRange (FoldedInstructions, firstInstr, lastInstr, TryGetInstructionIndex);
}
}
diff --git a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/TestFrameworkTests.g.cs b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/TestFrameworkTests.g.cs
index 32b3fb3390cb82..744a6f3841ccc8 100644
--- a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/TestFrameworkTests.g.cs
+++ b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/TestFrameworkTests.g.cs
@@ -75,6 +75,12 @@ public Task CanVerifyInterfacesOnTypesInAssembly ()
return RunTest (allowMissingWarnings: true);
}
+ [Fact]
+ public Task ILVerificationWorks ()
+ {
+ return RunTest (allowMissingWarnings: true);
+ }
+
[Fact]
public Task VerifyAttributesInAssemblyWorks ()
{
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Assertions/DisableILVerifyDiffingAttribute.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Assertions/DisableILVerifyDiffingAttribute.cs
new file mode 100644
index 00000000000000..9e6d7e53cfe12e
--- /dev/null
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Assertions/DisableILVerifyDiffingAttribute.cs
@@ -0,0 +1,17 @@
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+///
+/// This attribute is used to disable removing il verification errors that appear in the input assembly from the output verification results.
+///
+/// The original motivation for this is to make it easier to write a test that mostly verifies that the test frameworks ability to check il is working
+/// correctly.
+///
+[AttributeUsage (AttributeTargets.Class)]
+public class DisableILVerifyDiffingAttribute : BaseExpectedLinkedBehaviorAttribute
+{
+}
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectILFailureAttribute.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectILFailureAttribute.cs
new file mode 100644
index 00000000000000..597023deb453d3
--- /dev/null
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectILFailureAttribute.cs
@@ -0,0 +1,14 @@
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+[AttributeUsage (AttributeTargets.Class, AllowMultiple = true)]
+public class ExpectILFailureAttribute : BaseExpectedLinkedBehaviorAttribute
+{
+ public ExpectILFailureAttribute (params string[] messageContains)
+ {
+ }
+}
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Assertions/SkipPeVerifyAttribute.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Assertions/SkipILVerifyAttribute.cs
similarity index 55%
rename from src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Assertions/SkipPeVerifyAttribute.cs
rename to src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Assertions/SkipILVerifyAttribute.cs
index 5b293eacdd349d..dc02ecea033900 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Assertions/SkipPeVerifyAttribute.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Assertions/SkipILVerifyAttribute.cs
@@ -5,24 +5,14 @@
namespace Mono.Linker.Tests.Cases.Expectations.Assertions
{
-
- public enum SkipPeVerifyForToolchian
- {
- Pedump
- }
-
[AttributeUsage (AttributeTargets.Class, AllowMultiple = true)]
- public class SkipPeVerifyAttribute : BaseExpectedLinkedBehaviorAttribute
+ public class SkipILVerifyAttribute : BaseExpectedLinkedBehaviorAttribute
{
- public SkipPeVerifyAttribute ()
- {
- }
-
- public SkipPeVerifyAttribute (SkipPeVerifyForToolchian toolchain)
+ public SkipILVerifyAttribute ()
{
}
- public SkipPeVerifyAttribute (string assemblyName)
+ public SkipILVerifyAttribute (string assemblyName)
{
}
}
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTarget.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTarget.cs
index 8e59a832c62178..ff3d0937d56137 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTarget.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTarget.cs
@@ -14,9 +14,6 @@ namespace Mono.Linker.Tests.Cases.Attributes.Debugger.KeepDebugMembers
[SetupLinkerKeepDebugMembers ("true")]
#endif
- // Can be removed once this bug is fixed https://bugzilla.xamarin.com/show_bug.cgi?id=58168
- [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
-
[KeptMemberInAssembly (PlatformAssemblies.CoreLib, typeof (DebuggerDisplayAttribute), ".ctor(System.String)")]
[KeptMemberInAssembly (PlatformAssemblies.CoreLib, typeof (DebuggerDisplayAttribute), "set_Target(System.Type)")]
public class DebuggerDisplayAttributeOnAssemblyUsingTarget
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetOnUnusedType.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetOnUnusedType.cs
index fca51b2ca563da..acc464c6a8a6c4 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetOnUnusedType.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetOnUnusedType.cs
@@ -9,10 +9,6 @@
namespace Mono.Linker.Tests.Cases.Attributes.Debugger.KeepDebugMembers
{
[SetupLinkerTrimMode ("link")]
-
- // Can be removed once this bug is fixed https://bugzilla.xamarin.com/show_bug.cgi?id=58168
- [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
-
[KeptMemberInAssembly (PlatformAssemblies.CoreLib, typeof (DebuggerDisplayAttribute), ".ctor(System.String)")]
public class DebuggerDisplayAttributeOnAssemblyUsingTargetOnUnusedType
{
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly.cs
index a1708e30731206..083539d20107b7 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly.cs
@@ -13,9 +13,6 @@ namespace Mono.Linker.Tests.Cases.Attributes.Debugger.KeepDebugMembers
[SetupLinkerTrimMode ("link")]
[SetupCompileBefore ("library.dll", new[] { "../Dependencies/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly_Lib.cs" })]
- // Can be removed once this bug is fixed https://bugzilla.xamarin.com/show_bug.cgi?id=58168
- [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
-
[KeptMemberInAssembly (PlatformAssemblies.CoreLib, typeof (DebuggerDisplayAttribute), ".ctor(System.String)")]
[KeptMemberInAssembly (PlatformAssemblies.CoreLib, typeof (DebuggerDisplayAttribute), "set_TargetTypeName(System.String)")]
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInSameAssembly.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInSameAssembly.cs
index 342b768685f391..31a098588c05bf 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInSameAssembly.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInSameAssembly.cs
@@ -13,9 +13,6 @@ namespace Mono.Linker.Tests.Cases.Attributes.Debugger.KeepDebugMembers
[SetupLinkerKeepDebugMembers ("true")]
#endif
- // Can be removed once this bug is fixed https://bugzilla.xamarin.com/show_bug.cgi?id=58168
- [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
-
[KeptMemberInAssembly (PlatformAssemblies.CoreLib, typeof (DebuggerDisplayAttribute), ".ctor(System.String)")]
[KeptMemberInAssembly (PlatformAssemblies.CoreLib, typeof (DebuggerDisplayAttribute), "set_TargetTypeName(System.String)")]
public class DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInSameAssembly
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameOfGenericTypeInOtherAssembly.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameOfGenericTypeInOtherAssembly.cs
index 528965f5c0c199..db44758dbb2acf 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameOfGenericTypeInOtherAssembly.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameOfGenericTypeInOtherAssembly.cs
@@ -15,9 +15,6 @@ namespace Mono.Linker.Tests.Cases.Attributes.Debugger.KeepDebugMembers
#endif
[SetupCompileBefore ("library.dll", new[] { "../Dependencies/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly_Lib.cs" })]
- // Can be removed once this bug is fixed https://bugzilla.xamarin.com/show_bug.cgi?id=58168
- [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
-
[KeptMemberInAssembly (PlatformAssemblies.CoreLib, typeof (DebuggerDisplayAttribute), ".ctor(System.String)")]
[KeptMemberInAssembly (PlatformAssemblies.CoreLib, typeof (DebuggerDisplayAttribute), "set_TargetTypeName(System.String)")]
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameOfNestedTypeInOtherAssembly.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameOfNestedTypeInOtherAssembly.cs
index b7bf3b23f88c96..8dd7b6ba3bbc56 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameOfNestedTypeInOtherAssembly.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameOfNestedTypeInOtherAssembly.cs
@@ -12,9 +12,6 @@ namespace Mono.Linker.Tests.Cases.Attributes.Debugger.KeepDebugMembers
[SetupLinkerTrimMode ("link")]
[SetupCompileBefore ("library.dll", new[] { "../Dependencies/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly_Lib.cs" })]
- // Can be removed once this bug is fixed https://bugzilla.xamarin.com/show_bug.cgi?id=58168
- [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
-
[KeptMemberInAssembly (PlatformAssemblies.CoreLib, typeof (DebuggerDisplayAttribute), ".ctor(System.String)")]
[KeptMemberInAssembly (PlatformAssemblies.CoreLib, typeof (DebuggerDisplayAttribute), "set_TargetTypeName(System.String)")]
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnGenerics.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnGenerics.cs
index 2d99b155d8e336..1d54216ef879df 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnGenerics.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnGenerics.cs
@@ -3,8 +3,6 @@
namespace Mono.Linker.Tests.Cases.Attributes.Debugger.KeepDebugMembers
{
- // Can be removed once this bug is fixed https://bugzilla.xamarin.com/show_bug.cgi?id=58168
- [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
public class DebuggerDisplayAttributeOnGenerics
{
public static void Main ()
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnType.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnType.cs
index 5db37132917ac4..767a76cae9e9d0 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnType.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnType.cs
@@ -6,9 +6,6 @@
namespace Mono.Linker.Tests.Cases.Attributes.Debugger.KeepDebugMembers
{
[SetupLinkerTrimMode ("link")]
- // Can be removed once this bug is fixed https://bugzilla.xamarin.com/show_bug.cgi?id=58168
- [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
-
[KeptMemberInAssembly (PlatformAssemblies.CoreLib, typeof (DebuggerDisplayAttribute), ".ctor(System.String)")]
public class DebuggerDisplayAttributeOnType
{
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnTypeThatIsNotUsed.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnTypeThatIsNotUsed.cs
index 52525e60efbfe0..af5922ed8fe707 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnTypeThatIsNotUsed.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnTypeThatIsNotUsed.cs
@@ -8,8 +8,6 @@ namespace Mono.Linker.Tests.Cases.Attributes.Debugger.KeepDebugMembers
[SetupLinkerKeepDebugMembers ("true")]
#endif
- // Can be removed once this bug is fixed https://bugzilla.xamarin.com/show_bug.cgi?id=58168
- [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
public class DebuggerDisplayAttributeOnTypeThatIsNotUsed
{
public static void Main ()
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerTypeProxyAttributeOnAssemblyUsingTarget.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerTypeProxyAttributeOnAssemblyUsingTarget.cs
index d448bfe25c4c59..9d70568c04d038 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerTypeProxyAttributeOnAssemblyUsingTarget.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerTypeProxyAttributeOnAssemblyUsingTarget.cs
@@ -11,9 +11,6 @@ namespace Mono.Linker.Tests.Cases.Attributes.Debugger.KeepDebugMembers
{
[SetupLinkerTrimMode ("link")]
- // Can be removed once this bug is fixed https://bugzilla.xamarin.com/show_bug.cgi?id=58168
- [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
-
[KeptMemberInAssembly (PlatformAssemblies.CoreLib, typeof (DebuggerTypeProxyAttribute), ".ctor(System.Type)")]
[KeptMemberInAssembly (PlatformAssemblies.CoreLib, typeof (DebuggerTypeProxyAttribute), "set_Target(System.Type)")]
public class DebuggerTypeProxyAttributeOnAssemblyUsingTarget
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerTypeProxyAttributeOnType.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerTypeProxyAttributeOnType.cs
index bf815b4a372762..3c42d7b1c1518b 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerTypeProxyAttributeOnType.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerTypeProxyAttributeOnType.cs
@@ -6,9 +6,6 @@
namespace Mono.Linker.Tests.Cases.Attributes.Debugger.KeepDebugMembers
{
[SetupLinkerTrimMode ("link")]
- // Can be removed once this bug is fixed https://bugzilla.xamarin.com/show_bug.cgi?id=58168
- [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
-
[KeptMemberInAssembly (PlatformAssemblies.CoreLib, typeof (DebuggerTypeProxyAttribute), ".ctor(System.Type)")]
public class DebuggerTypeProxyAttributeOnType
{
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/AttributeOnAssemblyIsKeptIfDeclarationIsSkipped.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/AttributeOnAssemblyIsKeptIfDeclarationIsSkipped.cs
index ae0ec4137208d1..2291a9205c44b9 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/AttributeOnAssemblyIsKeptIfDeclarationIsSkipped.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/AttributeOnAssemblyIsKeptIfDeclarationIsSkipped.cs
@@ -8,7 +8,6 @@
namespace Mono.Linker.Tests.Cases.Attributes
{
- [SkipPeVerify]
[Define ("REFERENCE_INCLUDED")]
[SetupCompileBefore ("library.dll", new[] { "Dependencies/AttributeDefinedInReference.cs" })]
[SetupLinkerAction ("skip", "library")]
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/CoreLibraryAssemblyAttributesAreKept.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/CoreLibraryAssemblyAttributesAreKept.cs
index 4d702150ae6f79..e4d0bf419cc3d0 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/CoreLibraryAssemblyAttributesAreKept.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/CoreLibraryAssemblyAttributesAreKept.cs
@@ -17,7 +17,6 @@ namespace Mono.Linker.Tests.Cases.Attributes
[KeptAttributeInAssembly ("System.dll", typeof (AssemblyDescriptionAttribute))]
[KeptAttributeInAssembly ("System.dll", typeof (AssemblyCompanyAttribute))]
#endif
- [SkipPeVerify]
public class CoreLibraryAssemblyAttributesAreKept
{
public static void Main ()
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/FixedLengthArrayAttributesArePreserved.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/FixedLengthArrayAttributesArePreserved.cs
index f7d6e368213c35..e45db5de703df1 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/FixedLengthArrayAttributesArePreserved.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/FixedLengthArrayAttributesArePreserved.cs
@@ -8,8 +8,6 @@ namespace Mono.Linker.Tests.Cases.Attributes
/// The purpose of this test is mainly to provide coverage on the `KeptAttributeOnFixedBufferType` attribute
///
[SetupCompileArgument ("/unsafe")]
- // Can't verify because the test contains unsafe code
- [SkipPeVerify]
public class FixedLengthArrayAttributesArePreserved
{
public static void Main ()
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/MarshalAsCustomMarshalerInterface.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/MarshalAsCustomMarshalerInterface.cs
index 0434d0bf257944..8cadd7144fb38a 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/MarshalAsCustomMarshalerInterface.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/MarshalAsCustomMarshalerInterface.cs
@@ -6,8 +6,6 @@
namespace Mono.Linker.Tests.Cases.Attributes
{
[SetupLinkerTrimMode ("link")]
- [SkipPeVerify]
-
[KeptInterface (typeof (IUserData))]
public class MarshalAsCustomMarshalerInterface : IUserData
{
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/NoSecurity/CoreLibrarySecurityAttributeTypesAreRemoved.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/NoSecurity/CoreLibrarySecurityAttributeTypesAreRemoved.cs
index 2644b5dbb5f9d4..9d6c78d48d2f02 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/NoSecurity/CoreLibrarySecurityAttributeTypesAreRemoved.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/NoSecurity/CoreLibrarySecurityAttributeTypesAreRemoved.cs
@@ -27,15 +27,6 @@ namespace Mono.Linker.Tests.Cases.Attributes.NoSecurity
[RemovedTypeInAssembly (PlatformAssemblies.CoreLib, typeof (SecurityCriticalAttribute))]
[RemovedTypeInAssembly (PlatformAssemblies.CoreLib, typeof (SecuritySafeCriticalAttribute))]
[RemovedTypeInAssembly (PlatformAssemblies.CoreLib, typeof (SuppressUnmanagedCodeSecurityAttribute))]
-
- // Fails with `Runtime critical type System.Reflection.CustomAttributeData not found` which is a known short coming
- [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
- [SkipPeVerify ("System.dll")]
-
- // System.Core.dll is referenced by System.dll in the .NET FW class libraries. Our GetType reflection marking code
- // detects a GetType("SHA256CryptoServiceProvider") in System.dll, which then causes a type in System.Core.dll to be marked.
- // PeVerify fails on the original GAC copy of System.Core.dll so it's expected that it will also fail on the stripped version we output
- [SkipPeVerify ("System.Core.dll")]
public class CoreLibrarySecurityAttributeTypesAreRemoved
{
public static void Main ()
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CanLinkCoreLibrariesWithOnlyKeepUsedAttributes.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CanLinkCoreLibrariesWithOnlyKeepUsedAttributes.cs
index 6ac763c8dd4ab1..1bc8fe24015c32 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CanLinkCoreLibrariesWithOnlyKeepUsedAttributes.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CanLinkCoreLibrariesWithOnlyKeepUsedAttributes.cs
@@ -7,17 +7,6 @@ namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed
[SetupLinkerTrimMode ("link")]
[SetupLinkerArgument ("--used-attrs-only", "true")]
[Reference ("System.dll")]
- // System.Core.dll is referenced by System.dll in the .NET FW class libraries. Our GetType reflection marking code
- // detects a GetType("SHA256CryptoServiceProvider") in System.dll, which then causes a type in System.Core.dll to be marked.
- // PeVerify fails on the original GAC copy of System.Core.dll so it's expected that it will also fail on the stripped version we output
- [SkipPeVerify ("System.Core.dll")]
- // Fails with `Runtime critical type System.Reflection.CustomAttributeData not found`
- [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
-#if !NETCOREAPP
- // .NET Framework System.dll doesn't pass peverify
- [SkipPeVerify ("System.dll")]
-#endif
-
class CanLinkCoreLibrariesWithOnlyKeepUsedAttributes
{
static void Main ()
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CoreLibraryUnusedAssemblyAttributesAreRemoved.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CoreLibraryUnusedAssemblyAttributesAreRemoved.cs
index aa3641808184d1..64e046ec77106d 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CoreLibraryUnusedAssemblyAttributesAreRemoved.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CoreLibraryUnusedAssemblyAttributesAreRemoved.cs
@@ -13,7 +13,6 @@ namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed
#if !NETCOREAPP
[RemovedAttributeInAssembly ("System.dll", typeof (AssemblyDescriptionAttribute))]
#endif
- [SkipPeVerify]
public class CoreLibraryUnusedAssemblyAttributesAreRemoved
{
public static void Main ()
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CoreLibraryUsedAssemblyAttributesAreKept.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CoreLibraryUsedAssemblyAttributesAreKept.cs
index 292e9fb9dc7cb0..bbbbe72db926d2 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CoreLibraryUsedAssemblyAttributesAreKept.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CoreLibraryUsedAssemblyAttributesAreKept.cs
@@ -13,7 +13,6 @@ namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed
#if !NETCOREAPP
[KeptAttributeInAssembly ("System.dll", typeof (AssemblyDescriptionAttribute))]
#endif
- [SkipPeVerify]
public class CoreLibraryUsedAssemblyAttributesAreKept
{
public static void Main ()
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/FixedLengthArrayAttributesArePreserved.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/FixedLengthArrayAttributesArePreserved.cs
index 16bfacea2c754d..86078ca1b6615f 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/FixedLengthArrayAttributesArePreserved.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/FixedLengthArrayAttributesArePreserved.cs
@@ -6,9 +6,6 @@ namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed
{
[SetupLinkerArgument ("--used-attrs-only", "true")]
[SetupCompileArgument ("/unsafe")]
-
- // Can't verify because the test contains unsafe code
- [SkipPeVerify]
public class FixedLengthArrayAttributesArePreserved
{
public static void Main ()
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/NullableOnConstraints.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/NullableOnConstraints.cs
index b5efaa7dbcae0b..47cdfc9c9dfa8e 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/NullableOnConstraints.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/NullableOnConstraints.cs
@@ -8,6 +8,7 @@ namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed
[SetupCSharpCompilerToUse ("csc")]
[SetupLinkerArgument ("--used-attrs-only", "true")]
[SetupLinkerTrimMode ("link")]
+ [IgnoreDescriptors (false)]
public class NullableOnConstraints
{
public static void Main ()
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeTypeOnMethodIsRemoved.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeTypeOnMethodIsRemoved.cs
index 4e30d17f4c9e7e..57e6a31f5f8496 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeTypeOnMethodIsRemoved.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeTypeOnMethodIsRemoved.cs
@@ -5,10 +5,6 @@
namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed
{
[SetupLinkerArgument ("--used-attrs-only", "true")]
- // System.Core.dll is referenced by System.dll in the .NET FW class libraries. Our GetType reflection marking code
- // detects a GetType("SHA256CryptoServiceProvider") in System.dll, which then causes a type in System.Core.dll to be marked.
- // PeVerify fails on the original GAC copy of System.Core.dll so it's expected that it will also fail on the stripped version we output
- [SkipPeVerify ("System.Core.dll")]
class UnusedAttributeTypeOnMethodIsRemoved
{
static void Main ()
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/CopyOfCoreLibrariesKeepsUnusedTypes.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/CopyOfCoreLibrariesKeepsUnusedTypes.cs
index 119d34c7acdee5..75f6934b3d0f17 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/CopyOfCoreLibrariesKeepsUnusedTypes.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/CopyOfCoreLibrariesKeepsUnusedTypes.cs
@@ -11,8 +11,6 @@ namespace Mono.Linker.Tests.Cases.CoreLink
[KeptAssembly (PlatformAssemblies.CoreLib)]
[KeptAllTypesAndMembersInAssembly (PlatformAssemblies.CoreLib)]
-
- [SkipPeVerify]
class CopyOfCoreLibrariesKeepsUnusedTypes
{
public static void Main ()
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/DelegateAndMulticastDelegateKeepInstantiatedReqs.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/DelegateAndMulticastDelegateKeepInstantiatedReqs.cs
index 86890e5cbf7251..476fd19ef7b76c 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/DelegateAndMulticastDelegateKeepInstantiatedReqs.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/DelegateAndMulticastDelegateKeepInstantiatedReqs.cs
@@ -9,7 +9,7 @@ namespace Mono.Linker.Tests.Cases.CoreLink
{
[TestCaseRequirements (TestRunCharacteristics.TargetingNetCore, "Only for .NET Core")]
///
- /// Delegate and is created from
+ /// Delegate and is created from
///
[SetupLinkerTrimMode ("link")]
[KeptBaseOnTypeInAssembly (PlatformAssemblies.CoreLib, typeof (MulticastDelegate), PlatformAssemblies.CoreLib, typeof (Delegate))]
@@ -22,9 +22,6 @@ namespace Mono.Linker.Tests.Cases.CoreLink
[KeptMemberInAssembly (PlatformAssemblies.CoreLib, typeof (Delegate), "Equals(System.Object)")]
[KeptInterfaceOnTypeInAssembly (PlatformAssemblies.CoreLib, typeof (Delegate), PlatformAssemblies.CoreLib, typeof (ICloneable))]
[KeptInterfaceOnTypeInAssembly (PlatformAssemblies.CoreLib, typeof (Delegate), PlatformAssemblies.CoreLib, typeof (ISerializable))]
-
- // Fails due to Runtime critical type System.Reflection.CustomAttributeData not found.
- [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
public class DelegateAndMulticastDelegateKeepInstantiatedReqs
{
public static void Main ()
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/InstantiatedStructWithOverridesFromObject.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/InstantiatedStructWithOverridesFromObject.cs
index 43834594527d2a..ab4fd54233669a 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/InstantiatedStructWithOverridesFromObject.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/InstantiatedStructWithOverridesFromObject.cs
@@ -4,8 +4,6 @@
namespace Mono.Linker.Tests.Cases.CoreLink
{
[SetupLinkerTrimMode ("link")]
- // Need to skip due to `Runtime critical type System.Reflection.CustomAttributeData not found` failure
- [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
public class InstantiatedStructWithOverridesFromObject
{
public static void Main ()
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/InstantiatedTypeWithOverridesFromObject.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/InstantiatedTypeWithOverridesFromObject.cs
index a810ab9a6db906..6ad2f04e41e591 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/InstantiatedTypeWithOverridesFromObject.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/InstantiatedTypeWithOverridesFromObject.cs
@@ -4,8 +4,6 @@
namespace Mono.Linker.Tests.Cases.CoreLink
{
[SetupLinkerTrimMode ("link")]
- // Need to skip due to `Runtime critical type System.Reflection.CustomAttributeData not found` failure
- [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
public class InstantiatedTypeWithOverridesFromObject
{
public static void Main ()
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/LinkingOfCoreLibrariesRemovesUnusedMethods.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/LinkingOfCoreLibrariesRemovesUnusedMethods.cs
index 5b0b2010c6d9ac..05a1dfe40c8ab3 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/LinkingOfCoreLibrariesRemovesUnusedMethods.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/LinkingOfCoreLibrariesRemovesUnusedMethods.cs
@@ -14,8 +14,6 @@ namespace Mono.Linker.Tests.Cases.CoreLink
// we known should be removed which will at least verify that the core library was processed
[RemovedMemberInAssembly (PlatformAssemblies.CoreLib, typeof (Stack), ".ctor(System.Collections.ICollection)")]
- // Can be removed once this bug is fixed https://bugzilla.xamarin.com/show_bug.cgi?id=58168
- [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
class LinkingOfCoreLibrariesRemovesUnusedMethods
{
public static void Main ()
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/LinkingOfCoreLibrariesRemovesUnusedTypes.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/LinkingOfCoreLibrariesRemovesUnusedTypes.cs
index fb1aab3bec5802..3620f78258139a 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/LinkingOfCoreLibrariesRemovesUnusedTypes.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/LinkingOfCoreLibrariesRemovesUnusedTypes.cs
@@ -17,17 +17,6 @@ namespace Mono.Linker.Tests.Cases.CoreLink
[KeptAssembly ("System.dll")]
[KeptTypeInAssembly ("System.dll", typeof (System.Collections.Generic.SortedList<,>))]
[RemovedTypeInAssembly ("System.dll", typeof (System.Collections.Generic.SortedDictionary<,>))]
-
- // Can be removed once this bug is fixed https://bugzilla.xamarin.com/show_bug.cgi?id=58168
- [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
-
- // All sorts of stuff is flagged as invalid even in the original System.dll and System.Configuration.dll for mono class libraries
- [SkipPeVerify ("System.dll")]
- [SkipPeVerify ("System.Configuration.dll")]
- // System.Core.dll is referenced by System.dll in the .NET FW class libraries. Our GetType reflection marking code
- // detects a GetType("SHA256CryptoServiceProvider") in System.dll, which then causes a type in System.Core.dll to be marked.
- // PeVerify fails on the original GAC copy of System.Core.dll so it's expected that it will also fail on the stripped version we output
- [SkipPeVerify ("System.Core.dll")]
class LinkingOfCoreLibrariesRemovesUnusedTypes
{
public static void Main ()
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/NeverInstantiatedTypeWithOverridesFromObject.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/NeverInstantiatedTypeWithOverridesFromObject.cs
index 3fbe05cd47ad07..d0778ae1413c3c 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/NeverInstantiatedTypeWithOverridesFromObject.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/NeverInstantiatedTypeWithOverridesFromObject.cs
@@ -4,8 +4,6 @@
namespace Mono.Linker.Tests.Cases.CoreLink
{
[SetupLinkerTrimMode ("link")]
- // Need to skip due to `Runtime critical type System.Reflection.CustomAttributeData not found` failure
- [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
public class NeverInstantiatedTypeWithOverridesFromObject
{
public static void Main ()
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/NoSecurityPlusOnlyKeepUsedRemovesAllSecurityAttributesFromCoreLibraries.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/NoSecurityPlusOnlyKeepUsedRemovesAllSecurityAttributesFromCoreLibraries.cs
index 6b0e4bf500693b..23d30072e8a2a9 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/NoSecurityPlusOnlyKeepUsedRemovesAllSecurityAttributesFromCoreLibraries.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/CoreLink/NoSecurityPlusOnlyKeepUsedRemovesAllSecurityAttributesFromCoreLibraries.cs
@@ -27,13 +27,6 @@ namespace Mono.Linker.Tests.Cases.CoreLink
[RemovedTypeInAssembly (PlatformAssemblies.CoreLib, typeof (SecurityRulesAttribute))]
[RemovedTypeInAssembly (PlatformAssemblies.CoreLib, typeof (AllowPartiallyTrustedCallersAttribute))]
[RemovedTypeInAssembly (PlatformAssemblies.CoreLib, typeof (UnverifiableCodeAttribute))]
- // Fails with `Runtime critical type System.Reflection.CustomAttributeData not found` which is a known short coming
- [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
- [SkipPeVerify ("System.dll")]
- // System.Core.dll is referenced by System.dll in the .NET FW class libraries. Our GetType reflection marking code
- // detects a GetType("SHA256CryptoServiceProvider") in System.dll, which then causes a type in System.Core.dll to be marked.
- // PeVerify fails on the original GAC copy of System.Core.dll so it's expected that it will also fail on the stripped version we output
- [SkipPeVerify ("System.Core.dll")]
public class NoSecurityPlusOnlyKeepUsedRemovesAllSecurityAttributesFromCoreLibraries
{
public static void Main ()
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/IReflectDataflow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/IReflectDataflow.cs
index 30320309207ff4..ea14e8b4f2867f 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/IReflectDataflow.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/IReflectDataflow.cs
@@ -8,9 +8,6 @@ namespace Mono.Linker.Tests.Cases.DataFlow
{
[IgnoreTestCase ("Ignore in NativeAOT, see https://github.com/dotnet/runtime/issues/82447", IgnoredBy = Tool.NativeAot)]
[KeptAttributeAttribute (typeof (IgnoreTestCaseAttribute), By = Tool.Trimmer)]
- // Hits what appears to be a bug in the tool
- // Could not initialize vtable of class(0x02000007) .MyReflect due to VTable setup of type Mono.Linker.Tests.Cases.DataFlow.IReflectDataflow+MyReflect failed assembly:/tmp/linker_tests/output/test.exe type:MyReflect member:(null)
- [SkipPeVerify]
[ExpectedNoWarnings]
class IReflectDataflow
{
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/UnresolvedMembers.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/UnresolvedMembers.cs
index 08658a8e3d8663..e32c8727f91e09 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/UnresolvedMembers.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/UnresolvedMembers.cs
@@ -14,7 +14,7 @@ namespace Mono.Linker.Tests.Cases.DataFlow
// So it doesn't produce any of these warnings - which is also correct, because the code at runtime would never get there
// it would fail to JIT/run anyway.
- [SkipPeVerify]
+ [SkipILVerify]
[SetupLinkerArgument ("--skip-unresolved", "true")]
[SetupCompileBefore ("UnresolvedLibrary.dll", new[] { "Dependencies/UnresolvedLibrary.cs" }, removeFromLinkerInput: true)]
[ExpectedNoWarnings]
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveFields.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveFields.cs
index 0b202c3e6df5a0..4811c039807080 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveFields.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveFields.cs
@@ -23,13 +23,6 @@ namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInsta
"Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/A",
"Bar()")]
[SetupLinkerDescriptorFile ("NoInstanceCtorAndTypePreserveFields.xml")]
-
- // pedump reports this is valid with the following error.
- //
- // Assertion at metadata.c:1073, condition `index < meta->heap_blob.size' not met
- //
- // Not worried about it since this is already a niche edge case. Let's just skip verify for pedump
- [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
public class NoInstanceCtorAndTypePreserveFields
{
public static void Main ()
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveFieldsWithInterfacesMarked.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveFieldsWithInterfacesMarked.cs
index 87ba0dafd88140..6664223f54dd48 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveFieldsWithInterfacesMarked.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveFieldsWithInterfacesMarked.cs
@@ -26,13 +26,6 @@ namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInsta
"Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/A",
"Bar()")]
[SetupLinkerDescriptorFile ("NoInstanceCtorAndTypePreserveFieldsWithInterfacesMarked.xml")]
-
- // pedump reports this is valid with the following error.
- //
- // Assertion at metadata.c:1073, condition `index < meta->heap_blob.size' not met
- //
- // Not worried about it since this is already a niche edge case. Let's just skip verify for pedump
- [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
public class NoInstanceCtorAndTypePreserveFieldsWithInterfacesMarked
{
public static void Main ()
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveNone.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveNone.cs
index 0f792df4d39bb0..1d365705416dab 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveNone.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveNone.cs
@@ -14,12 +14,6 @@ namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInsta
"library",
"Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/IBar")]
[SetupLinkerDescriptorFile ("NoInstanceCtorAndTypePreserveNone.xml")]
- // pedump reports this is valid with the following error.
- //
- // Assertion at metadata.c:1073, condition `index < meta->heap_blob.size' not met
- //
- // Not worried about it since this is already a niche edge case. Let's just skip verify for pedump
- [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
public class NoInstanceCtorAndTypePreserveNone
{
public static void Main ()
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/References/ReferencesAreRemovedWhenAllUsagesAreRemoved.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/References/ReferencesAreRemovedWhenAllUsagesAreRemoved.cs
index 045607bc983d50..ea3eaa854c917b 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/References/ReferencesAreRemovedWhenAllUsagesAreRemoved.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/References/ReferencesAreRemovedWhenAllUsagesAreRemoved.cs
@@ -15,12 +15,6 @@ namespace Mono.Linker.Tests.Cases.References
[Reference ("System.dll")]
[RemovedAssembly ("System.dll")]
[KeptReference (PlatformAssemblies.CoreLib)]
- // Can be removed once this bug is fixed https://bugzilla.xamarin.com/show_bug.cgi?id=58168
- [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
- // System.Core.dll is referenced by System.dll in the .NET FW class libraries. Our GetType reflection marking code
- // detects a GetType("SHA256CryptoServiceProvider") in System.dll, which then causes a type in System.Core.dll to be marked.
- // PeVerify fails on the original GAC copy of System.Core.dll so it's expected that it will also fail on the stripped version we output
- [SkipPeVerify ("System.Core.dll")]
class ReferencesAreRemovedWhenAllUsagesAreRemoved
{
public static void Main ()
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsNotProcessedIfNameDoesNotMatchAnAssembly.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsNotProcessedIfNameDoesNotMatchAnAssembly.cs
index 5d12ef547a66c5..8c053eb5ea5899 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsNotProcessedIfNameDoesNotMatchAnAssembly.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsNotProcessedIfNameDoesNotMatchAnAssembly.cs
@@ -5,7 +5,6 @@ namespace Mono.Linker.Tests.Cases.Resources
{
[IgnoreDescriptors (false)]
[SetupCompileResource ("Dependencies/EmbeddedLinkXmlFileIsNotProcessedIfNameDoesNotMatchAnAssembly.xml", "NotMatchingAnAssemblyName.xml")]
- [SkipPeVerify]
[KeptResource ("NotMatchingAnAssemblyName.xml")]
public class EmbeddedLinkXmlFileIsNotProcessedIfNameDoesNotMatchAnAssembly
{
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsNotProcessedWithIgnoreDescriptors.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsNotProcessedWithIgnoreDescriptors.cs
index d13122132f9026..5b537cb469b137 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsNotProcessedWithIgnoreDescriptors.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsNotProcessedWithIgnoreDescriptors.cs
@@ -7,7 +7,6 @@ namespace Mono.Linker.Tests.Cases.Resources
[StripDescriptors (false)]
[SetupCompileResource ("Dependencies/EmbeddedLinkXmlFileIsNotProcessedWithIgnoreDescriptors.xml", "ILLink.Descriptors.xml")]
- [SkipPeVerify]
[KeptResource ("ILLink.Descriptors.xml")]
public class EmbeddedLinkXmlFileIsNotProcessedWithIgnoreDescriptors
{
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsNotProcessedWithIgnoreDescriptorsAndRemoved.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsNotProcessedWithIgnoreDescriptorsAndRemoved.cs
index 942614ff2530b8..2658bab22afdef 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsNotProcessedWithIgnoreDescriptorsAndRemoved.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsNotProcessedWithIgnoreDescriptorsAndRemoved.cs
@@ -7,7 +7,6 @@ namespace Mono.Linker.Tests.Cases.Resources
[StripDescriptors (true)]
[SetupCompileResource ("Dependencies/EmbeddedLinkXmlFileIsNotProcessedWithIgnoreDescriptorsAndRemoved.xml", "ILLink.Descriptors.xml")]
- [SkipPeVerify]
[RemovedResourceInAssembly ("test.exe", "ILLink.Descriptors.xml")]
public class EmbeddedLinkXmlFileIsNotProcessedWithIgnoreDescriptorsAndRemoved
{
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsProcessed.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsProcessed.cs
index fbcf1ea7f51931..f27b7e7da24a22 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsProcessed.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsProcessed.cs
@@ -6,7 +6,6 @@ namespace Mono.Linker.Tests.Cases.Resources
[IgnoreDescriptors (false)]
[SetupCompileResource ("Dependencies/EmbeddedLinkXmlFileIsProcessed.xml", "ILLink.Descriptors.xml")]
- [SkipPeVerify]
public class EmbeddedLinkXmlFileIsProcessed
{
public static void Main ()
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsProcessedAndKept.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsProcessedAndKept.cs
index a49d9a733af1db..fe394876d5cc5c 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsProcessedAndKept.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsProcessedAndKept.cs
@@ -7,7 +7,6 @@ namespace Mono.Linker.Tests.Cases.Resources
[StripDescriptors (false)]
[SetupCompileResource ("Dependencies/EmbeddedLinkXmlFileIsProcessedAndKept.xml", "ILLink.Descriptors.xml")]
- [SkipPeVerify]
[KeptResource ("ILLink.Descriptors.xml")]
public class EmbeddedLinkXmlFileIsProcessedAndKept
{
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsProcessedIfNameMatchesAnAssembly.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsProcessedIfNameMatchesAnAssembly.cs
index 9d76f275b5b442..b917b72c45e2c8 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsProcessedIfNameMatchesAnAssembly.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsProcessedIfNameMatchesAnAssembly.cs
@@ -7,7 +7,6 @@ namespace Mono.Linker.Tests.Cases.Resources
// Rename the resource so that it matches the name of an assembly being processed.
[SetupCompileResource ("Dependencies/EmbeddedLinkXmlFileIsProcessedIfNameMatchesAnAssembly.xml", "test.xml")]
- [SkipPeVerify]
public class EmbeddedLinkXmlFileIsProcessedIfNameMatchesAnAssembly
{
public static void Main ()
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Resources/NonLinkerEmbeddedResourceHasNoImpact.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Resources/NonLinkerEmbeddedResourceHasNoImpact.cs
index 47fabadf8f8cbd..24a69b9be92d57 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Resources/NonLinkerEmbeddedResourceHasNoImpact.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Resources/NonLinkerEmbeddedResourceHasNoImpact.cs
@@ -6,7 +6,6 @@ namespace Mono.Linker.Tests.Cases.Resources
[IgnoreDescriptors (false)]
[SetupCompileResource ("Dependencies/NonLinkerEmbeddedResourceHasNoImpact.xml", "ILLink.Descriptors.xml")]
- [SkipPeVerify]
[KeptResource ("ILLink.Descriptors.xml")]
public class NonLinkerEmbeddedResourceHasNoImpact
{
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Substitutions/StubBodyUnsafe.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Substitutions/StubBodyUnsafe.cs
index 1848082798daf2..abadd1f256e600 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Substitutions/StubBodyUnsafe.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Substitutions/StubBodyUnsafe.cs
@@ -6,7 +6,6 @@ namespace Mono.Linker.Tests.Cases.Substitutions
{
[SetupLinkerSubstitutionFile ("StubBodyUnsafe.xml")]
[SetupCompileArgument ("/unsafe")]
- [SkipPeVerify]
public class StubBodyUnsafe
{
public static unsafe void Main ()
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/AssemblyWithInvalidIL.il b/src/tools/illink/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/AssemblyWithInvalidIL.il
new file mode 100644
index 00000000000000..8c4b5eb975e1db
--- /dev/null
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/AssemblyWithInvalidIL.il
@@ -0,0 +1,36 @@
+.assembly extern mscorlib
+{
+}
+
+.assembly ILAssembly
+{
+
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+
+.module ILAssembly.dll
+
+// =============== CLASS MEMBERS DECLARATION ===================
+
+.class public auto ansi beforefieldinit Mono.Linker.Tests.Cases.TestFramework.Dependencies.AssemblyWithInvalidIL
+ extends [mscorlib]System.Object
+{
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: ret
+ }
+
+ .method public hidebysig instance string
+ GiveMeAValue() cil managed
+ {
+ .maxstack 1
+ .locals init (string V_0)
+ IL_0000: ret
+ }
+
+}
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/TestFramework/ILVerificationWorks.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/TestFramework/ILVerificationWorks.cs
new file mode 100644
index 00000000000000..d89fbd4c45df8a
--- /dev/null
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/TestFramework/ILVerificationWorks.cs
@@ -0,0 +1,25 @@
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.TestFramework;
+
+[DisableILVerifyDiffing] // Needed to produce an il failure
+[ExpectILFailure ("Mono.Linker.Tests.Cases.TestFramework.Dependencies.AssemblyWithInvalidIL.GiveMeAValue()",
+ "ReturnMissing: Return value missing on the stack",
+ "Offset IL_0000")]
+[SetupLinkerArgument ("--skip-unresolved", "true")] // needed due to the mscorlib shim
+[Define ("IL_ASSEMBLY_AVAILABLE")]
+[SetupCompileBefore ("ILAssembly.dll", new[] { "Dependencies/AssemblyWithInvalidIL.il" })]
+[KeptMemberInAssembly ("ILAssembly.dll", "Mono.Linker.Tests.Cases.TestFramework.Dependencies.AssemblyWithInvalidIL", "GiveMeAValue()")]
+public class ILVerificationWorks
+{
+ public static void Main ()
+ {
+#if IL_ASSEMBLY_AVAILABLE
+ System.Console.WriteLine (new Mono.Linker.Tests.Cases.TestFramework.Dependencies.AssemblyWithInvalidIL ().GiveMeAValue ());
+#endif
+ }
+}
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/TypeForwarding/TypeForwardersModifiers.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/TypeForwarding/TypeForwardersModifiers.cs
index 55689eb490c784..d5201cede89b52 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/TypeForwarding/TypeForwardersModifiers.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/TypeForwarding/TypeForwardersModifiers.cs
@@ -16,9 +16,6 @@ namespace Mono.Linker.Tests.Cases.TypeForwarding
[RemovedAssembly ("TypeForwarderModifiersLibFwd.dll")]
[RemovedAssemblyReference ("TypeForwardersModifiersLib", "TypeForwarderModifiersLibFwd")]
-
- [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
-
class TypeForwardersModifiers
{
static void Main ()
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBlock/UninitializedLocals.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBlock/UninitializedLocals.cs
index d0404ce3ca4cb9..0506a5c1ce1e6c 100644
--- a/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBlock/UninitializedLocals.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBlock/UninitializedLocals.cs
@@ -9,7 +9,7 @@ namespace Mono.Linker.Tests.Cases.UnreachableBlock
[Define ("IL_ASSEMBLY_AVAILABLE")]
[SetupCompileBefore ("library.dll", new[] { "Dependencies/LocalsWithoutStore.il" })]
[SetupLinkerArgument ("--enable-opt", "ipconstprop")]
- [SkipPeVerify]
+ [ExpectILFailure ("Mono.Linker.Tests.Cases.UnreachableBlock.Dependencies.ClassA.Method_2() - ReturnEmpty: Stack must contain only the return value. - Offset IL_0005")]
public class UninitializedLocals
{
[ExpectedInstructionSequence (new[] {
diff --git a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ILVerification/Extensions.cs b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ILVerification/Extensions.cs
new file mode 100644
index 00000000000000..cfe99131c25ea5
--- /dev/null
+++ b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ILVerification/Extensions.cs
@@ -0,0 +1,71 @@
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Reflection.Metadata;
+using System.Text;
+
+namespace Mono.Linker.Tests.TestCasesRunner.ILVerification;
+
+public static class Extensions
+{
+ public static string GetMethodSignature (this MethodDefinitionHandle handler, MetadataReader metadataReader)
+ {
+ var method = metadataReader.GetMethodDefinition (handler);
+ var signatureProvider = new SignatureProvider ();
+ StringBuilder sb = new StringBuilder ();
+ var signature = method.DecodeSignature (signatureProvider, new object ());
+ sb.Append (metadataReader.GetString (method.Name));
+ sb.Append ("(");
+ int paramIndex = 0;
+ foreach (var typeName in signature.ParameterTypes) {
+ if (paramIndex > 0)
+ sb.Append (",");
+
+ sb.Append (typeName);
+
+ paramIndex++;
+ }
+
+ sb.Append (")");
+ return sb.ToString ();
+ }
+
+ public static string GetMethodDeclaringTypeFullName (this MethodDefinitionHandle handle, MetadataReader metadataReader)
+ {
+ var definition = metadataReader.GetMethodDefinition (handle);
+ var declaringType = definition.GetDeclaringType ();
+ return declaringType.GetTypeFullName (metadataReader);
+ }
+
+ public static string GetTypeFullName (this TypeDefinitionHandle handle, MetadataReader metadataReader)
+ {
+ var typeDefinition = metadataReader.GetTypeDefinition (handle);
+ var declaringType = typeDefinition.GetDeclaringType ();
+
+ var builder = new StringBuilder ();
+ if (!declaringType.IsNil) {
+ builder.Append (GetTypeFullName (declaringType, metadataReader))
+ .Append ("+")
+ .Append (metadataReader.GetString (typeDefinition.Name));
+ } else {
+ builder.Append (metadataReader.GetString (typeDefinition.Namespace))
+ .Append (".")
+ .Append (metadataReader.GetString (typeDefinition.Name));
+ }
+
+ return builder.ToString ();
+ }
+
+ public static string GetTypeFullName (this TypeReferenceHandle handle, MetadataReader metadataReader)
+ {
+ var typeReference = metadataReader.GetTypeReference (handle);
+
+ var builder = new StringBuilder ();
+ builder.Append (metadataReader.GetString (typeReference.Namespace))
+ .Append (".")
+ .Append (metadataReader.GetString (typeReference.Name));
+
+ return builder.ToString ();
+ }
+}
diff --git a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ILVerification/ILChecker.cs b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ILVerification/ILChecker.cs
new file mode 100644
index 00000000000000..50397b2c690dd8
--- /dev/null
+++ b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ILVerification/ILChecker.cs
@@ -0,0 +1,170 @@
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using ILVerify;
+using Mono.Cecil;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Extensions;
+using NUnit.Framework;
+
+namespace Mono.Linker.Tests.TestCasesRunner.ILVerification;
+
+public class ILChecker
+{
+ public virtual void Check (LinkedTestCaseResult linkResult, AssemblyDefinition original)
+ {
+ ProcessSkipAttributes (linkResult, original, out bool skipCheckEntirely, out HashSet assembliesToSkip);
+
+ if (skipCheckEntirely)
+ return;
+
+ using var outputVerifier = CreateILVerifier (linkResult.OutputAssemblyPath.Parent);
+ using var inputVerifier = CreateILVerifier (linkResult.InputAssemblyPath.Parent);
+
+ var failureMessages = new StringBuilder ();
+
+ foreach (var file in linkResult.OutputAssemblyPath.Parent.Files ()) {
+ if (assembliesToSkip.Contains (file.FileName))
+ continue;
+
+ if (!ShouldCheckAssembly (file))
+ continue;
+
+ var outputResults = outputVerifier.Verify (file);
+
+ if (outputResults.Length == 0)
+ continue;
+
+ if (!DisableILDiffing (linkResult, original)) {
+ var inputResults = inputVerifier.VerifyByName (file.FileNameWithoutExtension);
+
+ outputResults = Diff (outputResults, inputResults);
+
+ if (outputResults.Length == 0)
+ continue;
+ }
+
+ failureMessages.AppendLine ($"IL Verification failed for {file.FileName}:");
+ failureMessages.AppendLine ("-----------------------------");
+
+ foreach (var result in outputResults) {
+ failureMessages.AppendLine (result.GetErrorMessage ());
+ }
+
+ failureMessages.AppendLine ("-----------------------------");
+ }
+
+ var failures = failureMessages.ToString ();
+ var hasFailures = !string.IsNullOrEmpty (failures);
+
+ ProcessExpectILFailures (linkResult, original, out bool expectILFailures, out List expectedFailureMessages);
+
+ if (expectILFailures) {
+ if (expectedFailureMessages.Count == 0 && !hasFailures)
+ Assert.Fail ("Expected IL failures, but there were none");
+
+ foreach (var expectedFailureMessage in expectedFailureMessages) {
+ if (!failures.Contains (expectedFailureMessage)) {
+ Assert.Fail ($"Expected IL failure message '{expectedFailureMessage}' was not found in the actual IL failure messages:\n--------------------\n{failures}");
+ }
+ }
+ } else {
+ if (hasFailures)
+ Assert.Fail (failures);
+ }
+ }
+
+ private static bool DisableILDiffing (LinkedTestCaseResult linkResult, AssemblyDefinition original)
+ {
+ return linkResult.TestCase.FindTypeDefinition (original)
+ .CustomAttributes
+ .FirstOrDefault (attr => attr.AttributeType.Name == nameof(DisableILVerifyDiffingAttribute)) != null;
+ }
+
+ private static void ProcessExpectILFailures (LinkedTestCaseResult linkResult, AssemblyDefinition original, out bool expectILFailures, out List failureMessages)
+ {
+ var attrs = linkResult.TestCase.FindTypeDefinition (original).CustomAttributes.Where (attr => attr.AttributeType.Name == nameof(ExpectILFailureAttribute)).ToArray ();
+ expectILFailures = attrs.Length > 0;
+ failureMessages = new List ();
+ foreach (var attr in attrs) {
+ var expectedMessageContains = ((CustomAttributeArgument[]) attr.GetConstructorArgumentValue (0)).Select (a => (string) a.Value).ToArray ();
+ failureMessages.AddRange (expectedMessageContains);
+ }
+ }
+
+ private void ProcessSkipAttributes (LinkedTestCaseResult linkResult, AssemblyDefinition original, out bool skipCheckEntirely, out HashSet assembliesToSkip)
+ {
+ var attrs = linkResult.TestCase.FindTypeDefinition (original).CustomAttributes.Where (attr => attr.AttributeType.Name == nameof(SkipILVerifyAttribute));
+ skipCheckEntirely = false;
+ assembliesToSkip = new HashSet ();
+ foreach (var attr in attrs) {
+ var ctorArg = attr.ConstructorArguments.FirstOrDefault ();
+
+ if (!attr.HasConstructorArguments) {
+ skipCheckEntirely = true;
+ } else if (ctorArg.Type.Name == nameof(String)) {
+ assembliesToSkip.Add ((string) ctorArg.Value);
+ } else {
+ throw new ArgumentException ($"Unhandled constructor argument type of {ctorArg.Type} on {nameof(SkipILVerifyAttribute)}");
+ }
+ }
+ }
+
+ public static ILVerifierResult[] Diff (ILVerifierResult[] outputResults, ILVerifierResult[] inputResults)
+ {
+ var inputErrors = new HashSet ();
+
+ foreach (var inputResult in inputResults) {
+ inputErrors.Add (CreateKey (inputResult));
+ }
+
+ var newErrors = new List ();
+
+ foreach (var outputResult in outputResults) {
+ var key = CreateKey (outputResult);
+
+ // The error existed in the input assembly, filter it out
+ if (inputErrors.Contains (key))
+ continue;
+
+ newErrors.Add (outputResult);
+ }
+
+ return newErrors.ToArray ();
+ }
+
+ static ErrorKey CreateKey (ILVerifierResult result)
+ {
+ return new ErrorKey (result.Result.Code,
+ result.TypeFullName,
+ result.MethodSignature,
+ result.Result.ErrorArguments
+ .Aggregate (string.Empty, (accum, error) => $"{accum}, {KeyForArgument (error)}"));
+
+ static string KeyForArgument (ErrorArgument argument)
+ {
+ // Technically, tokens and offsets could change. If they did this would mess up the diffing.
+ // So far I haven't noticed this happening. I'm not sure what to do about this case so I'm not going to do anything for the time being
+ // we can revisit if it becomes a problem.
+ return $"{argument.Name} : {argument.Value}";
+ }
+ }
+
+ protected virtual ILVerifier CreateILVerifier (NPath directory)
+ {
+ return new ILVerifier (new []
+ {
+ directory,
+ typeof (object).Assembly.Location.ToNPath ().Parent
+ },"System.Private.CoreLib");
+ }
+
+
+ protected bool ShouldCheckAssembly (NPath file) => file.ExtensionWithDot == ".exe" || file.ExtensionWithDot == ".dll" || file.ExtensionWithDot == ".winmd";
+
+ public record class ErrorKey(VerifierError Code, string TypeFullName, string MethodName, string ErrorArguments);
+}
diff --git a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ILVerification/ILVerifier.cs b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ILVerification/ILVerifier.cs
new file mode 100644
index 00000000000000..37b6c8b50bb4b0
--- /dev/null
+++ b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ILVerification/ILVerifier.cs
@@ -0,0 +1,148 @@
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Reflection.Metadata;
+using System.Reflection.PortableExecutable;
+using ILVerify;
+using Mono.Linker.Tests.Extensions;
+using NUnit.Framework;
+
+namespace Mono.Linker.Tests.TestCasesRunner.ILVerification;
+
+#nullable enable
+public class ILVerifier : IResolver, IDisposable
+{
+ readonly Verifier _verifier;
+ readonly Dictionary _assemblyCache = new();
+ readonly NPath[] _searchDirectories;
+
+ public ILVerifier (NPath[] searchDirectories, string systemModuleName)
+ {
+ _searchDirectories = searchDirectories;
+
+ _verifier = new Verifier (
+ this,
+ new VerifierOptions {
+ SanityChecks = true,
+ IncludeMetadataTokensInErrorMessages = true
+ });
+
+ _verifier.SetSystemModuleName (new AssemblyName (systemModuleName));
+ }
+
+ public ILVerifierResult[] VerifyByName (string assemblyName)
+ {
+ var reader = Resolve (assemblyName);
+ if (reader == null) {
+ Assert.Fail ($"Failed to resolve : {assemblyName}");
+ }
+
+ return Verify (reader!);
+ }
+
+ public ILVerifierResult[] Verify (NPath assemblyPath) => Verify (LoadAssemblyFromPath (assemblyPath));
+
+ public ILVerifierResult[] Verify (PEReader reader)
+ {
+ var results = _verifier.Verify (reader);
+
+ var metadataReader = reader.GetMetadataReader ();
+
+ return FilterResults (results)
+ .Select (r => CreateResult (r, metadataReader))
+ .ToArray ();
+ }
+
+ private static ILVerifierResult CreateResult (VerificationResult r, MetadataReader metadataReader) =>
+ new(
+ r,
+ r.Type.IsNil
+ ? r.Method.GetMethodDeclaringTypeFullName (metadataReader)
+ : r.Type.GetTypeFullName (metadataReader),
+ r.Method.IsNil
+ ? string.Empty
+ : r.Method.GetMethodSignature (metadataReader));
+
+ protected virtual IEnumerable FilterResults (IEnumerable results)
+ {
+ return results.Where (r => r.Code switch {
+ VerifierError.None
+ // ex. localloc cannot be statically verified by ILVerify
+ or VerifierError.Unverifiable
+ // initlocals must be set for verifiable methods with one or more local variables - Lots of these in class libraries
+ or VerifierError.InitLocals
+ => false,
+ _ => true
+ });
+ }
+
+ PEReader LoadAssemblyFromPath (NPath pathToAssembly)
+ => LoadAssemblyFromPath (pathToAssembly.FileNameWithoutExtension, pathToAssembly);
+
+ PEReader LoadAssemblyFromPath (string assemblyName, NPath pathToAssembly)
+ {
+ if (_assemblyCache.TryGetValue (assemblyName, out PEReader? reader))
+ return reader;
+ reader = new PEReader (File.OpenRead (pathToAssembly));
+ _assemblyCache.Add (assemblyName, reader);
+ return reader;
+ }
+
+ bool TryLoadAssemblyFromFolder (string assemblyName, NPath folder, [NotNullWhen (true)] out PEReader? peReader)
+ {
+ NPath? assemblyPath = null;
+ foreach (var extension in PossibleAssemblyExtensions) {
+ var candidate = folder.Combine ($"{assemblyName}{extension}");
+ if (candidate.FileExists ()) {
+ assemblyPath = candidate;
+ break;
+ }
+ }
+
+ if (assemblyPath == null) {
+ peReader = null;
+ return false;
+ }
+
+ peReader = new PEReader (File.OpenRead (assemblyPath));
+ _assemblyCache.Add (assemblyName, peReader);
+ return true;
+ }
+
+ protected string[] PossibleAssemblyExtensions => new[] { ".dll", ".exe", ".winmd" };
+
+ PEReader? Resolve (string assemblyName)
+ {
+ PEReader? reader;
+ if (_assemblyCache.TryGetValue (assemblyName, out reader)) {
+ return reader;
+ }
+
+ foreach (var searchDirectory in _searchDirectories) {
+ if (TryLoadAssemblyFromFolder (assemblyName, searchDirectory, out reader))
+ return reader;
+ }
+
+ return null;
+ }
+
+ PEReader? IResolver.ResolveAssembly (AssemblyName assemblyName)
+ => Resolve (assemblyName.Name ?? assemblyName.FullName);
+
+ PEReader? IResolver.ResolveModule (AssemblyName referencingModule, string fileName)
+ => Resolve (Path.GetFileNameWithoutExtension (fileName));
+
+ public void Dispose ()
+ {
+ foreach (var reader in _assemblyCache.Values)
+ reader.Dispose ();
+ _assemblyCache.Clear ();
+ }
+}
+#nullable restore
diff --git a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ILVerification/ILVerifierResult.cs b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ILVerification/ILVerifierResult.cs
new file mode 100644
index 00000000000000..26081dd4733377
--- /dev/null
+++ b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ILVerification/ILVerifierResult.cs
@@ -0,0 +1,52 @@
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System.Text;
+using ILVerify;
+
+namespace Mono.Linker.Tests.TestCasesRunner.ILVerification;
+
+public class ILVerifierResult
+{
+ public readonly VerificationResult Result;
+ public readonly string TypeFullName;
+ public readonly string MethodSignature;
+
+ public ILVerifierResult (VerificationResult result, string typeFullName, string methodSignature)
+ {
+ Result = result;
+ TypeFullName = typeFullName;
+ MethodSignature = methodSignature;
+ }
+
+ public string GetErrorMessage ()
+ {
+ var sb = new StringBuilder ();
+ if (string.IsNullOrEmpty (MethodSignature))
+ sb.Append (TypeFullName);
+ else {
+ sb.Append (TypeFullName);
+ sb.Append (".");
+ sb.Append (MethodSignature);
+ }
+
+ sb.Append ($" - {Result.Code}: ");
+ sb.Append (Result.Message);
+ if (Result.ErrorArguments.Length > 0)
+ sb.Append (" - ");
+ foreach (var argument in Result.ErrorArguments) {
+ sb.Append (FormatArgument (argument));
+ }
+
+ return sb.ToString ();
+
+ static string FormatArgument (ErrorArgument argument)
+ {
+ if (argument.Name == "Token" && argument.Value is int token)
+ return $" {argument.Name} 0x{token:X8}";
+ if (argument.Name == "Offset" && argument.Value is int offset)
+ return $" {argument.Name} IL_{offset:X4}";
+ return $" {argument.Name} {argument.Value}";
+ }
+ }
+}
diff --git a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ILVerification/SignatureProvider.cs b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ILVerification/SignatureProvider.cs
new file mode 100644
index 00000000000000..1307fca590a4cb
--- /dev/null
+++ b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ILVerification/SignatureProvider.cs
@@ -0,0 +1,101 @@
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Collections.Immutable;
+using System.Reflection.Metadata;
+using System.Text;
+
+namespace Mono.Linker.Tests.TestCasesRunner.ILVerification;
+
+public class SignatureProvider : ISignatureTypeProvider
+{
+ public string GetPrimitiveType (PrimitiveTypeCode typeCode)
+ => typeCode switch {
+ PrimitiveTypeCode.Boolean => "bool",
+ PrimitiveTypeCode.Byte => "uint8",
+ PrimitiveTypeCode.Char => "char",
+ PrimitiveTypeCode.Double => "float64",
+ PrimitiveTypeCode.Int16 => "int16",
+ PrimitiveTypeCode.Int32 => "int32",
+ PrimitiveTypeCode.Int64 => "int64",
+ PrimitiveTypeCode.IntPtr => "native int",
+ PrimitiveTypeCode.Object => "object",
+ PrimitiveTypeCode.SByte => "int8",
+ PrimitiveTypeCode.Single => "float32",
+ PrimitiveTypeCode.String => "string",
+ PrimitiveTypeCode.TypedReference => "typedref",
+ PrimitiveTypeCode.UInt16 => "uint16",
+ PrimitiveTypeCode.UInt32 => "uint32",
+ PrimitiveTypeCode.UInt64 => "uint64",
+ PrimitiveTypeCode.UIntPtr => "native uint",
+ PrimitiveTypeCode.Void => "void",
+ _ => ""
+ };
+
+ public string GetTypeFromDefinition (MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind = 0)
+ => handle.GetTypeFullName (reader);
+
+ public string GetTypeFromReference (MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind = 0)
+ => handle.GetTypeFullName (reader);
+
+ public string GetTypeFromSpecification (MetadataReader reader, object genericContext, TypeSpecificationHandle handle, byte rawTypeKind = 0)
+ => throw new NotImplementedException ();
+
+ public string GetSZArrayType (string elementType)
+ => elementType + "[]";
+
+ public string GetPointerType (string elementType)
+ => elementType + "*";
+
+ public string GetByReferenceType (string elementType)
+ => elementType + "&";
+
+ public string GetGenericMethodParameter (object genericContext, int index)
+ => "!!" + index;
+
+ public string GetGenericTypeParameter (object genericContext, int index)
+ => "!" + index;
+
+ public string GetPinnedType (string elementType)
+ => elementType + " pinned";
+
+ public string GetGenericInstantiation (string genericType, ImmutableArray typeArguments)
+ => genericType + "<" + string.Join (",", typeArguments) + ">";
+
+ public string GetModifiedType (string modifierType, string unmodifiedType, bool isRequired)
+ => unmodifiedType + (isRequired ? " modreq(" : " modopt(") + modifierType + ")";
+
+ public string GetArrayType (string elementType, ArrayShape shape)
+ {
+ var builder = new StringBuilder ();
+
+ builder.Append (elementType);
+ builder.Append ('[');
+
+ for (int i = 0; i < shape.Rank; i++) {
+ int lowerBound = 0;
+
+ if (i < shape.LowerBounds.Length) {
+ lowerBound = shape.LowerBounds[i];
+ builder.Append (lowerBound);
+ }
+
+ builder.Append ("...");
+
+ if (i < shape.Sizes.Length) {
+ builder.Append (lowerBound + shape.Sizes[i] - 1);
+ }
+
+ if (i < shape.Rank - 1) {
+ builder.Append (',');
+ }
+ }
+
+ builder.Append (']');
+ return builder.ToString ();
+ }
+
+ public string GetFunctionPointerType (MethodSignature signature)
+ => $"{signature.ReturnType} *({string.Join (",", signature.ParameterTypes)})";
+}
diff --git a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/PeVerifier.cs b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/PeVerifier.cs
deleted file mode 100644
index aa3cd40e72133b..00000000000000
--- a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/PeVerifier.cs
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright (c) .NET Foundation and contributors. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Linq;
-using Mono.Cecil;
-using Mono.Linker.Tests.Cases.Expectations.Assertions;
-using Mono.Linker.Tests.Extensions;
-
-namespace Mono.Linker.Tests.TestCasesRunner
-{
- public class PeVerifier
- {
- private readonly string _peExecutable;
-
- public PeVerifier ()
- {
- }
-
- public PeVerifier (string peExecutable)
- {
- _peExecutable = peExecutable;
- }
-
- public virtual void Check (LinkedTestCaseResult linkResult, AssemblyDefinition original)
- {
- ProcessSkipAttributes (linkResult, original, out bool skipCheckEntirely, out HashSet assembliesToSkip);
-
- if (skipCheckEntirely)
- return;
-
- foreach (var file in linkResult.OutputAssemblyPath.Parent.Files ()) {
- if (file.ExtensionWithDot != ".exe" && file.ExtensionWithDot != ".dll")
- continue;
-
- // Always skip the I18N assemblies, for some reason they end up in the output directory on OSX.
- // verification of these fails due to native pointers
- if (file.FileName.StartsWith ("I18N"))
- continue;
-
- if (assembliesToSkip.Contains (file.FileName))
- continue;
-
- CheckAssembly (file);
- }
- }
-
- private void ProcessSkipAttributes (LinkedTestCaseResult linkResult, AssemblyDefinition original, out bool skipCheckEntirely, out HashSet assembliesToSkip)
- {
- var peVerifyAttrs = linkResult.TestCase.FindTypeDefinition (original).CustomAttributes.Where (attr => attr.AttributeType.Name == nameof (SkipPeVerifyAttribute));
- skipCheckEntirely = false;
- assembliesToSkip = new HashSet ();
- foreach (var attr in peVerifyAttrs) {
- var ctorArg = attr.ConstructorArguments.FirstOrDefault ();
-
- if (!attr.HasConstructorArguments) {
- skipCheckEntirely = true;
- } else if (ctorArg.Type.Name == nameof (SkipPeVerifyForToolchian)) {
- var skipToolchain = (SkipPeVerifyForToolchian) ctorArg.Value;
-
- if (skipToolchain == SkipPeVerifyForToolchian.Pedump) {
- if (Environment.OSVersion.Platform != PlatformID.Win32NT)
- skipCheckEntirely = true;
- } else
- throw new ArgumentException ($"Unhandled platform and toolchain values of {Environment.OSVersion.Platform} and {skipToolchain}");
- } else if (ctorArg.Type.Name == nameof (String)) {
- assembliesToSkip.Add ((string) ctorArg.Value);
- } else {
- throw new ArgumentException ($"Unhandled constructor argument type of {ctorArg.Type} on {nameof (SkipPeVerifyAttribute)}");
- }
- }
- }
-
- protected virtual void CheckAssembly (NPath assemblyPath)
- {
-#if NETCOREAPP
- // the PE Verifier does not know how to resolve .NET Core assemblies.
-#else
- var capturedOutput = new List ();
- var process = new Process ();
- SetupProcess (process, assemblyPath);
- process.StartInfo.RedirectStandardOutput = true;
- process.OutputDataReceived += (sender, args) => capturedOutput.Add (args.Data);
- process.Start ();
- process.BeginOutputReadLine ();
- process.WaitForExit ();
-
- if (process.ExitCode != 0) {
- Assert.Fail ($"Invalid IL detected in {assemblyPath}\n{capturedOutput.Aggregate ((buff, s) => buff + Environment.NewLine + s)}");
- }
-#endif
- }
-
- protected virtual void SetupProcess (Process process, NPath assemblyPath)
- {
- var exeArgs = Environment.OSVersion.Platform == PlatformID.Win32NT ? $"/nologo {assemblyPath.InQuotes ()}" : $"--verify metadata,code {assemblyPath.InQuotes ()}";
- process.StartInfo.FileName = _peExecutable;
- process.StartInfo.Arguments = exeArgs;
- process.StartInfo.UseShellExecute = false;
- process.StartInfo.CreateNoWindow = true;
- process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
-
- if (Environment.OSVersion.Platform != PlatformID.Win32NT) {
- process.StartInfo.Environment["MONO_PATH"] = assemblyPath.Parent.ToString ();
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs
index 641036229a215a..c5bfcd9efdb2b1 100644
--- a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs
+++ b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs
@@ -14,6 +14,7 @@
using Mono.Linker.Tests.Cases.Expectations.Assertions;
using Mono.Linker.Tests.Cases.Expectations.Metadata;
using Mono.Linker.Tests.Extensions;
+using Mono.Linker.Tests.TestCasesRunner.ILVerification;
using NUnit.Framework;
using WellKnownType = ILLink.Shared.TypeSystemProxy.WellKnownType;
@@ -25,11 +26,9 @@ public class ResultChecker
readonly BaseAssemblyResolver _linkedResolver;
readonly ReaderParameters _originalReaderParameters;
readonly ReaderParameters _linkedReaderParameters;
- readonly PeVerifier _peVerifier;
public ResultChecker ()
: this (new TestCaseAssemblyResolver (), new TestCaseAssemblyResolver (),
- new PeVerifier (),
new ReaderParameters {
SymbolReaderProvider = new DefaultSymbolReaderProvider (false)
},
@@ -40,24 +39,15 @@ public ResultChecker ()
}
public ResultChecker (BaseAssemblyResolver originalsResolver, BaseAssemblyResolver linkedResolver,
- PeVerifier peVerifier,
ReaderParameters originalReaderParameters, ReaderParameters linkedReaderParameters)
{
_originalsResolver = originalsResolver;
_linkedResolver = linkedResolver;
- _peVerifier = peVerifier;
_originalReaderParameters = originalReaderParameters;
_linkedReaderParameters = linkedReaderParameters;
}
- static void VerifyIL (NPath pathToAssembly, AssemblyDefinition linked)
- {
- using var verifier = new ILVerifier (pathToAssembly);
- foreach (var result in verifier.Results)
- Assert.Fail (ILVerifier.GetErrorMessage (result));
- }
-
- static void ValidateTypeRefsHaveValidAssemblyRefs (AssemblyDefinition linked)
+ protected static void ValidateTypeRefsHaveValidAssemblyRefs (AssemblyDefinition linked)
{
foreach (var typeRef in linked.MainModule.GetTypeReferences ()) {
switch (typeRef.Scope) {
@@ -89,22 +79,6 @@ static void ValidateTypeRefsHaveValidAssemblyRefs (AssemblyDefinition linked)
}
}
- static bool ShouldValidateIL (AssemblyDefinition inputAssembly)
- {
- if (HasAttribute (inputAssembly, nameof (SkipPeVerifyAttribute)))
- return false;
-
- var caaIsUnsafeFlag = (CustomAttributeArgument caa) =>
- caa.Type.IsTypeOf (WellKnownType.System_String)
- && (string) caa.Value == "/unsafe";
- var customAttributeHasUnsafeFlag = (CustomAttribute ca) => ca.ConstructorArguments.Any (caaIsUnsafeFlag);
- if (GetCustomAttributes (inputAssembly, nameof (SetupCompileArgumentAttribute))
- .Any (customAttributeHasUnsafeFlag))
- return false;
-
- return true;
- }
-
public virtual void Check (LinkedTestCaseResult linkResult)
{
InitializeResolvers (linkResult);
@@ -119,11 +93,6 @@ public virtual void Check (LinkedTestCaseResult linkResult)
var linked = ResolveLinkedAssembly (linkResult.OutputAssemblyPath.FileNameWithoutExtension);
- if (ShouldValidateIL (original)) {
- VerifyIL (linkResult.OutputAssemblyPath, linked);
- ValidateTypeRefsHaveValidAssemblyRefs (linked);
- }
-
InitialChecking (linkResult, original, linked);
PerformOutputAssemblyChecks (original, linkResult.OutputAssemblyPath.Parent);
@@ -164,6 +133,8 @@ void VerifyILOfOtherAssemblies (LinkedTestCaseResult linkResult)
}
}
+ protected virtual ILChecker CreateILChecker () => new ();
+
protected virtual AssemblyChecker CreateAssemblyChecker (AssemblyDefinition original, AssemblyDefinition linked, LinkedTestCaseResult linkedTestCase)
{
return new AssemblyChecker (original, linked, linkedTestCase);
@@ -308,7 +279,8 @@ protected virtual void AdditionalChecking (LinkedTestCaseResult linkResult, Asse
protected virtual void InitialChecking (LinkedTestCaseResult linkResult, AssemblyDefinition original, AssemblyDefinition linked)
{
- _peVerifier.Check (linkResult, original);
+ CreateILChecker ().Check(linkResult, original);
+ ValidateTypeRefsHaveValidAssemblyRefs (linked);
}
void VerifyLinkingOfOtherAssemblies (AssemblyDefinition original)